stages: - prepare unbound_release_preconditions_failed: stage: .pre image: alpine:3.21@sha256:21dc6063fd678b478f57c0e13f47560d0ea4eeba26dfc947b2a4f81f686b9f45 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:latest@sha256:71d85f63991b29fbbc34ac9953be544d190874788885b7cd2f23b197bb995997 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 > 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_COMMIT_TITLE =~ /^chore\(release\): prepare for .*$/' when: never - if: $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH unbound_release_handle_mr: stage: .pre image: alpine:latest@sha256:21dc6063fd678b478f57c0e13f47560d0ea4eeba26dfc947b2a4f81f686b9f45 needs: - unbound_release_changelog before_script: - 'apk add --no-cache git jq curl' script: - | LATEST="$(git describe --abbrev=0 --tags 2>/dev/null || echo '')" if [[ -n "${LATEST}" && "$(cat VERSION)" == "${LATEST}" ]]; then echo "No changes worthy of a version bump" exit 0 fi echo "Fetching existing release MRs" MRS=$(curl -s \ -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 -s \ -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 $(cat VERSION)" DESCRIPTION="$(cat CHANGES.md)" CONTENT="$(base64 -w0 update 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" else # Not exists => create 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" fi if [ -n "${MR}" ]; then echo "Updating existing MR" echo "Rebasing branch" 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" 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_COMMIT_TITLE =~ /^chore\(release\): prepare for .*$/' when: never - if: $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH unbound_release_prepare_release: stage: .pre image: name: orhunp/git-cliff:latest@sha256:71d85f63991b29fbbc34ac9953be544d190874788885b7cd2f23b197bb995997 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_COMMIT_TITLE =~ /^chore\(release\): prepare for .*$/' - if: $CI_COMMIT_TAG && $UNBOUND_RELEASE_TAG_ONLY == "true" unbound_release_create_release: stage: .pre image: alpine:latest@sha256:21dc6063fd678b478f57c0e13f47560d0ea4eeba26dfc947b2a4f81f686b9f45 needs: - unbound_release_prepare_release before_script: - 'apk add --no-cache jq curl' script: - | 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_COMMIT_TITLE =~ /^chore\(release\): prepare for .*$/' unbound_release_tag: stage: .pre image: alpine:latest@sha256:21dc6063fd678b478f57c0e13f47560d0ea4eeba26dfc947b2a4f81f686b9f45 needs: - unbound_release_prepare_release before_script: - 'apk add --no-cache curl' script: - | 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: '$CI_COMMIT_TITLE =~ /^chore\(release\): prepare for .*$/'