Skip to main content

Publish ⚡️

caution

The Publish command is restricted and requires setting the --power option to be used. You can pass it explicitly or set it globally by running:

scala-cli config power true

caution

The publish sub-command is an experimental feature.

Please bear in mind that non-ideal user experience should be expected. If you encounter any bugs or have feedback to share, make sure to reach out to the maintenance team on GitHub.

The publish sub-command allows to publish Scala CLI projects to Maven repositories.

We recommend running the publish setup sub-command once prior to running publish, in order to set missing using directives for publishing, but this is not mandatory.

Required settings

scala-cli publish and scala-cli publish local might complain about missing settings. An organization, a name (or a module name), and (a way to compute) a version are needed, but Scala CLI may be able to compute sensible defaults for them.

We recommend setting the settings below via using directives rather than on the command-line, so that commands such as scala publish . or scala publish local . work fine for your project. Command-line options for those settings take over the using directive values, and are provided as a convenience.

This table lists settings allowing to specify those. See the sub-sections right after for more details.

using directiveCommand-line optionExample valuesNotes
Organizationpublish.organization--organizationorg.virtuslab.scala-cli
Namepublish.name--namescala-cli
Module Namepublish.moduleName--module-namescala-cli_3Module Name includes the Scala prefix, such as _2.13 or _3. Specifying Name should be favored over Module Name
Compute Versionpublish.computeVersion--compute-versiongit:tag
Versionpublish.version--version0.1.0, 0.1.1-SNAPSHOTAs much as possible, Compute Version (describing how to compute the version) should be favored over Version

Organization

