Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
name: Prepare Release Branch

on:
workflow_dispatch:
inputs:
version:
description: |
The release version in <Major>.<minor> format.
required: true
type: string
next-version:
description: |
The <Major>.<minor> version that will be used for the next
release.
required: true
type: string
rust-version:
description: |
The Rust version that will be used for the new release branch.
required: true
type: string
dry-run:
description: Do not push anything
default: true
type: boolean

jobs:
validate-version:
runs-on: ubuntu-24.04
steps:
- name: Validate release versions
run: |
function validate_version() {
name="$1"
version="$2"

if [[ ! "$version" =~ ^([[:digit:]]+)\.([[:digit:]]+)$ ]] ; then
echo >&2 "Invalid $name $version. The expected format is <Major>.<minor>"
exit 1
fi
}

validate_version "version" ${{ inputs.version }}
validate_version "next-version" ${{ inputs.next-version }}
validate_version "rust-version" ${{ inputs.rust-version }}

prepare-release-branch:
runs-on: ubuntu-24.04
needs:
- validate-version
steps:
- uses: actions/checkout@v6
with:
submodules: false
ref: main
token: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }}

- name: Initialize mandatory git config
run: |
git config user.name "${{ github.event.sender.login }}"
git config user.email noreply@github.com

- 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 }}"
Comment on lines +63 to +74
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.


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 }}
token: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }}
Comment on lines +82 to +86
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
- 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.


- name: Pin Rust version
run: |
sed -i -e "s/^RUST_VERSION .*/RUST_VERSION ?= ${{ inputs.rust-version }}/" \
constants.mk

- name: Update fact version
run: |
sed -i \
-e "/^version = / s/\".*\"/\"${{ inputs.version}}.0\"/" \
fact/Cargo.toml

cargo update -p fact

- name: Print git diff for validation
run: |
git diff

- name: Create Pull Request
if: ${{ ! inputs.dry-run }}
uses: peter-evans/create-pull-request@v8
with:
token: '${{ secrets.RHACS_BOT_GITHUB_TOKEN }}'
commit-message: 'chore: pin Rust version and update fact version'
committer: '${{ secrets.RHACS_BOT_GITHUB_USERNAME }} <${{ secrets.RHACS_BOT_GITHUB_EMAIL }}>'
author: '${{ secrets.RHACS_BOT_GITHUB_USERNAME }} <${{ secrets.RHACS_BOT_GITHUB_EMAIL }}>'
branch: chore/pin-rust-update-version-${{ inputs.version }}
signoff: false
delete-branch: true
title: 'chore: pin Rust version and update fact version'
body: |
Pin Rust version to ${{ inputs.rust-version }} and update fact to version ${{ inputs.version }}
team-reviewers: |
collector-team
draft: false

update-version:
runs-on: ubuntu-24.04
needs:
- validate-version
steps:
Comment on lines +123 to +127
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
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.

- uses: actions/checkout@v6
with:
submodules: false
ref: main
token: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }}

- name: Update CHANGELOG.md
run: |
sed -i \
-e "s/^## Next/&\n\n## ${{ inputs.version }}.0/" \
CHANGELOG.md

- name: Update fact version
run: |
sed -i \
-e "/^version = / s/\".*\"/\"${{ inputs.next-version }}.0-dev\"/" \
fact/Cargo.toml

cargo update -p fact

- name: Print git diff for validation
run: |
git diff

- name: Create Pull Request
if: ${{ ! inputs.dry-run }}
uses: peter-evans/create-pull-request@v8
with:
token: '${{ secrets.RHACS_BOT_GITHUB_TOKEN }}'
commit-message: 'chore: update CHANGELOG.md and fact version'
committer: '${{ secrets.RHACS_BOT_GITHUB_USERNAME }} <${{ secrets.RHACS_BOT_GITHUB_EMAIL }}>'
author: '${{ secrets.RHACS_BOT_GITHUB_USERNAME }} <${{ secrets.RHACS_BOT_GITHUB_EMAIL }}>'
branch: chore/update-changelog-fact-${{ inputs.next-version }}-dev
signoff: false
delete-branch: true
title: 'chore(docs): Update CHANGELOG.md and fact version'
body: |
Cut the CHANGELOG.md changes and update fact to version ${{ inputs.next-version }}-dev
team-reviewers: |
collector-team
draft: false
60 changes: 60 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Release new version

on:
workflow_dispatch:
inputs:
version:
description: |
The release version in <Major>.<minor> format.
required: true
type: string
dry-run:
description: Do not push anything
default: true
type: boolean

jobs:
release:
runs-on: ubuntu-24.04
env:
VERSION: ${{ inputs.version }}
steps:
- uses: actions/checkout@v6
with:
submodules: true
fetch-depth: 0
ref: release-${{ inputs.version }}
token: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }}

- 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"
Comment on lines +29 to +44
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
- 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: Initialize mandatory git config
run: |
git config user.name "${{ github.event.sender.login }}"
git config user.email noreply@github.com

- 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}"
Comment on lines +51 to +60
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

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.

Suggested change
- 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.

Loading