feat(ci): add basic release workflows#665
Conversation
Since the repository has some pretty strict rules about pushing certain branches, we need to define some basic workflows that will allow us to push them via a robot account. While we are at it, we are also automating some of the additional steps needed for updating and pinning versions TODO: update release.md
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR adds two new GitHub Actions workflows to automate the release process. The ChangesRelease Automation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/prepare-release.yml:
- Around line 63-74: Make the tag and branch steps idempotent so rerunning the
workflow doesn't fail: for the tag referenced as "${{ inputs.version }}.x" check
whether the tag already exists (e.g., via git rev-parse --verify) and only
create it if missing instead of unconditionally running git tag; for the branch
"release-${{ inputs.version }}" use git checkout -B "release-${{ inputs.version
}}" to recreate/reset the local branch reliably, fetch remote refs first, and
when pushing use a safe update (git push --force-with-lease origin "release-${{
inputs.version }}" or push the tag only if newly created) so the Push internal
tag and release-${{ inputs.version }} branch step becomes rerunnable without
manual cleanup.
- Around line 123-127: The update-version job currently only depends on
validate-version, so it can run and open the next-version PR even if
prepare-release-branch fails; change its dependencies so update-version also
waits for the prepare-release-branch job to complete successfully (add
prepare-release-branch to the needs list for the update-version job), ensuring
update-version will not advance main before a release branch/tag is created.
- Around line 82-86: The checkout step always tries to fetch ref: release-${{
inputs.version }} which fails in dry-run because that remote branch isn't
pushed; replace the single checkout with two conditional steps: one
actions/checkout@v6 step that includes ref: release-${{ inputs.version }} and
runs only when inputs.dry-run is false, and a second actions/checkout@v6 step
without the ref (default checkout of the workflow commit) that runs when
inputs.dry-run is true; update the step names accordingly so later steps use the
same workspace.
In @.github/workflows/release.yml:
- Around line 51-60: The tag is constructed with undefined variable RELEASE and
PATCH isn't exported to the Push tag step; update the Create release tag step to
build the tag using the defined VERSION and the patch from
steps.patch.outputs.patch (e.g., use "${VERSION}.${{ steps.patch.outputs.patch
}}") and export or set PATCH consistently so the Push tag step pushes the exact
same ref (or change the Push tag step to push "${VERSION}.${{
steps.patch.outputs.patch }}" too); ensure both steps reference the same
variables (replace RELEASE with VERSION and either set env PATCH from
steps.patch.outputs.patch or inline the steps.patch.outputs.patch expression in
both steps) so the tag name is correct and consistent.
- Around line 29-44: Patch selection currently uses git describe --tags
--abbrev=0 which returns the nearest tag from HEAD (variable last_tag in the
"Determine patch version" step); change it to explicitly pick the latest tag
matching the requested series ${VERSION}.* (e.g. replace the last_tag assignment
with a command that lists tags filtered by pattern and sorts by version, such as
using git tag --list "${VERSION}.*" --sort=-v:refname | head -n1), then keep the
existing regex/patch logic but add a guard to fail if no matching tag is found
(empty last_tag) so the patch calculation uses the correct series tag instead of
a nearest unrelated tag.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: 5db6a745-9ef7-4156-9be2-6df4dd8c93f0
📒 Files selected for processing (2)
.github/workflows/prepare-release.yml.github/workflows/release.yml
| - name: Create internal tag and release-${{ inputs.version }} branch | ||
| run: | | ||
| git checkout main | ||
| git pull --ff-only | ||
| git tag "${{ inputs.version }}.x" | ||
| git checkout -b "release-${{ inputs.version }}" | ||
|
|
||
| - name: Push internal tag and release-${{ inputs.version }} branch | ||
| if: ${{ ! inputs.dry-run }} | ||
| run: | | ||
| git push origin "${{ inputs.version }}.x" | ||
| git push --set-upstream origin "release-${{ inputs.version }}" |
There was a problem hiding this comment.
Make branch/tag creation rerunnable.
These commands unconditionally recreate the internal tag and release branch. If a later job fails after the push, rerunning the workflow stops here and requires manual cleanup before you can recover.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/prepare-release.yml around lines 63 - 74, Make the tag and
branch steps idempotent so rerunning the workflow doesn't fail: for the tag
referenced as "${{ inputs.version }}.x" check whether the tag already exists
(e.g., via git rev-parse --verify) and only create it if missing instead of
unconditionally running git tag; for the branch "release-${{ inputs.version }}"
use git checkout -B "release-${{ inputs.version }}" to recreate/reset the local
branch reliably, fetch remote refs first, and when pushing use a safe update
(git push --force-with-lease origin "release-${{ inputs.version }}" or push the
tag only if newly created) so the Push internal tag and release-${{
inputs.version }} branch step becomes rerunnable without manual cleanup.
| - uses: actions/checkout@v6 | ||
| with: | ||
| submodules: false | ||
| ref: release-${{ inputs.version }} | ||
| token: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }} |
There was a problem hiding this comment.
Dry runs cannot reach this checkout.
prepare-release-branch only pushes release-${{ inputs.version }} when dry-run is false, but this job always checks that ref out from origin. In dry-run mode the branch does not exist remotely, so the workflow fails before the validation diff is produced.
Possible fix
pin-rust-version:
runs-on: ubuntu-24.04
needs:
- validate-version
- prepare-release-branch
steps:
- uses: actions/checkout@v6
with:
submodules: false
- ref: release-${{ inputs.version }}
+ ref: main
token: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }}
+
+ - name: Switch to release branch
+ run: |
+ if [[ "${{ inputs.dry-run }}" == "true" ]]; then
+ git checkout -b "release-${{ inputs.version }}"
+ else
+ git fetch origin "release-${{ inputs.version }}:release-${{ inputs.version }}"
+ git checkout "release-${{ inputs.version }}"
+ fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - uses: actions/checkout@v6 | |
| with: | |
| submodules: false | |
| ref: release-${{ inputs.version }} | |
| token: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }} | |
| - uses: actions/checkout@v6 | |
| with: | |
| submodules: false | |
| ref: main | |
| token: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }} | |
| - name: Switch to release branch | |
| run: | | |
| if [[ "${{ inputs.dry-run }}" == "true" ]]; then | |
| git checkout -b "release-${{ inputs.version }}" | |
| else | |
| git fetch origin "release-${{ inputs.version }}:release-${{ inputs.version }}" | |
| git checkout "release-${{ inputs.version }}" | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/prepare-release.yml around lines 82 - 86, The checkout
step always tries to fetch ref: release-${{ inputs.version }} which fails in
dry-run because that remote branch isn't pushed; replace the single checkout
with two conditional steps: one actions/checkout@v6 step that includes ref:
release-${{ inputs.version }} and runs only when inputs.dry-run is false, and a
second actions/checkout@v6 step without the ref (default checkout of the
workflow commit) that runs when inputs.dry-run is true; update the step names
accordingly so later steps use the same workspace.
| update-version: | ||
| runs-on: ubuntu-24.04 | ||
| needs: | ||
| - validate-version | ||
| steps: |
There was a problem hiding this comment.
Don’t advance main before the release branch exists.
update-version only waits for validation, so it can still open the next-version PR even if prepare-release-branch fails. That leaves main ahead of a release branch/tag that was never cut.
Possible fix
update-version:
runs-on: ubuntu-24.04
needs:
- validate-version
+ - prepare-release-branch📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| update-version: | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - validate-version | |
| steps: | |
| update-version: | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - validate-version | |
| - prepare-release-branch | |
| steps: |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/prepare-release.yml around lines 123 - 127, The
update-version job currently only depends on validate-version, so it can run and
open the next-version PR even if prepare-release-branch fails; change its
dependencies so update-version also waits for the prepare-release-branch job to
complete successfully (add prepare-release-branch to the needs list for the
update-version job), ensuring update-version will not advance main before a
release branch/tag is created.
| - name: Determine patch version | ||
| id: patch | ||
| run: | | ||
| last_tag="$(git describe --tags --abbrev=0)" | ||
|
|
||
| if [[ "$last_tag" =~ ^"${VERSION}"\.x$ ]]; then | ||
| patch=0 | ||
| elif [[ "$last_tag" =~ ^"${VERSION}"\.([[:digit:]]+)$ ]]; then | ||
| patch=$((BASH_REMATCH[1] + 1)) | ||
| else | ||
| echo >&2 "Failed to determine patch version for ${VERSION}" | ||
| echo >&2 "Last tag found: $last_tag" | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "patch=$patch" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
Patch selection is based on the nearest tag, not the requested release series.
git describe --tags --abbrev=0 returns the closest reachable tag from HEAD; it does not limit the result to ${VERSION}.*. A different series tag on the branch makes Line 34/36 fail or increments from the wrong base.
Safer approach
- name: Determine patch version
id: patch
run: |
- last_tag="$(git describe --tags --abbrev=0)"
+ last_tag="$(
+ {
+ git tag --list "${VERSION}.[0-9]*"
+ git tag --list "${VERSION}.x"
+ } | sort -V | tail -n1
+ )"
+
+ if [[ -z "$last_tag" ]]; then
+ echo >&2 "Failed to determine patch version for ${VERSION}"
+ exit 1
+ fi
if [[ "$last_tag" =~ ^"${VERSION}"\.x$ ]]; then
patch=0
elif [[ "$last_tag" =~ ^"${VERSION}"\.([[:digit:]]+)$ ]]; then
patch=$((BASH_REMATCH[1] + 1))📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Determine patch version | |
| id: patch | |
| run: | | |
| last_tag="$(git describe --tags --abbrev=0)" | |
| if [[ "$last_tag" =~ ^"${VERSION}"\.x$ ]]; then | |
| patch=0 | |
| elif [[ "$last_tag" =~ ^"${VERSION}"\.([[:digit:]]+)$ ]]; then | |
| patch=$((BASH_REMATCH[1] + 1)) | |
| else | |
| echo >&2 "Failed to determine patch version for ${VERSION}" | |
| echo >&2 "Last tag found: $last_tag" | |
| exit 1 | |
| fi | |
| echo "patch=$patch" >> "$GITHUB_OUTPUT" | |
| - name: Determine patch version | |
| id: patch | |
| run: | | |
| last_tag="$( | |
| { | |
| git tag --list "${VERSION}.[0-9]*" | |
| git tag --list "${VERSION}.x" | |
| } | sort -V | tail -n1 | |
| )" | |
| if [[ -z "$last_tag" ]]; then | |
| echo >&2 "Failed to determine patch version for ${VERSION}" | |
| exit 1 | |
| fi | |
| if [[ "$last_tag" =~ ^"${VERSION}"\.x$ ]]; then | |
| patch=0 | |
| elif [[ "$last_tag" =~ ^"${VERSION}"\.([[:digit:]]+)$ ]]; then | |
| patch=$((BASH_REMATCH[1] + 1)) | |
| else | |
| echo >&2 "Failed to determine patch version for ${VERSION}" | |
| echo >&2 "Last tag found: $last_tag" | |
| exit 1 | |
| fi | |
| echo "patch=$patch" >> "$GITHUB_OUTPUT" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release.yml around lines 29 - 44, Patch selection
currently uses git describe --tags --abbrev=0 which returns the nearest tag from
HEAD (variable last_tag in the "Determine patch version" step); change it to
explicitly pick the latest tag matching the requested series ${VERSION}.* (e.g.
replace the last_tag assignment with a command that lists tags filtered by
pattern and sorts by version, such as using git tag --list "${VERSION}.*"
--sort=-v:refname | head -n1), then keep the existing regex/patch logic but add
a guard to fail if no matching tag is found (empty last_tag) so the patch
calculation uses the correct series tag instead of a nearest unrelated tag.
| - name: Create release tag | ||
| env: | ||
| PATCH: ${{ steps.patch.outputs.patch }} | ||
| run: | | ||
| git tag -a -m "fact v${VERSION}.${PATCH} release" "${RELEASE}.${PATCH}" | ||
|
|
||
| - name: Push tag | ||
| if: ${{ ! inputs.dry-run }} | ||
| run: | | ||
| git push origin "${VERSION}.${PATCH}" |
There was a problem hiding this comment.
The tag name is built from variables that are not available here.
Line 55 uses ${RELEASE}, which is never defined, and Line 60 uses ${PATCH} in a different step where that env var does not exist. As written, the workflow creates the wrong tag name and then tries to push a different or nonexistent ref.
Possible fix
- name: Create release tag
- env:
- PATCH: ${{ steps.patch.outputs.patch }}
run: |
- git tag -a -m "fact v${VERSION}.${PATCH} release" "${RELEASE}.${PATCH}"
+ git tag -a \
+ -m "fact v${VERSION}.${{ steps.patch.outputs.patch }} release" \
+ "${VERSION}.${{ steps.patch.outputs.patch }}"
- name: Push tag
if: ${{ ! inputs.dry-run }}
run: |
- git push origin "${VERSION}.${PATCH}"
+ git push origin "${VERSION}.${{ steps.patch.outputs.patch }}"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Create release tag | |
| env: | |
| PATCH: ${{ steps.patch.outputs.patch }} | |
| run: | | |
| git tag -a -m "fact v${VERSION}.${PATCH} release" "${RELEASE}.${PATCH}" | |
| - name: Push tag | |
| if: ${{ ! inputs.dry-run }} | |
| run: | | |
| git push origin "${VERSION}.${PATCH}" | |
| - name: Create release tag | |
| run: | | |
| git tag -a \ | |
| -m "fact v${VERSION}.${{ steps.patch.outputs.patch }} release" \ | |
| "${VERSION}.${{ steps.patch.outputs.patch }}" | |
| - name: Push tag | |
| if: ${{ ! inputs.dry-run }} | |
| run: | | |
| git push origin "${VERSION}.${{ steps.patch.outputs.patch }}" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release.yml around lines 51 - 60, The tag is constructed
with undefined variable RELEASE and PATCH isn't exported to the Push tag step;
update the Create release tag step to build the tag using the defined VERSION
and the patch from steps.patch.outputs.patch (e.g., use "${VERSION}.${{
steps.patch.outputs.patch }}") and export or set PATCH consistently so the Push
tag step pushes the exact same ref (or change the Push tag step to push
"${VERSION}.${{ steps.patch.outputs.patch }}" too); ensure both steps reference
the same variables (replace RELEASE with VERSION and either set env PATCH from
steps.patch.outputs.patch or inline the steps.patch.outputs.patch expression in
both steps) so the tag name is correct and consistent.
Description
Since the repository has some pretty strict rules about pushing certain branches, we need to define some basic workflows that will allow us to push them via a robot account. While we are at it, we are also automating some of the additional steps needed for updating and pinning versions
TODO: update release.md
Checklist
Automated testing
If any of these don't apply, please comment below.
Testing Performed
TODO(replace-me)
Use this space to explain how you tested your PR, or, if you didn't test it, why you did not do so. (Valid reasons include "CI is sufficient" or "No testable changes")
In addition to reviewing your code, reviewers must also review your testing instructions, and make sure they are sufficient.
For more details, ref the Confluence page about this section.