Skip to content

Commit b9c8a60

Browse files
Merge pull request #13632 from dotty-staging/add-run-command-communitybuild
add run task to community build Main
2 parents 0bece40 + 1e44975 commit b9c8a60

File tree

3 files changed

+104
-87
lines changed

3 files changed

+104
-87
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package dotty.communitybuild
2+
3+
import java.nio.file._
4+
import java.io.{PrintWriter, File}
5+
import java.nio.charset.StandardCharsets.UTF_8
6+
7+
object CommunityBuildRunner:
8+
9+
/** Depending on the mode of operation, either
10+
* runs the test or updates the project. Updating
11+
* means that all the dependencies are fetched but
12+
* minimal other extra other work is done. Updating
13+
* is necessary since we run tests each time on a fresh
14+
* Docker container. We run the update on Docker container
15+
* creation time to create the cache of the dependencies
16+
* and avoid network overhead. See https://github.com/lampepfl/dotty-drone
17+
* for more infrastructural details.
18+
*/
19+
extension (self: CommunityProject) def run()(using suite: CommunityBuildRunner): Unit =
20+
if self.requiresExperimental && !compilerSupportExperimental then
21+
log(s"Skipping ${self.project} - it needs experimental features unsupported in this build.")
22+
return
23+
self.dependencies.foreach(_.publish())
24+
self.testOnlyDependencies().foreach(_.publish())
25+
suite.runProject(self)
26+
27+
trait CommunityBuildRunner:
28+
29+
/** fails the current operation, can be specialised in a concrete Runner
30+
* - overridden in `CommunityBuildTest`
31+
*/
32+
def failWith(msg: String): Nothing = throw IllegalStateException(msg)
33+
34+
/** Build the given project with the published local compiler and sbt plugin.
35+
*
36+
* This test reads the compiler version from community-build/dotty-bootstrapped.version
37+
* and expects community-build/sbt-dotty-sbt to set the compiler plugin.
38+
*
39+
* @param project The project name, should be a git submodule in community-build/
40+
* @param command The binary file of the program used to test the project – usually
41+
* a build tool like SBT or Mill
42+
* @param arguments Arguments to pass to the testing program
43+
*/
44+
def runProject(projectDef: CommunityProject): Unit =
45+
val project = projectDef.project
46+
val command = projectDef.binaryName
47+
val arguments = projectDef.buildCommands
48+
49+
@annotation.tailrec
50+
def execTimes(task: () => Int, timesToRerun: Int): Boolean =
51+
val exitCode = task()
52+
if exitCode == 0
53+
then true
54+
else if timesToRerun == 0
55+
then false
56+
else
57+
log(s"Rerunning tests in $project because of a previous run failure.")
58+
execTimes(task, timesToRerun - 1)
59+
60+
log(s"Building $project with dotty-bootstrapped $compilerVersion...")
61+
62+
val projectDir = communitybuildDir.resolve("community-projects").resolve(project)
63+
64+
if !Files.exists(projectDir.resolve(".git")) then
65+
failWith(s"""
66+
|
67+
|Missing $project submodule. You can initialize this module using
68+
|
69+
| git submodule update --init community-build/community-projects/$project
70+
|
71+
|""".stripMargin)
72+
73+
val testsCompletedSuccessfully = execTimes(projectDef.build, 3)
74+
75+
if !testsCompletedSuccessfully then
76+
failWith(s"""
77+
|
78+
|$command exited with an error code. To reproduce without JUnit, use:
79+
|
80+
| sbt community-build/prepareCommunityBuild
81+
| cd community-build/community-projects/$project
82+
| $command ${arguments.init.mkString(" ")} "${arguments.last}"
83+
|
84+
|For a faster feedback loop on SBT projects, one can try to extract a direct call to dotc
85+
|using the sbt export command. For instance, for scalacheck, use
86+
| sbt export jvm/test:compileIncremental
87+
|
88+
|""".stripMargin)
89+
end runProject
90+
91+
end CommunityBuildRunner

community-build/src/scala/dotty/communitybuild/Main.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import java.nio.file.Path
55
import java.nio.file.Files
66
import scala.sys.process._
77

8+
import CommunityBuildRunner.run
89

910
object Main:
1011

@@ -106,12 +107,15 @@ object Main:
106107
println(s"Documentation not found for ${failed.mkString(", ")}")
107108
sys.exit(1)
108109

110+
case "run" :: names if names.nonEmpty =>
111+
given CommunityBuildRunner()
112+
withProjects(names, "Running")(_.run())
113+
109114
case args =>
110115
println("USAGE: <COMMAND> <PROJECT NAME>")
111-
println("COMMAND is one of: publish doc run")
116+
println("COMMAND is one of: publish, build, doc, doc all, run")
112117
println("Available projects are:")
113118
allProjects.foreach { k =>
114119
println(s"\t${k.project}")
115120
}
116121
sys.exit(1)
117-

community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala

