This repository has been archived on 2026-03-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
ci-templates/Release.gitlab-ci.yml
T
argoyle 7b520d8d0f chore(release): update version handling in CI script
Updates the CI script to improve version retrieval and checking logic. 
Replaces direct calls to the VERSION file with reading from a 
`.version` JSON file, ensuring proper version management. Handles 
the creation and updating of the CHANGELOG and .version files to 
enhance the release process. Adjusts conditions for executing 
release tasks based on current tags and branches to prevent 
unnecessary executions.
2025-09-11 09:29:09 +02:00

269 lines
11 KiB
YAML

stages:
- prepare
unbound_release_preconditions_failed:
stage: .pre
image: amd64/alpine:3.22.1@sha256:04f9172abd4691ef13a65d0c5c3057ba365a8db269e848ae24f2151e50997f99
script:
- |
echo "To use Unbound Release, a UNBOUND_RELEASE_TOKEN environment variable needs to be defined."
echo "It needs API access to write repository files, create MRs and releases and it needs at least Developer access."
echo " "
echo "See more info here:"
echo "Personal Access Tokens: https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html"
echo "Project Access Tokens: https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html"
echo "Group Access Tokens: https://docs.gitlab.com/ee/user/group/settings/group_access_tokens.html"
- 'false'
rules:
- if: $UNBOUND_RELEASE_TOKEN == null
unbound_release_changelog:
stage: .pre
image:
name: orhunp/git-cliff:2.10.0@sha256:ae15c208868fd474987e30b2b8486d0cdf55ee580c68ec14237b3ac6a36e0d91
entrypoint: [ "" ]
variables:
GIT_STRATEGY: clone # clone entire repo instead of reusing workspace
GIT_DEPTH: 0 # avoid shallow clone to give cliff all the info it needs
script:
- 'echo "Generating changelog"'
- 'git-cliff --bump --unreleased --strip header > CHANGES.md'
- 'git-cliff --bump | sed "s/\s\+$//" > CHANGELOG.md'
- 'echo "Bumping version"'
- 'git-cliff --bumped-version 2>/dev/null > VERSION'
artifacts:
paths:
- CHANGES.md
- CHANGELOG.md
- VERSION
rules:
- if: $UNBOUND_RELEASE_TOKEN == null
when: never
- if: $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH
unbound_release_handle_mr:
stage: .pre
image: amd64/alpine:3.22.1@sha256:04f9172abd4691ef13a65d0c5c3057ba365a8db269e848ae24f2151e50997f99
variables:
GIT_STRATEGY: clone # clone entire repo instead of reusing workspace
GIT_DEPTH: 0 # avoid shallow clone to have the tags available
needs:
- unbound_release_changelog
before_script:
- 'apk add --no-cache git jq curl'
script:
- |
VERSION="$(cat VERSION)"
LATEST="$(cat .version 2>/dev/null | jq -r '.version' || git describe --abbrev=0 --tags 2>/dev/null || echo '')"
if [[ -n "${LATEST}" && "${VERSION}" == "${LATEST}" ]]; then
echo "No changes worthy of a version bump"
exit 0
fi
echo "Fetching existing release MRs"
MRS=$(curl -sf \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/merge_requests?state=opened&source_branch=next-release")
BRANCHES=$(curl -sf \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/repository/branches?regex=^next-release\$")
MR=$(echo "${MRS}" | jq ".[].iid")
BRANCH=$(echo "${BRANCHES}" | jq ".[].name")
TITLE="chore(release): prepare for ${VERSION}"
DESCRIPTION="$(cat CHANGES.md)"
CONTENT="$(base64 -w0 <CHANGELOG.md)"
NEW_BRANCH_BODY_TMPL='{"branch": "next-release", "start_branch": $startBranch, "author_name": "Unbound Release", "content": $content, "commit_message": $title, "encoding": "base64" }'
OLD_BRANCH_BODY_TMPL='{"branch": "next-release", "author_name": "Unbound Release", "content": $content, "commit_message": $title, "encoding": "base64" }'
BODY_TMPL=${NEW_BRANCH_BODY_TMPL}
if [ -n "${BRANCH}" ]; then
BODY_TMPL=${OLD_BRANCH_BODY_TMPL}
fi
BODY="$(jq --null-input -c \
--arg title "${TITLE}" \
--arg content "${CONTENT}" \
--arg startBranch "${CI_DEFAULT_BRANCH}" \
"${BODY_TMPL}")"
echo "Creating or updating CHANGELOG.md"
curl -sf -X POST \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
--data "${BODY}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/repository/files/CHANGELOG%2Emd" || \
curl -sf -X PUT \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
--data "${BODY}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/repository/files/CHANGELOG%2Emd"
CONTENT="$(jq --null-input -c --arg version "${VERSION}" '{"version":$version}' | base64 -w0)"
BODY="$(jq --null-input -c \
--arg title "${TITLE}" \
--arg content "${CONTENT}" \
--arg startBranch "${CI_DEFAULT_BRANCH}" \
"${OLD_BRANCH_BODY_TMPL}")"
echo "Creating or updating .version"
curl -s --fail-with-body -X POST \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
--data "${BODY}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/repository/files/%2Eversion" || \
curl -s --fail-with-body -X PUT \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
--data "${BODY}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/repository/files/%2Eversion"
if [ -n "${MR}" ]; then
echo "Updating existing MR"
echo "Rebasing MR"
curl -sf -X PUT \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/merge_requests/${MR}/rebase"
rebasing="true"
while [[ "${rebasing}" == "true" ]]; do
sleep 1
echo "Checking if MR is rebased"
rebasing=$(curl -sf \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/merge_requests/${MR}?include_rebase_in_progress=true" | jq -r '.rebase_in_progress')
done
echo "MR rebased"
echo "Updating title"
BODY_TMPL='{"target_branch":$target,"title":$title,"description":$description,"remove_source_branch":true,"squash":true}'
BODY=$(jq --null-input -c \
--arg title "${TITLE}" \
--arg description "${DESCRIPTION}" \
--arg target "${CI_DEFAULT_BRANCH}" \
"${BODY_TMPL}")
curl -sf -X PUT \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
--data "${BODY}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/merge_requests/${MR}"
else
echo "Creating new MR"
BODY_TMPL='{"source_branch":"next-release","target_branch":$target,"title":$title,"description":$description,"remove_source_branch":true,"squash":true}'
BODY=$(jq --null-input -c \
--arg title "${TITLE}" \
--arg description "${DESCRIPTION}" \
--arg target "${CI_DEFAULT_BRANCH}" \
"${BODY_TMPL}")
curl -sf -X POST \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
--data "${BODY}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/merge_requests"
fi
rules:
- if: $UNBOUND_RELEASE_TOKEN == null
when: never
- if: $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH
unbound_release_prepare_release:
stage: .pre
image:
name: orhunp/git-cliff:2.10.0@sha256:ae15c208868fd474987e30b2b8486d0cdf55ee580c68ec14237b3ac6a36e0d91
entrypoint: [ "" ]
variables:
GIT_STRATEGY: clone # clone entire repo instead of reusing workspace
GIT_DEPTH: 0 # avoid shallow clone to give cliff all the info it needs
script:
- |
echo "Generating changelog"
if [ -n "${CI_COMMIT_TAG}" ]; then
git-cliff --bump --latest --strip header > CHANGES.md
else
git-cliff --bump --unreleased --strip header > CHANGES.md
fi
echo "Bumping version"
git-cliff --bumped-version 2>/dev/null > VERSION
artifacts:
paths:
- CHANGES.md
- VERSION
rules:
- if: $UNBOUND_RELEASE_TOKEN == null
when: never
- if: $CI_COMMIT_TAG == null && $CI_DEFAULT_BRANCH != $CI_COMMIT_BRANCH
when: never
- if: $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH
unbound_release_create_release:
stage: .pre
image: amd64/alpine:3.22.1@sha256:04f9172abd4691ef13a65d0c5c3057ba365a8db269e848ae24f2151e50997f99
variables:
GIT_STRATEGY: clone # clone entire repo instead of reusing workspace
GIT_DEPTH: 0 # avoid shallow clone to have the tags available
needs:
- unbound_release_prepare_release
before_script:
- 'apk add --no-cache git jq curl'
script:
- |
if [ ! -r .version ]; then
echo "Version file not found"
exit 0
fi
VERSION="$(cat .version 2>/dev/null | jq -r '.version')"
LATEST="$(git describe --abbrev=0 --tags 2>/dev/null || echo '')"
if [[ -n "${LATEST}" && "${VERSION}" == "${LATEST}" ]]; then
echo "Version ${VERSION} already exists"
exit 0
fi
echo "Creating release"
NAME="$(cat VERSION)"
MESSAGE="$(cat CHANGES.md)"
BODY_TMPL='{"name":$name,"tag_name":$name,"tag_message":$name,"description":$message,"ref":$ref}'
BODY="$(jq --null-input -c \
--arg name "${NAME}" \
--arg message "${MESSAGE}" \
--arg ref "${CI_DEFAULT_BRANCH}" \
"${BODY_TMPL}")"
curl -sf -X POST \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
--data "${BODY}" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/releases"
rules:
- if: $UNBOUND_RELEASE_TOKEN == null
when: never
- if: $CI_DEFAULT_BRANCH != $CI_COMMIT_BRANCH
when: never
- if: $UNBOUND_RELEASE_TAG_ONLY == "true"
when: never
- if: $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH
unbound_release_tag:
stage: .pre
image: amd64/alpine:3.22.1@sha256:04f9172abd4691ef13a65d0c5c3057ba365a8db269e848ae24f2151e50997f99
variables:
GIT_STRATEGY: clone # clone entire repo instead of reusing workspace
GIT_DEPTH: 0 # avoid shallow clone to have the tags available
needs:
- unbound_release_prepare_release
before_script:
- 'apk add --no-cache git jq curl'
script:
- |
VERSION="$(cat VERSION)"
LATEST="$(git describe --abbrev=0 --tags 2>/dev/null || echo '')"
if [[ -n "${LATEST}" && "${VERSION}" == "${LATEST}" ]]; then
echo "Version ${VERSION} already exists"
exit 0
fi
echo "Creating tag"
NAME="$(cat VERSION)"
MESSAGE="$(cat CHANGES.md)"
curl -sf -X POST \
-H "Authorization: Bearer ${UNBOUND_RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/repository/tags?tag_name=${NAME}&ref=${CI_DEFAULT_BRANCH}&message=${NAME}"
rules:
- if: $UNBOUND_RELEASE_TOKEN == null
when: never
- if: $CI_DEFAULT_BRANCH != $CI_COMMIT_BRANCH
when: never
- if: $UNBOUND_RELEASE_TAG_ONLY == null
when: never
- if: $UNBOUND_RELEASE_TAG_ONLY == "false"
when: never
- if: $UNBOUND_RELEASE_TAG_ONLY == "true"