Configuration
December 2, 2025 ยท View on GitHub
Start here if you're setting up a repo use gha-scala-library-release-workflow! If your organisation has never used
gha-scala-library-release-workflow before, you'll need to follow the instructions in
Organisation Setup first.
The release workflow needs a release.yml GitHub workflow in your repo, and specific updated sbt settings.
Example GitHub pull requests making these changes can be found further below.
Repo settings
- Ensure your GitHub App has access to your repo. Guardian developers: Get an org-owner to click
Configureon the gu-scala-library-release app and grant access to the repo - usually just having admin permissions on the repo would be enough to reliably add your repo to the list of selected repositories, but as of December 2025, we've found that if a user does not have org-owner rights, adding repositories can actually unintentionally remove repos. - Guardian developers: Comply with the repository requirements of
guardian/github-secret-access, i.e. ensure the repository has aproductionTopic label.
Branch protection
Your GitHub App will need to push to directly to your default branch as part of the release, bypassing any branch protection. GitHub provides two different methods of branch protection:
- Branch protection rules - there is no mechanism to allow a GitHub App to bypass branch protection rules, so you'll need to remove any rules that apply to the default branch.
- Branch protection rulesets - rulesets can be configured to allow specified GitHub Apps (e.g. your GitHub app) to bypass branch protection - update your rulesets accordingly. Guardian developers: see recommended branch protection rulesets.
GitHub workflow
Example .github/workflows/release.yml
The functionality of gha-scala-library-release-workflow is provided in a
reusable workflow
called reusable-release.yml -
don't copy-and-paste that big file, instead just make a small release.yml workflow to
call
it (as in the example file above).
Your repo will require access to release credentials to pass on those secrets to the workflow.
Java version
Your repository must contain an asdf-formatted .tool-versions file
in the root of the repository, specifying the Java version to be used by the workflow for
building your project, eg:
java corretto-21.0.3.9.1
Note that although asdf requires a fully-specified Java version (eg 21.0.3.9.1 - use
asdf list-all java to list all possible Java versions), currently the workflow will only
match the major version of Java specified in the file (eg 21), and will always use the
AWS Corretto distribution of Java. This is due to
limitations in
actions/setup-java.
As recommended below, you should also specify a -release flag in
scalacOptions to ensure that your library is compiled for any older versions of Java you wish
to support, even if you're taking advantage of a more recent version of Java for building the
library.
sbt
Minimum sbt version: 1.9.0
Recommended sbt plugins
sbt-version-policy- to supply automatic compatibility-based version-numbering that follows recommended Scala semver rules on your library, as well as automatically setting theversionSchemeof your project to"early-semver"(essential).sbt-release
Recommended sbt settings
version- as specified bysbt-release, this should be the sole entry in yourversion.sbtfile, and should define a semver version (major.minor.patch), which during normal dev has a-SNAPSHOTsuffix (eg1.4.7-SNAPSHOT). You can think of-SNAPSHOTas meaning 'a snapshot preview' - so when you're working on1.4.7-SNAPSHOT, you're working on a preview of the forthcoming1.4.7release. The workflow will automatically update theversionduring each release, as appropriate.
- Artifact-producing modules - any module (project or subproject) that creates an artifact for Maven Central
organization- this dictates the groupId of your artifacts, and can be either the same as your Sonatype account profile name (egcom.gufor the Guardian), or a dot-suffixed version of it (egcom.gu.foobar) if your project ('foobar') releases multiple artifacts (details)licenses := Seq(License.Apache2)- or whatever license you're using. Specifying a license is required for submitting artifacts to Maven Central.scalacOptionsshould include-release:11(available with Scala 2.13.9 and above, also known as-java-output-versionin Scala 3), or whatever minimum version of Java you want to support. The workflow will build your project with whatever Java version you declare in.tool-versions- but while this can be a relatively new version of Java, in order for your compiled code to support older versions of Java, and avoidUnsupportedClassVersionErrorerrors, you'll need to set this flag. See also Scala/Java compatibility.
- Non-artifact-producing modules - any module that doesn't make an artifact to publish to Maven Central
(often, the 'root' project in a multi-project build)
publish / skip := true(rather than other legacy hacks likepublishArtifact := false). This setting is respected bysbt-version-policy- it won't attempt to calculate compatibility on a module that doesn't publish artifacts.
- Top-level 'release' module - if your project has a multi-module
build this could be called 'root', or, if your project only has one module, it and your
artifact-producing module could be the same thing, and just use top-level settings.
- In
releaseProcess, you'll want fewer steps than the old list specified bysbt-sonatype, now just:checkSnapshotDependencies, inquireVersions, runClean, runTest, setReleaseVersion, commitReleaseVersion, tagRelease, setNextVersion, commitNextVersion(if your tests require special privileges you may need to droprunTest) - Enable automated compatibility-based versioning by updating the
releaseVersionsetting. The correct version bump will be calculated by thesbt-version-policyplugin - yourversioncan go up by more than just anx.x.PATCHincrement in a release, if Scala semver rules say that it should. You'll need toimport sbtversionpolicy.withsbtrelease.ReleaseVersionat the top of yourbuild.sbt, and then use one of the following two methods, depending on whether your project is multi-module or not:- Multi-module :
releaseVersion := ReleaseVersion.fromAggregatedAssessedCompatibilityWithLatestRelease().value - Single-module :
releaseVersion := ReleaseVersion.fromAssessedCompatibilityWithLatestRelease().value
- Multi-module :
- In
Unnecessary sbt plugins
sbt-pgp- the workflow๐ Signjob now handles PGP signing directly with GPGsbt-sonatype- this is no longer needed
Unnecessary sbt settings
These settings are now set by gha-scala-library-release-workflow and can be removed from your build.sbt
or sonatype.sbt (sonatype.sbt can generally be deleted entirely):
homepagedeveloperspomExtrapublishTosonatypeProfileNamescmInfo- In
releaseProcess, it's essential you remove steps that are now separately performed elsewhere in the workflow (ie sign, release, push):releaseStepCommands likepublishSignedandsonatypeBundleReleasepushChanges
Examples
You can see a long list of example PRs updating repos to use gha-scala-library-release-workflow
here.
See also all repos using Scala Library Release Workflow.