Automated Release Management #
It’s a best practice for Open Source projects to automate their release process to reduce manual effort and maintain consistent, traceable changelogs. This relies on two complementary practices: a structured commit convention and a release automation tool.
When automated releases are expected #
Automated releases make sense if the project publishes release artifacts beyond the Git repository itself, for example:
- package registry uploads (for example PyPI)
- GitHub Releases with build artifacts
- GitHub Marketplace actions
- container images
In these cases, users consume a packaged output, so reproducible and auditable release creation should be automated.
If a repository is only consumed directly from Git (for example documentation or internal one-off tooling with no published artifacts), release automation can be optional.
Conventional Commits #
All commits to the default branch must follow the Conventional Commits specification:
type(optional-scope): description
Common types: feat, fix, docs, ci, chore, refactor, test, build, perf.
A feat commit triggers a minor version bump, a fix commit triggers a patch bump, and a BREAKING CHANGE footer triggers a major bump.
In addition, it’s best practice to squash-merge pull requests to keep the commit history clean and ensure that the PR title serves as the commit message, which must also follow the Conventional Commits format.
Semantic Versioning #
OpenRail projects that publish releases should follow Semantic Versioning, which defines a version format of MAJOR.MINOR.PATCH and rules for when to increment each part of the version number based on the types of changes introduced.
release-please #
release-please automates the release process by analysing the commit history. When commits following the Conventional Commits convention are merged to the default branch, release-please creates or updates a release pull request that bumps the version (according to Semantic Versioning) and updates the changelog. Merging that PR triggers the actual release (e.g. creating a Git tag, creating a GitHub release, and publishing to a package repository, if activated).
See purl-tools for a working example, including its release-please-config.json, .release-please-manifest.json, and release workflow .github/workflows/release-please.yaml.
For OpenRail projects, you may use the shared GitHub App (openrail-releaser) for authentication, so that the release PR can itself trigger CI workflows. In order to activate this (and make use of the two necessary secrets), an owner of the GitHub organization needs to configure the app and add the new repository to the section “Repository access”, as the app is only available for selected repositories.
Ensuring Conventional Commits for release-please #
For release-please to work properly, commit should follow the Conventional Commits format, and pull requests should be squash-merged while ensuring that the PR title (or at least the squash commit) also follows Conventional Commits format. If these requirements are not met, release-please may not be able to correctly determine the next version number or generate a meaningful changelog.
To avoid errors, you may configure the repository:
- Squash merging only: Disable “Allow merge commits” and “Allow rebase merging”
- Auto-delete branches: Enable “Automatically delete head branches”
Publishing to package registries #
Many OpenRail projects are Python-based and publish their releases to PyPI. A good combination with release-please is the use of an automatic release workflow that is triggered when a new release is created, which uses OIDC-based authentication to publish the new release and generates signed, digital attestations. This also prevents the need for storing long-lived secrets in GitHub and allows to publish releases without manual intervention.
You may see the workflow configuration in the purl-tools repository as an example.
In order to make this work, two things are necessary:
- You need to create a GitHub environment for the repository, in the example called
pypi. - At pypi.org, you need to edit the Publishing settings of the package, and add a new publisher via GitHub. In the input field, you provide information about the repository and the publishing workflow.