Skip to content

Commit f9f243b

Browse files
lihaoyic0d33ngr
andauthored
Backport "Mill sonatype publishing doc" (com-lihaoyi#5107)
Backport of com-lihaoyi#4928 to 0.12.x --------- Co-authored-by: Jeffrey <[email protected]>
1 parent f422131 commit f9f243b

File tree

17 files changed

+260
-17
lines changed

17 files changed

+260
-17
lines changed

contrib/sonatypecentral/readme.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
= Sonatype Central
1+
= Sonatype Central (Plugin Moved to Scalalib)
22
:page-aliases: Plugin_Sonatype_Central.adoc
33

44
This plugin allows users to publish open-source packages to Maven Central via the Sonatype Central portal.

contrib/sonatypecentral/src/mill/contrib/sonatypecentral/package.scala

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/modules/ROOT/pages/extending/contrib-plugins.adoc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ include::partial$example/extending/imports/3-contrib-import.adoc[]
5050
* xref:contrib/proguard.adoc[]
5151
* xref:contrib/scalapblib.adoc[]
5252
* xref:contrib/scoverage.adoc[]
53-
* xref:contrib/sonatypecentral.adoc[]
5453
* xref:contrib/testng.adoc[]
5554
* xref:contrib/twirllib.adoc[]
5655
* xref:contrib/versionfile.adoc[]

docs/modules/ROOT/pages/javalib/publishing.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ include::partial$example/javalib/publishing/6-jpackage.adoc[]
3333

3434
include::partial$example/javalib/publishing/2-publish-module.adoc[]
3535

36+
== Publishing to Sonatype Maven Central
37+
38+
include::partial$example/javalib/publishing/9-publish-module-sonatype.adoc[]
39+
3640
== Checking API compatibility
3741

3842
Mill provides the ability to check API changes with the https://revapi.org/revapi-site/main/index.html[Revapi] analysis and change tracking tool.

docs/modules/ROOT/pages/kotlinlib/publishing.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ include::partial$example/kotlinlib/publishing/8-native-image-libs.adoc[]
2323

2424
include::partial$example/kotlinlib/publishing/2-publish-module.adoc[]
2525

26+
== Publishing to Sonatype Maven Central
27+
28+
include::partial$example/kotlinlib/publishing/3-publish-module-sonatype.adoc[]
29+
2630
include::partial$Publishing_Footer.adoc[]
2731

2832
== `jlink` and `jpackage`

docs/modules/ROOT/pages/scalalib/publishing.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ include::partial$example/scalalib/publishing/8-native-image-libs.adoc[]
2424

2525
include::partial$example/scalalib/publishing/2-publish-module.adoc[]
2626

27+
== Publlishing to Sonatype Maven Central
28+
29+
include::partial$example/scalalib/publishing/3-publish-module-sonatype.adoc[]
30+
2731
include::partial$Publishing_Footer.adoc[]
2832

2933
== `jlink` and `jpackage`

docs/modules/ROOT/partials/Publishing_Footer.adoc

Lines changed: 156 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
== Publishing to Sonatype Maven Central
1+
This example configured for publishing to Sonatype Maven Central via
2+
Central Portal. Extends `SonatypeCentralPublishModule` which provides
3+
simplified publishing tasks without requiring Nexus repository manager.
4+
5+
== Instructions for Publishing to Maven Central via Central Portal
26

37
Once you've mixed in `PublishModule`, apart from publishing locally, you can also publish
48
your project's modules to maven central
@@ -17,6 +21,14 @@ for publishing:
1721

1822
[source,bash]
1923
----
24+
# Sonatype Central Portal needs your public key to be uploaded so it can use for verification of artifacts from their end.
25+
#
26+
# Send your public key to ubuntu server so Sonatype Maven Central can use for verification of the artifacts
27+
gpg --keyserver keyserver.ubuntu.com --send-keys $LONG_ID
28+
#
29+
# Check the server for information about the public key. information will be displayed if found
30+
gpg --keyserver keyserver.ubuntu.com --recv-keys $LONG_ID
31+
#
2032
# The LHS and RHS of the User Token, accessible through the sonatype
2133
# website `Profile` / `User Token` / `Access User Token`
2234
export MILL_SONATYPE_USERNAME=...
@@ -44,6 +56,77 @@ export MILL_PGP_PASSPHRASE=...
4456

4557
=== Publishing
4658

59+
You can publish all eligible modules in your Mill project using
60+
`mill.scalalib.SonatypeCentralPublishModule/`:
61+
62+
[source,console]
63+
----
64+
> mill mill.scalalib.SonatypeCentralPublishModule/
65+
----
66+
67+
You can also specify individual modules you want to publish in two ways:
68+
69+
[source,console]
70+
----
71+
> mill foo.publishSonatypeCentral
72+
----
73+
74+
[source.console]
75+
----
76+
> mill mill.scalalib.SonatypeCentralPublishModule/ --publishArtifacts foo.publishArtifacts
77+
----
78+
79+
=== Publishing Using Github Actions
80+
81+
82+
To publish on Github Actions, you can use something like this:
83+
84+
```yaml
85+
# .github/workflows/publish-artifacts.yml
86+
name: Publish Artifacts
87+
on:
88+
push:
89+
tags:
90+
- '**'
91+
workflow_dispatch:
92+
jobs:
93+
publish-artifacts:
94+
runs-on: ubuntu-latest
95+
steps:
96+
- uses: actions/checkout@v3
97+
- uses: actions/setup-java@v3
98+
with:
99+
distribution: 'temurin'
100+
java-version: '17'
101+
- run: ./mill mill.scalalib.SonatypeCentralPublishModule/
102+
env:
103+
MILL_PGP_PASSPHRASE: ${{ secrets.MILL_PGP_PASSPHRASE }}
104+
MILL_PGP_SECRET_BASE64: ${{ secrets.MILL_PGP_SECRET_BASE64 }}
105+
MILL_SONATYPE_PASSWORD: ${{ secrets.MILL_SONATYPE_PASSWORD }}
106+
MILL_SONATYPE_USERNAME: ${{ secrets.MILL_SONATYPE_USERNAME }}
107+
```
108+
109+
Where `MILL_PGP_PASSPHRASE`, `MILL_PGP_SECRET_BASE64`, `MILL_SONATYPE_PASSWORD`, and
110+
`MILL_SONATYPE_USERNAME` configured for the repository's or organization's Github Actions
111+
workflows. See
112+
https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions[Using Secrets in Github Actions]
113+
for more details.
114+
115+
116+
== Instructions for Publishing to Maven Central via Legacy OSSHR (Deprecated)
117+
118+
[NOTE]
119+
--
120+
Publishing via the legacy OSSRH (OSS Repository Hosting) is deprecated and will reach end-of-life on June 30, 2025,
121+
due to the retirement of https://help.sonatype.com/en/sonatype-nexus-repository-2-sunsetting-information.html[Sonatype’s Nexus Repository Manager v2]. Sonatype now recommends using the https://central.sonatype.org/publish/publish-portal-guide/[Central Portal] for all new publishing.
122+
Migration is strongly encouraged to avoid disruptions. For full details, see the https://central.sonatype.org/news/20250326_ossrh_sunset/[OSSRH Sunset Announcement].
123+
--
124+
125+
Just like publishing via the Central Portal requires a GPG key and publish secrets,
126+
publishing via the legacy OSSHR(OSS Repository Hosting) also requires them.
127+
128+
=== Publishing
129+
47130
You can publish all eligible modules in your Mill project using
48131
the xref:fundamentals/modules.adoc#_default_tasks[default task] of the
49132
xref:fundamentals/modules.adoc#_external_modules[External Module] `mill.scalalib.PublishModule`:
@@ -141,6 +224,78 @@ mill mill.scalalib.PublishModule/ \
141224
----
142225

143226

227+
== `SonatypeCentralPublishModule` Configurations
228+
229+
This module provides settings and a CLI interface for publishing artifacts to Sonatype Maven Central.
230+
You can configure it through your `build.mill` file or by passing command-line options to it.
231+
232+
=== Module-Level Settings
233+
You can override default publishing settings in your build.mill like this:
234+
235+
[source,scala]
236+
----
237+
object mymodule extends SonatypeCentralPublishModule {
238+
override def sonatypeCentralGpgArgs: T[String] = "--batch, --yes, -a, -b"
239+
240+
override def sonatypeCentralConnectTimeout: T[Int] = 5000
241+
242+
override def sonatypeCentralReadTimeout: T[Int] = 60000
243+
244+
override def sonatypeCentralAwaitTimeout: T[Int] = 120 * 1000
245+
246+
override def sonatypeCentralShouldRelease: T[Boolean] = true
247+
...
248+
}
249+
----
250+
251+
=== Argument Reference
252+
253+
==== publishAll
254+
255+
The `publishAll` task can be called from the CLI. If a required value is not provided via the CLI option,
256+
it will fall back to an environment variable (if available) or raise an error if missing.
257+
258+
The `./mill mill.scalalib.SonatypeCentralPublishModule/publishAll` takes the following options:
259+
260+
`username`: The username for calling the Sonatype Central publishing api. Defaults to the `SONATYPE_USERNAME` environment variable if unset. If neither the parameter nor the environment variable are set, an error will be thrown. +
261+
262+
`password`: The password for calling the Sonatype Central publishing api. Defaults to the `SONATYPE_PASSWORD` environment variable if unset. If neither the parameter nor the environment variable are set, an error will be thrown. +
263+
264+
`gpgArgs`: Arguments to pass to the gpg package for signing artifacts. Uses the `MILL_PGP_PASSPHRASE` environment variable if set. _Default: `[--passphrase=$MILL_PGP_PASSPHRASE], --no-tty, --pinentry-mode, loopback, --batch, --yes, -a, -b`._ +
265+
266+
`publishArtifacts`: The command for generating all publishable artifacts (ex. `__.publishArtifacts`). Required. +
267+
268+
`readTimeout`: The timeout for receiving a response from Sonatype Central after the initial connection has occurred. _Default: 60000._ +
269+
270+
`awaitTimeout`: The overall timeout for all retries (including exponential backoff) of the bundle upload. _Default: 120 * 1000._ +
271+
272+
`connectTimeout`: The timeout for the initial connection to Sonatype Central if there is no response. _Default: 5000._ +
273+
274+
`shouldRelease`: Whether the bundle should be automatically released when uploaded to Sonatype Central. If `false`, the bundle will still be uploaded, but users will need to manually log in to Sonatype Central and publish the bundle from the portal. _Default: true_ +
275+
276+
`bundleName`: If set, all packages will be uploaded in a single bundle with the given name. If unset, packages will be uploaded separately. Recommended bundle name syntax: groupName-artifactId-versionNumber. As an example, if publishing the `com.lihaoyi` `requests` package, without the bundle name, four different bundles will be uploaded, one for each scala version supported. With a bundle name of `com.lihaoyi-requests-<new_version>`, a single bundle will be uploaded that contains all packages across scala versions. It is recommended to set the bundle name, so that packages can be verified and deployed together. _Default: No bundle name is set and packages will be uploaded separately_
277+
278+
==== Example command
279+
280+
----
281+
$ mill -i \
282+
mill.scalalib.SonatypeCentralPublishModule/publishAll \
283+
--username myusername \
284+
--password mypassword \
285+
--gpgArgs --passphrase=$MILL_PGP_PASSPHRASE,--no-tty,--pinentry-mode,loopback,--batch,--yes,-a,-b \
286+
--publishArtifacts __.publishArtifacts \
287+
--readTimeout 36000 \
288+
--awaitTimeout 36000 \
289+
--connectTimeout 36000 \
290+
--shouldRelease false \
291+
--bundleName com.lihaoyi-requests:1.0.0
292+
----
293+
294+
==== publishSonatypeCentral
295+
296+
The `__.publishSonatypeCentral` command takes the `username` and `password` arguments, documented above.
297+
298+
144299
== Publishing to other repositories
145300

146301
While Sonatype Maven Central is the default publish repository for JVM ecosystem projects,
@@ -149,4 +304,3 @@ there are also others that you can use. Mill supports these largely through cont
149304
* xref:contrib/codeartifact.adoc[]
150305
* xref:contrib/artifactory.adoc[]
151306
* xref:contrib/bintray.adoc[]
152-
* xref:contrib/sonatypecentral.adoc[]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//// SNIPPET:BUILD
2+
package build
3+
4+
import mill._, javalib._, publish._
5+
6+
import mill.scalalib.SonatypeCentralPublishModule
7+
8+
object foo extends JavaModule with SonatypeCentralPublishModule {
9+
def scalaVersion = "2.13.8"
10+
def publishVersion = "0.0.1"
11+
12+
def pomSettings = PomSettings(
13+
description = "Hello",
14+
organization = "com.lihaoyi",
15+
url = "https://github.com/lihaoyi/example",
16+
licenses = Seq(License.MIT),
17+
versionControl = VersionControl.github("lihaoyi", "example"),
18+
developers = Seq(Developer("lihaoyi", "Li Haoyi", "https://github.com/lihaoyi"))
19+
)
20+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package foo;
2+
3+
public class Foo {
4+
public static void main(String[] args) {
5+
System.out.println("Hello World");
6+
}
7+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//// SNIPPET:BUILD
2+
package build
3+
4+
import mill._, kotlinlib._, publish._
5+
6+
import mill.scalalib.SonatypeCentralPublishModule
7+
8+
object foo extends KotlinModule with SonatypeCentralPublishModule {
9+
def scalaVersion = "2.13.8"
10+
def publishVersion = "0.0.1"
11+
12+
def pomSettings = PomSettings(
13+
description = "Hello",
14+
organization = "com.lihaoyi",
15+
url = "https://github.com/lihaoyi/example",
16+
licenses = Seq(License.MIT),
17+
versionControl = VersionControl.github("lihaoyi", "example"),
18+
developers = Seq(Developer("lihaoyi", "Li Haoyi", "https://github.com/lihaoyi"))
19+
)
20+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package foo
2+
3+
fun main(args: Array<String>) = println("Hello World")
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// SNIPPET:BUILD
2+
package build
3+
import mill._, scalalib._, publish._
4+
5+
object foo extends ScalaModule with SonatypeCentralPublishModule {
6+
def scalaVersion = "2.13.8"
7+
def publishVersion = "0.0.1"
8+
9+
def pomSettings = PomSettings(
10+
description = "Hello",
11+
organization = "com.lihaoyi",
12+
url = "https://github.com/lihaoyi/example",
13+
licenses = Seq(License.MIT),
14+
versionControl = VersionControl.github("lihaoyi", "example"),
15+
developers = Seq(Developer("lihaoyi", "Li Haoyi", "https://github.com/lihaoyi"))
16+
)
17+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package foo
2+
object Foo {
3+
def main(args: Array[String]): Unit = {
4+
println("Hello World")
5+
}
6+
}

integration/ide/gen-idea/resources/hello-idea/idea/mill_modules/mill-build.iml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@
99
<orderEntry type="inheritedJdk"/>
1010
<orderEntry type="sourceFolder" forTests="false"/>
1111
<orderEntry type="library" name="scala-SDK-2.13.<!-- IGNORE -->" level="project"/>
12-
<!-- IGNORE -->
1312
</component>
1413
</module>

scalalib/package.mill

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import mill.contrib.buildinfo.BuildInfo
55
import scala.util.chaining._
66
object `package` extends RootModule with build.MillStableScalaModule {
77
def moduleDeps = Seq(build.main, build.scalalib.api, build.testrunner)
8-
def ivyDeps = Agg(build.Deps.scalafmtDynamic, build.Deps.scalaXml)
8+
def ivyDeps = Agg(
9+
build.Deps.scalafmtDynamic,
10+
build.Deps.scalaXml,
11+
build.Deps.sonatypeCentralClient
12+
)
913
def testIvyDeps = super.testIvyDeps() ++ Agg(build.Deps.TestDeps.scalaCheck)
1014
def testTransitiveDeps =
1115
super.testTransitiveDeps() ++ Seq(worker.testDep(), `classgraph-worker`.testDep())
Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
package mill.contrib.sonatypecentral
1+
package mill.scalalib
22

33
import com.lumidion.sonatype.central.client.core.{PublishingType, SonatypeCredentials}
44
import mill._
55
import scalalib._
66
import define.{ExternalModule, Task}
7-
import mill.api.Result
8-
import mill.contrib.sonatypecentral.SonatypeCentralPublishModule.{
7+
import mill.main.Tasks
8+
import mill.define.TaskModule
9+
import mill.api.{Result, experimental}
10+
import mill.scalalib.SonatypeCentralPublishModule.{
911
defaultAwaitTimeout,
1012
defaultConnectTimeout,
1113
defaultCredentials,
@@ -19,6 +21,7 @@ import mill.scalalib.publish.SonatypeHelpers.{
1921
USERNAME_ENV_VARIABLE_NAME
2022
}
2123

24+
@experimental
2225
trait SonatypeCentralPublishModule extends PublishModule {
2326
def sonatypeCentralGpgArgs: T[String] = Task {
2427
PublishModule.defaultGpgArgsForPassphrase(Task.env.get("MILL_PGP_PASSPHRASE")).mkString(",")
@@ -60,16 +63,20 @@ trait SonatypeCentralPublishModule extends PublishModule {
6063
}
6164
}
6265

63-
object SonatypeCentralPublishModule extends ExternalModule {
66+
object SonatypeCentralPublishModule extends ExternalModule with TaskModule {
6467

6568
val defaultCredentials: String = ""
6669
val defaultReadTimeout: Int = 60000
6770
val defaultConnectTimeout: Int = 5000
6871
val defaultAwaitTimeout: Int = 120 * 1000
6972
val defaultShouldRelease: Boolean = true
7073

74+
// Set the default command to "publishAll"
75+
def defaultCommandName(): String = "publishAll"
76+
7177
def publishAll(
72-
publishArtifacts: mill.main.Tasks[PublishModule.PublishData],
78+
publishArtifacts: Tasks[PublishModule.PublishData] =
79+
Tasks.resolveMainDefault("__.publishArtifacts"),
7380
username: String = defaultCredentials,
7481
password: String = defaultCredentials,
7582
shouldRelease: Boolean = defaultShouldRelease,
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package mill.contrib.sonatypecentral
1+
package mill.scalalib
22

33
import com.lumidion.sonatype.central.client.core.{
44
DeploymentName,

0 commit comments

Comments
 (0)