My team had the exact same use-case. Our merge strategy is the following:
- We use merge trains
- We squash our commits
And as pre-requisites, you need:
- A project access token (made available in CI) with at least read api access
- Scoped labels for the kind of release (obviously)
Based on these conditions, you can solve this problem by inspecting the commit message in your commit stage, extract out the branch name from the commit, and use that branch name to hit the Gitlab API to get the merge request's label.
We have two stages in our gitlab-ci:
verify_tags:
stage: lint
script:
- sh build-scripts/verify-merge-request-labels.sh
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
this stage verifies that merge requests have labels. If they don't, they can't be merged. The verify-merge-request-labels.sh script is pretty simple:
#!/bin/sh
BUMP_VERSION_TYPE=$(echo "$CI_MERGE_REQUEST_LABELS" | sed -E 's/.*bump version::(major|minor|patch).*/\1/')
case $BUMP_VERSION_TYPE in
major|minor|patch)
echo "Detected semver part $BUMP_VERSION_TYPE"
;;
*)
echo "Could not parse semver part out of $CI_MERGE_REQUEST_LABELS. Make sure to add a \`bump version\` label to your merge request."
exit 1
;;
esac
The second stage actually gets ran when the branch is getting merged in.
increment_version:
stage: release
image: python:3.9
before_script:
- git remote set-url origin "https://gitlab-ci-token:${RUNNER_TOKEN}@${YOUR_GIT_HOST}/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}.git"
- git config --global user.email "${GITLAB_USER_EMAIL}"
- git config --global user.name "${GITLAB_USER_NAME}"
- poetry install --only dev
script:
- poetry run bumpver update $(python build-scripts/determine-bumpver-semver-flag.py)
- git push -o ci.skip origin $(git tag) HEAD:${CI_COMMIT_REF_NAME}
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
The second script is a bit more complex (and long) so I won't share its entirety, but its snippets (in python using requests) are as follows:
branch_pattern = r"Merge branch '(?P<branch>[^']*)'"
source_branch = re.search(branch_pattern, os.environ["CI_COMMIT_TITLE"]).group("branch")
# Get original merge request corresponding to source branch
query_params = {"source_branch": source_branch}
url = f"{os.environ['CI_API_V4_URL']}/projects/{os.environ['CI_PROJECT_ID']}/merge_requests"
r = requests.get(
url=url,
params=query_params,
headers={"Authorization": f"Bearer {os.environ['RUNNER_TOKEN']}"},
)
labels = r.json()[0]["labels"]
The API reference is here