CI: Automate final release workflow with version bumping

Introduce a new CI job in .gitlab-ci-release.yml to automate the
creation of project releases.

This change implements two new jobs in .gitlab-ci-release.yml:

1. A version:bump job that runs on a schedule. On the first Monday of an
even-numbered month, it automatically updates the VERSION and PATCHLEVEL
in the Makefile and pushes the change to the master branch.

2. A release:create job that is triggered by the version bump commit. It
creates the final GitLab Release and corresponding Git tag on the commit
containing the updated Makefile.

This ensures that the repository's version is correctly updated and
committed just before the official release tag is applied, creating a
clean and reliable release history.

This single job, designed to run on a schedule, contains logic to:

  - create a final release (e.g. 2025.08) on the first Monday of an
    even-numbered month.
  - create a release candidate (e.g. 2025.07-rc1) on all other
    scheduled days.

This uses official release-cli to create both the git tag and the
corresponding GitLab Release entry automatically.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2025-07-15 16:10:34 -06:00
parent 0c856610a9
commit 6a3532c0db
2 changed files with 59 additions and 33 deletions

View File

@@ -1,48 +1,73 @@
# .gitlab-ci-release.yml
# This single job handles the creation of both final releases and release candidates.
# It determines which type of release to create based on the date.
release:create:
stage: release
# We use the official release-cli image provided by GitLab.
image: registry.gitlab.com/gitlab-org/release-cli:latest
# Job to automatically update the version in the Makefile and push a commit.
# This runs on a schedule and only acts when a final release is due.
version:bump:
stage: version_bump
image: alpine:3.18 # A small image with git and bash
rules:
# This job only runs on scheduled pipelines that target the 'master' branch.
# Run only on scheduled pipelines targeting the 'master' branch.
- if: '$CI_PIPELINE_SOURCE == "schedule" && $CI_COMMIT_REF_NAME == "master"'
script:
- |
echo "🚀 Checking release conditions for pipeline on branch '$CI_COMMIT_REF_NAME'..."
# Use %-m, %-u, %-d to avoid issues with zero-padding (e.g., '08' being an invalid octal number).
echo "Checking if a final release is scheduled today..."
MONTH=$(date +%-m)
DAY_OF_WEEK=$(date +%-u) # 1=Monday, 7=Sunday
DAY_OF_WEEK=$(date +%-u)
DAY_OF_MONTH=$(date +%-d)
# FINAL RELEASE: Occurs on the first Monday of an even-numbered month.
# 1. The month is even (e.g., February, April...).
# 2. The day of the week is Monday.
# 3. The day is within the first 7 days of the month.
if [ $((MONTH % 2)) -eq 0 ] && [ "$DAY_OF_WEEK" -eq 1 ] && [ "$DAY_OF_MONTH" -le 7 ]; then
# This is a Final Release
TAG_NAME=$(date +%Y.%m)
RELEASE_TITLE="Release $TAG_NAME"
echo "✅ Conditions met for a Final Release. Creating tag: $TAG_NAME"
else
# This is a Release Candidate (RC)
# RC index is calculated based on the day of the month:
# Days 1-14 -> rc1, Days 15-28 -> rc2, etc.
RC_INDEX=$(( (DAY_OF_MONTH - 1) / 14 + 1 ))
TAG_NAME="$(date +%Y.%m)-rc${RC_INDEX}"
RELEASE_TITLE="Release Candidate $TAG_NAME"
echo "📝 Conditions met for a Release Candidate. Creating tag: $TAG_NAME"
# Only proceed on the first Monday of an even-numbered month.
if ! { [ $((MONTH % 2)) -eq 0 ] && [ "$DAY_OF_WEEK" -eq 1 ] && [ "$DAY_OF_MONTH" -le 7 ]; }; then
echo "Not a final release day. Nothing to do."
exit 0
fi
echo "Executing release-cli to create the release..."
echo "✅ Final release day detected. Updating Makefile..."
# Set up Git
apk add --no-cache git
git config --global user.name "GitLab CI"
git config --global user.email "gitlab-ci@${CI_SERVER_HOST}"
# Set the new version details
NEW_VERSION=$(date +%Y)
NEW_PATCHLEVEL=$(printf "%02d" $MONTH)
# Use sed to update the Makefile
sed -i "s/^VERSION = .*/VERSION = $NEW_VERSION/" Makefile
sed -i "s/^PATCHLEVEL = .*/PATCHLEVEL = $NEW_PATCHLEVEL/" Makefile
sed -i "s/^SUBLEVEL = .*/SUBLEVEL =/" Makefile
sed -i "s/^EXTRAVERSION = .*/EXTRAVERSION =/" Makefile
# If there are no changes, exit.
if git diff --quiet Makefile; then
echo "Makefile is already up-to-date."
exit 0
fi
# Commit and push the changes
echo "Pushing version bump to master branch..."
git add Makefile
COMMIT_MESSAGE="chore: Bump version to $NEW_VERSION.$NEW_PATCHLEVEL"
git commit -m "$COMMIT_MESSAGE"
# The GIT_WRITE_TOKEN is a variable you need to create (see setup below)
git push "https://gitlab-ci-token:${GIT_WRITE_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" HEAD:master
# Job to create the release. This job now triggers from the commit pushed by the 'version:bump' job.
release:create:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
# Run only on commits to master with a specific commit message.
- if: '$CI_COMMIT_BRANCH == "master" && $CI_COMMIT_MESSAGE =~ /^chore: Bump version to/'
script:
- |
echo "🚀 Release commit detected. Creating GitLab Release..."
# Extract the tag name directly from the commit message (e.g., "2025.08")
TAG_NAME=$(echo "$CI_COMMIT_MESSAGE" | sed -n 's/chore: Bump version to //p')
RELEASE_TITLE="Release $TAG_NAME"
release-cli create \
--name "$RELEASE_TITLE" \
--tag-name "$TAG_NAME" \
--description "Automated release created by GitLab CI. Based on commit $CI_COMMIT_SHORT_SHA on the '$CI_COMMIT_REF_NAME' branch." \
--description "Automated release created by GitLab CI for commit $CI_COMMIT_SHORT_SHA." \
--ref "$CI_COMMIT_SHA"

View File

@@ -27,6 +27,7 @@ stages:
- test.py
- sjg-lab
- world build
- version_bump
- release
.buildman_and_testpy_template: &buildman_and_testpy_dfn