-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Release pipeline automation
The Solidus repository at solidusio/solidus
relies on a series of automation to streamline the processes related to delivering new versions.
Most of the integrations are controlled by labels on Pull Requests. For this reason, we need to be very careful before renaming or deleting them.
All submitted PRs get assigned a label that identifies which gem the changes belong to:
changelog:solidus_core
changelog:solidus_backend
changelog:solidus_api
changelog:solidus_sample
changelog:solidus
-
changelog:repository
: identifies updates that don't belong to any gem.
The triage is automatically done by the "Triage for Changelog" workflow by checking the files modified on a PR. On top of that, the "Ensure Changelog label" workflow fails if none of those labels is present.
Eventually, the information will be leveraged to create the release notes and update the Changelog. The changelog:skip
label can be manually applied to skip a PR from that downstream automation.
Whenever a PR is merged, their changelog labels are used to add a new entry in the GitHub release draft for the next version.
That's done by the "Update Release Draft on GitHub" workflow.
As the release notes are automatically generated, we must avoid manually updating them.
When the time comes to release a new Solidus version, we can manually dispatch the "Prepare release" workflow. As the GitHub documentation explains, there're different ways of doing that.
To prepare a new release from GitHub's UI, navigate to the "Actions" tab and select the "Prepare release" item.
After that, click on the "Run workflow" dropdown. It'll prompt you to select the branch from which the release needs to be prepared and whether it is the next-to-last after a major release.
Alternatively, the most straightforward way to run the workflow from the command line is through GitHub's CLI tool:
# Prepare a release on master
gh workflow run prepare_release.yml
# Prepare a release on master for the previous release after the last minor in a series
gh workflow run prepare_release.yml -F last_minor=true
# Prepare a release for v3.2
gh workflow run prepare_release.yml --ref v3.2
Once the automation is run, a new PR for the picked branch will be ready with the following:
- References to the current Solidus version bumped to the release candidate one.
- Updated Changelog with the contents of the corresponding release notes.
The created PR will contain the release:generate
label and the release:generate-last_minor
one in case the corresponding checkbox has been checked. Those labels will be used to perform the after-release chores.
It's worth noting that the release to RubyGems is not covered, so security is not compromised. That step still needs to be manually done through the gem release
command provided by the gem-release
gem.
Once a PR preparing a release is merged, a new PR is created, automating the post-release chores:
- Bumping version to the next candidate
.dev
one. - Publishing the release draft and tagging the last commit accordingly.
- Creating a new v* branch for releases on master (minor and major releases).
That's coordinated thanks to the "Prepare post-release" workflow.
Most of the automation mentioned above needs information about the active pipeline, e.g., the current version, the candidate tag, etc. That's orchestrated by the "Extract Pipeline Context" composite action. We can summarize its work:
- The most recent tag is extracted from the list of tags in the repository:
- For master, that's going to be the higher one.
- For v* branches, that will be the higher one for the branch.
- For the to-be-released candidate:
- For master:
- It's one minor level higher than the current tag when
Spree::VERSION
doesn't track a major release. - It's one major level higher than the current tag when
Spree::VERSION
tracks a major release.
- It's one minor level higher than the current tag when
- For v* branches, it's one patch level higher than the current tag.
- For master:
- For the next to-be-released candidate (only used to prepare the after-release chores):
- For master:
- It's one minor level higher than the candidate tag when we don't specify that a candidate will be the last minor release (see how to prepare a release).
- It's one major level higher than the current tag when we specify that a candidate till be the last minor release.
- For v* branches, it's one patch level higher than the to-be-released tag.
- For master:
flowchart LR
Contributor("USER")
Maintainer("MAINTAINER")
TriageWorkflow("WORKFLOW: Triage")
EnsureLabelWorkflow("WORKFLOW: Ensure Label")
PrepareReleaseWorkflow("WORKFLOW: Prepare release")
PreparePostReleaseWorkflow("WORKFLOW: Prepare post-release")
Contributor-->ContributionPR
Maintainer-->PrepareReleasePR
ContributionPR --> TriageWorkflow --> EnsureLabelWorkflow --> Draft
PrepareReleasePR --> PrepareReleaseWorkflow --> PreparePostReleasePR
PreparePostReleasePR --> PreparePostReleaseWorkflow
PrepareReleaseWorkflow <--> Draft
PreparePostReleaseWorkflow --> Tag
PreparePostReleaseWorkflow -- master? --> Branch
PreparePostReleaseWorkflow -- publish --> Draft
subgraph "Pull requests"
PrepareReleasePR("PR: Prepare release (changelog:skip, release:generate)")
PreparePostReleasePR("PR: Prepare post-release")
ContributionPR("PR: Contribution (changelog:solidus_core)")
end
subgraph "Release notes"
Draft("Draft")
end
subgraph "Tags"
Tag("Tag")
end
subgraph "Branches"
Branch("Branch")
end