Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support mill init from an existing sbt project #4586

Open
wants to merge 73 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
ac22329
Initially copy and adapt some code to support `mill init` from an exi…
ShreckYe Feb 4, 2025
d2ad688
Add a cross module for the models and split the code because Mill use…
ShreckYe Feb 5, 2025
39f928e
Initially implement assembling and adding the `sbt-mill-init-generate…
ShreckYe Feb 6, 2025
3c9f155
Add code to add the sbt plugin and run the `millInitGenerateProjectTr…
ShreckYe Feb 6, 2025
923ddf4
Remove the files generated by sbt in "main/init/sbt/test/resources/sc…
ShreckYe Feb 6, 2025
268eb63
Replace "SBT"s with lowercase "sbt"
ShreckYe Feb 6, 2025
86e1807
Move the old "sbt-mill-init-generate-project-tree" Mill module and ru…
ShreckYe Feb 6, 2025
9991d8a
Remove unneeded code in the generated sbt plugin project and add µTes…
ShreckYe Feb 6, 2025
a253537
Move `ProjectTreePlugin` into the sbt project and set up the build lo…
ShreckYe Feb 7, 2025
01bfcf5
Initially complete implementing `SbtBuildGenMain` and the sbt plugin …
ShreckYe Feb 15, 2025
8b141aa
Remove the unnecessary code marked with TODOs to be removed in the pr…
ShreckYe Feb 15, 2025
1fd0b65
Do not diff a subproject's `BuildInfo` with `ThisBuild`'s anymore in …
ShreckYe Feb 16, 2025
f38991b
Move the "mill.scalalib.SbtModule" import into `SbtBuildGenMain` to f…
ShreckYe Feb 16, 2025
f70e818
Export and import sbt's `scalaVersion` too
ShreckYe Feb 16, 2025
7e1e2b6
Exclude the Scala Standard Libraries
ShreckYe Feb 16, 2025
6f4c45d
Add the https://github.com/pbassiner/sbt-multi-project-example projec…
ShreckYe Feb 16, 2025
913ef1d
Generate the expected snapshots for "sbt-multi-project-example" and i…
ShreckYe Feb 16, 2025
ac9d657
Generate the expected snapshots for "sbt-multi-project-example" with …
ShreckYe Feb 16, 2025
f8d748b
Set the settings in `ThisBuild` in "sbt-multi-project-example" so the…
ShreckYe Feb 16, 2025
4156577
Add POM settings in `ThisBuild` in "sbt-multi-project-example" to tes…
ShreckYe Feb 16, 2025
f0d1378
Stop updating the expected test sample snapshots
ShreckYe Feb 16, 2025
ea780d7
Copy and adapt the docs and some code for sbt from those for Gradle r…
ShreckYe Feb 16, 2025
b59e33f
Copy and adapt the integration tests for sbt from those for Gradle, r…
ShreckYe Feb 17, 2025
31154ac
Add a TODO
ShreckYe Feb 17, 2025
3d2fafe
Add the example tests, and add more and rearrange the integration tes…
ShreckYe Feb 18, 2025
44f6ada
Set up sbt in the CI to fix the failing CI tests
ShreckYe Feb 19, 2025
802f005
Move `setup-sbt` to `post-build-setup`
ShreckYe Feb 19, 2025
39baa2d
Refine a TODO
ShreckYe Feb 19, 2025
0c9b749
Merge branch 'main' into init-from-sbt
ShreckYe Feb 19, 2025
3db8288
Fix compiling and test issues after the merge
ShreckYe Feb 19, 2025
918359e
Split the `sbt assembly` command into a tuple, and replace `scala.sys…
ShreckYe Feb 19, 2025
4419d7f
Fix calling the sbt command in the `sbtPluginJarResources` Mill task …
ShreckYe Feb 19, 2025
68d830f
Get the `sbt millInitExportBuild` command to work on Windows with a w…
ShreckYe Feb 19, 2025
7155ec8
Fix a bug that the exported projects are ordered differently in diffe…
ShreckYe Feb 19, 2025
3ef1bef
Try fixing integration test timeout in the CI
ShreckYe Feb 20, 2025
1655bb9
Fix a compiling error introduced in the previous commit
ShreckYe Feb 20, 2025
6b717b7
Try fixing more integration test failures on CI, both on Linux with J…
ShreckYe Feb 20, 2025
018cd53
Fix the failing example tests added in commit 3d2fafed6a2cdcbce2f8c6c…
ShreckYe Feb 20, 2025
4112c6f
Run `./mill mill.scalalib.scalafmt.ScalafmtModule/reformatAll` since …
ShreckYe Feb 20, 2025
40cdaa3
Add one more exception in docs from the integration test failures fix…
ShreckYe Feb 20, 2025
3cfb3aa
Add `setup-sbt` in `autofix.ci` too as it fails without it
ShreckYe Feb 20, 2025
e66f8ee
Merge branch 'main' into init-from-sbt
ShreckYe Feb 20, 2025
7ed2c3a
Fix the merge
ShreckYe Feb 20, 2025
ee28377
Support converting child projects nested in a parent directory which …
ShreckYe Feb 22, 2025
88c31b1
Run more `compile` and `test` tasks in the submodules of part of the …
ShreckYe Feb 22, 2025
f533126
Reformat `GradleBuildGenMain.scala`
ShreckYe Feb 22, 2025
6e48c2b
[autofix.ci] apply automated fixes
autofix-ci[bot] Feb 22, 2025
2286ed0
Fix the integration tests failing on windows caused by `split('\n')`
ShreckYe Feb 22, 2025
768a2b1
Fix the bug the converted sbt test modules extend `MavenTests` instea…
ShreckYe Feb 23, 2025
cd168ff
Update (fix) an integration test accordingly
ShreckYe Feb 23, 2025
9ee23de
Try fixing Mill `test` in the converted project of `MillInitScalaCsv1…
ShreckYe Feb 23, 2025
87afa17
Move the `jvmId` config arg to `BasicConfig` and support it in `SbtBu…
ShreckYe Feb 23, 2025
02206a6
Support the `baseProject` config arg too in `SbtBuildGenMain` and upd…
ShreckYe Feb 23, 2025
c819207
Fix assertions in `MillInitSbtMultiProjectExampleTests` that fail due…
ShreckYe Feb 23, 2025
22033e9
Support comparing a module's `def`'s with and extending super base mo…
ShreckYe Feb 24, 2025
34b837d
Fix assertions in `MillInitSbtMultiProjectExampleTests` that fail due…
ShreckYe Feb 24, 2025
729fc9d
Fix bugs introduced in commit 22033e909dd461689b374815ca4602b087b8830…
ShreckYe Feb 24, 2025
f1bfd9a
Fix some grammar mistakes
ShreckYe Feb 24, 2025
af5454d
Rename some integration tests for explicitness and consistency
ShreckYe Feb 24, 2025
8794040
Update `MillInitSbtZioHttpTests` with the result and improve `testAll…
ShreckYe Feb 24, 2025
ca1c827
Support more `CrossVersion` types
ShreckYe Feb 24, 2025
1cd32b0
Fix a warning discovered by CI `lint-autofix`
ShreckYe Feb 24, 2025
d34d385
Fix a warning by making a def private
ShreckYe Feb 24, 2025
1d8011c
Supported converting `type, `classifier`, and `exclusions` in sbt dep…
ShreckYe Feb 24, 2025
12e9d73
Run more `compile` and `test` tasks in the submodules of all the conv…
ShreckYe Feb 25, 2025
2be0d80
Reformat "main/init/package.mill" as `lint-autofix` fails on CI
ShreckYe Feb 25, 2025
44c7381
Add a comment
ShreckYe Feb 25, 2025
8ca434a
Review the reasons why the tasks succeed or fail and improve comments…
ShreckYe Feb 25, 2025
75af776
Run more `compile` and `test` tasks in `MillInitSbtScalaCheckTests`
ShreckYe Feb 25, 2025
6cac44b
Merge branch 'main' into init-from-sbt
ShreckYe Feb 25, 2025
c2256f8
Reformat
ShreckYe Feb 25, 2025
10d2076
Add some `override`s following commit 57ab8e6218f5fab869e238037edfc8d…
ShreckYe Feb 25, 2025
d0d1e39
Update the expected test snapshots and fix the unit tests broken by t…
ShreckYe Feb 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/actions/post-build-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ runs:
name: ${{ inputs.os }}-selective-execution-artifact

- run: mv out/mill-selective-execution/mill-selective-execution.json out/mill-selective-execution.json
shell: bash
shell: bash

- uses: sbt/setup-sbt@v1
2 changes: 1 addition & 1 deletion .github/actions/pre-build-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,4 @@ runs:
- uses: actions/checkout@v4

- run: echo temurin:${{ inputs.java-version }} > .mill-jvm-version
shell: bash
shell: bash
2 changes: 2 additions & 0 deletions .github/workflows/autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: sbt/setup-sbt@v1

- run: |
./mill __.fix + mill.javalib.palantirformat.PalantirFormatModule/ + mill.scalalib.scalafmt.ScalafmtModule/ + mill.kotlinlib.ktlint.KtlintModule/
./mill --meta-level 1 mill.scalalib.scalafmt.ScalafmtModule/
Expand Down
19 changes: 13 additions & 6 deletions build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ object Deps {
// and then add to it `bridgeScalaVersions`
val scalaVersion = "3.6.2"
val scala2Version = "2.13.15"
// The Scala 2.12.x version
val scalaVersion212 = "2.12.20"
// The Scala 2.12.x version to use for some workers
val workerScalaVersion212 = "2.12.20"
val workerScalaVersion212 = scalaVersion212
val sbtScalaVersion212 = scalaVersion212

val testScala213Version = "2.13.15"
// Scala Native 4.2 will not get releases for new Scala version
Expand Down Expand Up @@ -194,7 +197,8 @@ object Deps {
val sourcecode = ivy"com.lihaoyi::sourcecode:0.4.3-M5"
val upickle = ivy"com.lihaoyi::upickle:4.1.0"
val windowsAnsi = ivy"io.github.alexarchambault.windows-ansi:windows-ansi:0.0.6"
val zinc = ivy"org.scala-sbt::zinc:1.10.7".withDottyCompat(scalaVersion)
val sbtVersion = "1.10.7"
val zinc = ivy"org.scala-sbt::zinc:$sbtVersion".withDottyCompat(scalaVersion)
// keep in sync with doc/antora/antory.yml
val bsp4j = ivy"ch.epfl.scala:bsp4j:2.2.0-M2"
val fansi = ivy"com.lihaoyi::fansi:0.5.0"
Expand All @@ -220,6 +224,7 @@ object Deps {
ivy"org.apache.maven.resolver:maven-resolver-transport-wagon:$mavenResolverVersion"
val coursierJvmIndexVersion = "0.0.4-84-f852c6"
val gradleApi = ivy"dev.gradleplugins:gradle-api:8.11.1"
val sbt = ivy"org.scala-sbt:sbt:$sbtVersion"

object RuntimeDeps {
val dokkaVersion = "2.0.0"
Expand Down Expand Up @@ -714,16 +719,18 @@ trait MillStableScalaModule extends MillPublishScalaModule with Mima {
}
}

trait MillPublishCrossScalaModule extends MillPublishJavaModule with CrossScalaModule

object bridge extends Cross[BridgeModule](compilerBridgeScalaVersions)
trait BridgeModule extends MillPublishJavaModule with CrossScalaModule {
trait BridgeModule extends MillPublishCrossScalaModule {
def scalaVersion = crossScalaVersion
def publishVersion = bridgeVersion
def artifactName = "mill-scala-compiler-bridge"
def pomSettings = commonPomSettings(artifactName())
def crossFullScalaVersion = true
def ivyDeps = Agg(
ivy"org.scala-sbt:compiler-interface:${Deps.zinc.version}",
ivy"org.scala-sbt:util-interface:${Deps.zinc.version}"
ivy"org.scala-sbt:compiler-interface:${Deps.sbtVersion}",
ivy"org.scala-sbt:util-interface:${Deps.sbtVersion}"
) ++ Agg(
if (ZincWorkerUtil.isScala3(crossScalaVersion))
ivy"org.scala-lang::scala3-compiler:${crossScalaVersion}"
Expand All @@ -738,7 +745,7 @@ trait BridgeModule extends MillPublishJavaModule with CrossScalaModule {
def compilerBridgeIvyDeps: T[Agg[Dep]] = Agg(
(if (ZincWorkerUtil.isScala3(crossScalaVersion))
ivy"org.scala-lang:scala3-sbt-bridge:${crossScalaVersion}"
else ivy"org.scala-sbt::compiler-bridge:${Deps.zinc.version}").exclude("*" -> "*")
else ivy"org.scala-sbt::compiler-bridge:${Deps.sbtVersion}").exclude("*" -> "*")
)

def compilerBridgeSourceJars: T[Agg[PathRef]] = Task {
Expand Down
1 change: 1 addition & 0 deletions dist/package.mill
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ object `package` extends RootModule with InstallModule {
build.main.graphviz.testDep(),
build.main.init.maven.testDep(),
build.main.init.gradle.testDep(),
build.main.init.sbt.testDep(),
build.scalalib.backgroundwrapper.testDep(),
build.contrib.bloop.testDep(),
build.contrib.buildinfo.testDep(),
Expand Down
1 change: 1 addition & 0 deletions example/package.mill
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ object `package` extends RootModule with Module {
object web extends Cross[ExampleCrossModule](build.listIn(millSourcePath / "web"))
object native extends Cross[ExampleCrossModule](build.listIn(millSourcePath / "native"))
object spark extends Cross[ExampleCrossModule](build.listIn(millSourcePath / "spark"))
object migrating extends Cross[ExampleCrossModule](build.listIn(millSourcePath / "migrating"))
}
object javascriptlib extends Module {
object basic extends Cross[ExampleCrossModule](build.listIn(millSourcePath / "basic"))
Expand Down
23 changes: 23 additions & 0 deletions example/scalalib/migrating/1-sbt-complete/build.mill
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/** Usage

> rm build.mill # remove any existing build file

> git init .
> git remote add -f origin https://github.com/scalacenter/library-example.git
> git checkout v1.0.1

> ./mill init
converting module library-example
Dependency Dependency(com.lightbend.paradox,paradox-theme-generic,false,0.4.4,Some(paradox-theme)) with an unknown configuration "paradox-theme" is dropped.
Dependency Dependency(com.lightbend.paradox,paradox-theme-generic,false,0.4.4,Some(paradox-theme)) with an unknown configuration "paradox-theme" is dropped.
generated 1 Mill build file(s)
removing existing Mill build files
writing Mill build file to build.mill
converted sbt build to Mill
formatting Mill build files
Formatting 1 Scala sources
init completed, run "mill resolve _" to list available tasks

> ./mill compile
done compiling
*/
25 changes: 25 additions & 0 deletions example/scalalib/migrating/2-sbt-incomplete/build.mill
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/** Usage

> rm build.mill # remove any existing build file

> git init .
> git remote add -f origin https://github.com/tototoshi/scala-csv.git
> git checkout 2.0.0

> ./mill init
converting sbt build
Running the added `millInitExportBuild` sbt task to export the build
converting module scala-csv
generated 1 Mill build file(s)
removing existing Mill build files
writing Mill build file to build.mill
converted sbt build to Mill
formatting Mill build files
Formatting 1 Scala sources
init completed, run "mill resolve _" to list available tasks

> ./mill compile # You will have to further configure the `CrossScalaModule` for different Scala versions
error: class CSVReader protected (private val lineReader: LineReader)(implicit format: CSVFormat) extends Closeable with CSVReaderCompat {
error: ^
error: one error found
*/
78 changes: 78 additions & 0 deletions integration/feature/init/src/IntegrationTesterExt.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package mill.integration

import mill.testkit.IntegrationTester
import utest.*

val defaultInitCommand =
Seq("init", "--base-module", "BaseModule", "--deps-object", "Deps", "--merge")

case class SplitResolvedTasks(successful: Seq[String], failed: Seq[String]) {
val all = (successful ++ failed).sorted
}

extension (tester: IntegrationTester)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets move this to a object InitUtils object with static methods

/**
* @param expectedCompileTasks [[ None ]] to denote that the `resolve __.compile` task fails
* @param expectedTestTasks [[ None ]] to denote that the `resolve __.test` task fails
* @return
*/
def testMillInit(
initCommand: Seq[String] = defaultInitCommand,
expectedInitResult: Boolean = true,
// expectedCompileResult: Boolean,
expectedCompileTasks: Option[SplitResolvedTasks],
expectedTestTasks: Option[SplitResolvedTasks]
) = {
import tester.*

val initResult = eval(initCommand, stdout = os.Inherit, stderr = os.Inherit)
assert(initResult.isSuccess == expectedInitResult)

/*
val compileResult = eval("compile")
assert(compileResult.isSuccess == expectedCompileResult)
*/

def testAllResolvedTasks(taskName: String, expected: Option[SplitResolvedTasks]) = {
val resolveAllTasksResult = eval(("resolve", s"__.$taskName"))
expected.fold(
assert(!resolveAllTasksResult.isSuccess)
)(expected => {
assert(resolveAllTasksResult.isSuccess)
val resolvedAllTasks = resolveAllTasksResult.out.linesIterator.toSeq.sorted
Predef.assert(
expected.all == resolvedAllTasks,
s"""
|expected: ${expected.all}
|resolved: $resolvedAllTasks
|""".stripMargin
)

for (task <- expected.successful)
Predef.assert(eval(task).isSuccess, s"task $task failed")

for (task <- expected.failed)
Predef.assert(!eval(task).isSuccess, s"task $task succeeded")
})
}

testAllResolvedTasks("compile", expectedCompileTasks)
testAllResolvedTasks("test", expectedTestTasks)
}

extension (module: String) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, let's use normal methods rather than extensions

def compileTask: String =
s"$module.compile"
private def testModuleOrTask: String =
s"$module.test"
def testTask: String =
testModuleOrTask
def testModule: String =
testModuleOrTask
def testCompileTask: String =
testModule.compileTask
def testTestTask: String =
testModule.testTask
def allCompileTasks: Seq[String] =
Seq(compileTask, testCompileTask)
}
Loading
Loading