Lines changed: 7 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -7,93 +7,15 @@ import org.junit.{Ignore, Test}
77
import org.junit.Assert.{assertEquals, fail}
88
import org.junit.experimental.categories.Category
99

10-
abstract class CommunityBuildTest:
11-
given CommunityBuildTest = this
12-
13-
/** Depending on the mode of operation, either
14-
* runs the test or updates the project. Updating
15-
* means that all the dependencies are fetched but
16-
* minimal other extra other work is done. Updating
17-
* is necessary since we run tests each time on a fresh
18-
* Docker container. We run the update on Docker container
19-
* creation time to create the cache of the dependencies
20-
* and avoid network overhead. See https://github.com/lampepfl/dotty-drone
21-
* for more infrastructural details.
22-
*/
23-
extension (self: CommunityProject) def run()(using suite: CommunityBuildTest): Unit =
24-
if self.requiresExperimental && !compilerSupportExperimental then
25-
println(
26-
s"Skipping ${self.project} - it needs experimental features unsupported in this build."
27-
)
28-
return
29-
self.dependencies.foreach(_.publish())
30-
self.testOnlyDependencies().foreach(_.publish())
31-
suite.test(self)
32-
33-
/** Build the given project with the published local compiler and sbt plugin.
34-
*
35-
* This test reads the compiler version from community-build/dotty-bootstrapped.version
36-
* and expects community-build/sbt-dotty-sbt to set the compiler plugin.
37-
*
38-
* @param project The project name, should be a git submodule in community-build/
39-
* @param command The binary file of the program used to test the project – usually
40-
* a build tool like SBT or Mill
41-
* @param arguments Arguments to pass to the testing program
42-
*/
43-
def test(projectDef: CommunityProject): Unit = {
44-
val project = projectDef.project
45-
val command = projectDef.binaryName
46-
val arguments = projectDef.buildCommands
47-
48-
@annotation.tailrec
49-
def execTimes(task: () => Int, timesToRerun: Int): Boolean =
50-
val exitCode = task()
51-
if exitCode == 0
52-
then true
53-
else if timesToRerun == 0
54-
then false
55-
else
56-
log(s"Rerunning tests in $project because of a previous run failure.")
57-
execTimes(task, timesToRerun - 1)
58-
59-
log(s"Building $project with dotty-bootstrapped $compilerVersion...")
60-
61-
val projectDir = communitybuildDir.resolve("community-projects").resolve(project)
62-
63-
if (!Files.exists(projectDir.resolve(".git"))) {
64-
fail(s"""
65-
|
66-
|Missing $project submodule. You can initialize this module using
67-
|
68-
| git submodule update --init community-build/community-projects/$project
69-
|
70-
|""".stripMargin)
71-
}
72-
73-
val testsCompletedSuccessfully = execTimes(projectDef.build, 3)
74-
75-
if (!testsCompletedSuccessfully) {
76-
fail(s"""
77-
|
78-
|$command exited with an error code. To reproduce without JUnit, use:
79-
|
80-
| sbt community-build/prepareCommunityBuild
81-
| cd community-build/community-projects/$project
82-
| $command ${arguments.init.mkString(" ")} "${arguments.last}"
83-
|
84-
|For a faster feedback loop on SBT projects, one can try to extract a direct call to dotc
85-
|using the sbt export command. For instance, for scalacheck, use
86-
| sbt export jvm/test:compileIncremental
87-
|
88-
|""".stripMargin)
89-
}
90-
}
91-
end CommunityBuildTest
10+
import CommunityBuildRunner.run
9211

9312
class TestCategory
9413

14+
given testRunner: CommunityBuildRunner with
15+
override def failWith(msg: String) = { fail(msg); ??? }
16+
9517
@Category(Array(classOf[TestCategory]))
96-
class CommunityBuildTestA extends CommunityBuildTest:
18+
class CommunityBuildTestA:
9719
@Test def izumiReflect = projects.izumiReflect.run()
9820
@Test def scalaSTM = projects.scalaSTM.run()
9921
@Test def scalatest = projects.scalatest.run()
@@ -112,7 +34,7 @@ class CommunityBuildTestA extends CommunityBuildTest:
11234
end CommunityBuildTestA
11335

11436
@Category(Array(classOf[TestCategory]))
115-
class CommunityBuildTestB extends CommunityBuildTest:
37+
class CommunityBuildTestB:
11638
@Test def cats = projects.cats.run()
11739
@Test def catsEffect3 = projects.catsEffect3.run()
11840
@Test def catsMtl = projects.catsMtl.run()
@@ -132,7 +54,7 @@ class CommunityBuildTestB extends CommunityBuildTest:
13254
end CommunityBuildTestB
13355

13456
@Category(Array(classOf[TestCategory]))
135-
class CommunityBuildTestC extends CommunityBuildTest:
57+
class CommunityBuildTestC:
13658
@Test def akka = projects.akka.run()
13759
@Test def algebra = projects.algebra.run()
13860
@Test def betterfiles = projects.betterfiles.run()

0 commit comments

Comments
 (0)