If your Scala CLI project lives in a git repository having a GitHub remote, Scala CLI will infer an organization from it: if your project lives in GitHub organization foo (that is, lives somewhere under https://github.com/foo/), Scala CLI will use io.github.foo as default Maven organization.

To override this default value, set the publish.organization directive, like

//> using publish.organization io.github.foo

Name

Scala CLI will use the project directory name as default Maven name. That is, if your Scala CLI project lives in a directory named something, it will be published as something (pure Java project) or something_3 (Scala 3 project) for example.

To override this default value, set the publish.name directive, like

//> using publish.name something

Version

If your Scala CLI project lives in a git repository, Scala CLI will infer a way to compute versions from it: if the current commit has a tag v1.2.3, version 1.2.3 is assumed. Else, if it has such a tag earlier in the git history, version 1.2.4-SNAPSHOT is assumed.

To override this default value, set the publish.computeVersion directive, like

//> using publish.computeVersion git:tag

Please note that only tags that follow the semantic versioning are taken into consideration.

Values available for project version configuration are:

  • git:tag or git: use the latest stable git tag, if it is older than HEAD then try to increment it and add a suffix -SNAPSHOT, if no tag is available then use 0.1.0-SNAPSHOT
  • git:dynver: use the latest (stable or unstable) git tag, if it is older than HEAD then use the output of -{distance from last tag}-g{shortened version of HEAD commit hash}-SNAPSHOT, if no tag is available then use 0.1.0-SNAPSHOT

The difference between stable and unstable tags are, that the latter can contain letters, e.g. v0.1.0-RC1. It is also possible to specify the path to the repository, e.g. git:tag:../my-repo, git:dynver:../my-repo.

Repository settings

A repository is required for the publish command, and might need other settings to work fine (to pass credentials for example). See Repositories for more information.

When publishing from you CI, we recommend letting scala-cli publish setup setting those settings via using directives. When publishing from your local machine to Maven Central, we recommend setting the repository via a publish.repository directive, and keeping your Sonatype credentials in the Scala CLI settings, via commands such as

scala-cli config publish.credentials s01.oss.sonatype.org env:SONATYPE_USER env:SONATYPE_PASSWORD
using directiveCommand-line optionExample valuesNotes
Repositorypublish.repository--publish-repositorycentral, central-s01, github, https://artifacts.company.com/maven

Other settings

A number of metadata can be set either by using directives, or from the command-line. These metadata are optional in the publish local command, but might be mandatory for some repositories in the publish command, like Maven Central for non-snapshot versions.

We recommend setting the settings below via using directives rather than on the command-line, so that these don't have to be recalled for each scala-cli publish or scala-cli publish local invocation. Command-line options for those settings take over the using directive values, and are provided as a convenience.

using directiveCommand-line optionExample valuesNotes
Licensepublish.license--licenseApache-2.0, MIT, Foo:https://foo.com/license.txt, …Run scala-cli publish --license list to list pre-defined licenses
URLpublish.url--url
VCSpublish.vcs--vcsgithub:VirtusLab/scala-cli, https://github.com/VirtusLab/scala-cli.gitscm:git:github.com/VirtusLab/scala-cli.git
Developerspublish.developer--developeralexme|Alex Me|https://alex.meCan be specified multiple times, using directives and CLI values add up
Docspublish.doc--doc--doc=false, //> using doc falseUse to disable publishing docs jar.

Signing

Scala CLI can sign the artifacts it publishes with PGP signatures. Signing in Scala CLI can be handled by either

A signing mechanism will be chosen based on options and directives specified, it can also be overriden with --signer with one of the values:

  • bc - Bouncy Castle library will be used for signing, PGP secret key is required
  • gpg - a local gpg binary will be used for signing, GPG key ID is required
  • none - NO signing will take place

Bouncy Castle

Bouncy Castle library is the quickest way of signing artifacts with Scala CLI. A benefit of using it is that it has no external dependencies, Scala CLI is able to sign things with Bouncy Castle without further setup on your side. However, it does not provide a complex PGP handling functionality as e.g. GPG does.

When the --signer option is not specified Bouncy Castle library will be used for signing if one of these conditions occur:

  • the --secret-key option has been passed
  • target repository requires signing (e.g. central)

To succesfully use PGP signing with Bouncy Castle a PGP key pair is required. Scala CLI can generate and keep PGP keys for you by using:

scala-cli --power config --create-pgp-key --pgp-password MY_CHOSEN_PASSWORD

It's not mandatory, although recomended, to use a password to encrypt your keychains. To store the private keychain in an unencrypted form use --pgp-password none. To randomly generate a pasword, use --pgp-password random instead.

The generated values are kept in the config and will be used by default unless specified otherwise:

  • with directives:

    //> using publish.secretKey env:PGP_SECRET
    //> using publish.secretKeyPassword command:get_my_password
  • with options:

    scala-cli --power publish \
    --secret-key env:PGP_SECRET \
    --secret-key-password file:pgp_password.txt \

Since these values should be kept secret, the options and directives accept the format documented here.

GPG

Using GPG to sign artifacts requires the gpg binary to be installed on your system. A benefit of using gpg to sign artifacts over Bouncy Castle is: you can use keys from your GPG key ring, or from external devices that GPG may support.

To get started, consult the documentation on the library's website and be sure to read about Protecting code integrity with PGP guide from the Linux Foundation.

To enable signing with GPG, pass --gpg-key *key_id* on the command line or specify it with a using directive: //>using publish.gpgKey key_id. If needed, you can specify arguments meant to be passed to gpg, with --gpg-option or //>using publish.gpgOptions --opt1 --opt2, like

--gpg-key 1234567890ABCDEF --gpg-option --foo --gpg-option --bar

Checksums

Scala CLI can generate checksums of the artifacts it publishes.

By default, Scala CLI generates SHA-1 and MD5 checksums. To disable checksums, pass --checksum none. To generate checksum formats to generate, pass them via --checksum, separating the checksum values with , or using --checksum multiple times:

--checksum sha1,md5
--checksum sha1 --checksum md5

To list supported checksum types, pass --checksum list.

CI overrides

Scala CLI allows some publishing-related settings to have different values on your local machine and on CIs. In particular, this can be convenient to handle credentials and signing parameters, as these can be read from different locations on developers' machines and on CIs.

On CIs (when CI is set in the environment, whatever its value), the CI override is used if it's there. Else the main directive is used.

SettingsDirectiveCI override directive
Compute Versionpublish.computeVersionpublish.ci.computeVersion
Repositorypublish.repositorypublish.ci.repository
Repository Userpublish.userpublish.ci.user
Repository Passwordpublish.passwordpublish.ci.password
Repository Realmpublish.realmpublish.ci.realm
Secret Keypublish.secretKeypublish.ci.secretKey
Secret Key Passwordpublish.secretKeyPasswordpublish.ci.secretKeyPassword
GPG keypublish.gpgKeypublish.ci.gpgKey
GPG optionspublish.gpgOptionspublish.ci.gpgOptions

Repositories

Maven Central

Right now the easiest way to publish to Maven Central Repository is to use Sonatype repositories - s01.oss.sonatype.org or oss.sonatype.org Since 25.02.2021 s01 is the default server for new users, if your account is older than that you probably need to use the legacy oss.sonatype.org. More about this here.

Use central as repository to push artifacts to Maven Central via oss.sonatype.org. To push to it via s01.oss.sonatype.org, use central-s01.

When using central or central-s01 as repository, artifacts are pushed either to https://oss.sonatype.org/content/repositories/snapshots (versions ending in SNAPSHOT) or to https://oss.sonatype.org/staging/deploy/maven2 (in that case, Sonatype API endpoints are called to "close" and "release" artifacts, which later syncs them to https://repo1.maven.org/maven2).

GitHub Packages

Use github (GitHub organization and name computed from the git remotes) or github:org/name (replace org and name by the GitHub organization and name of your repository, like github:VirtusLab/scala-cli) to push artifacts to GitHub Packages.

Note that, as of writing this, this disables parallel uploading of artifacts, checksums, and signing (all not supported by GitHub Packages as of writing this).

Ivy2 Local

Use ivy2Local to put artifacts in the local Ivy2 repository, just like how publish local does.

Other pre-defined repositories

All pre-defined repositories accepted by coursier, such as jitpack or sonatype:snapshots, are accepted as repositories for publishing.

Generic Maven repositories

Pass a URL (beginning with http:// or https://) to push to custom HTTP servers. Pushing to such repositories relies on HTTP PUT requests (just like for the pre-defined repositories above).

You can also pass a path to a local directory, absolute (recommended) or relative (beware of name clashes with pre-defined repositories above).

Authentication

Specify publish repository authentication either on the command-line or via using directives. See user / password / realm in the settings table and the CI overrides.

Connection parameters configuration

When publishing large packages or when the internet connection is spotty one may use the following options to configure the connection parameters:

  • --connection-timeout-seconds - the connection timeout in seconds
  • --response-timeout-seconds - the response timeout in seconds
  • --connection-timeout-retries - the number of times to retry the connection on timeout

Publishing to Sonatype uses a staging repository which may sometimes cause problems when transitioning through states. If a publishing process fails with status 500 and message "Staging repository is already transitioning" you can try to tweak the following parameters taht are Sonatype specific:

  • --staging-repo-retries - the number of times to retry the staging repository transition
  • --staging-repo-wait-time-milis - the base time to wait between retries in milliseconds

Publishing

Once all the necessary settings are set, publish a Scala CLI project with a command such as this one:

scala-cli --power publish .

(. is for the Scala CLI project in the current directory)

Publishing io.github.scala-cli:hello-scala-cli_3:0.1.0-SNAPSHOT
✔ Computed 8 checksums
🚚 Wrote 12 files

👀 Check results at
https://s01.oss.sonatype.org/content/repositories/snapshots/io/github/scala-cli/hello-scala-cli_3/0.1.0-SNAPSHOT