feat: automate releases via workflow_dispatch#151
Conversation
📝 WalkthroughWalkthroughThis PR moves automated tag-based release steps out of build.yml into a manual ChangesRelease Workflow Migration and Dev Defaults
Sequence DiagramsequenceDiagram
participant User
participant ReleaseWF as release.yml (manual)
participant BuildJob as build-and-upload
participant Quay as Quay Registry
participant GitHub as GitHub API
User->>ReleaseWF: workflow_dispatch(version, skills_ref)
ReleaseWF->>ReleaseWF: authorize actor & validate version
ReleaseWF->>BuildJob: start amd64 & arm64 builds
BuildJob->>BuildJob: make oci-build & make oci-save (amd64/arm64), upload artifacts
BuildJob-->>Quay: artifacts ready
Quay->>Quay: load/push per-arch images, build/push manifest (version)
Quay->>Quay: build/push manifest (latest)
ReleaseWF->>GitHub: gh release create v{version}
GitHub-->>User: release published
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
README.md (1)
153-156:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate
CLAUDIO_IMAGEdefault description to match template behavior.README still says the default is “current release version”, but
integrations/gitlab-ci/claudio.ymlnow defaults toquay.io/aipcc-cicd/claudio:latest.🤖 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 `@README.md` around lines 153 - 156, Update the README's "Available variables" entry for CLAUDIO_IMAGE to reflect the actual default value used by the CI template: replace "override the claudio image (default: current release version)" with a line stating the real default "override the claudio image (default: quay.io/aipcc-cicd/claudio:latest)" so CLAUDIO_IMAGE accurately documents the template behavior.
🤖 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/release.yml:
- Line 33: Replace all floating GitHub Actions refs with immutable commit SHAs
(or other pinned refs) for each usage of the actions listed:
actions/checkout@v6, actions/upload-artifact@v7, actions/download-artifact@v8,
and docker/login-action@v4; locate every occurrence of those strings in the
workflow files and update the uses: lines to a full commit SHA or pinned tag
(e.g., actions/checkout@<commit-sha>) and ensure consistency across release.yml,
push-pr-images.yml, and build.yml.
- Around line 32-33: The checkout steps using actions/checkout@v6 are leaving
the token persisted; update each actions/checkout@v6 step to include a with:
block setting persist-credentials: false so the GITHUB_TOKEN is not left
available to later steps or artifacts (i.e., add "with: persist-credentials:
false" under each actions/checkout@v6 invocation).
In `@README.md`:
- Around line 191-194: Step 3 in the patch-release steps conflicts with the
automated release workflow: remove or replace the manual tagging instruction
"git tag v0.7.1 && git push origin v0.7.1 release-0.7" and instead instruct
contributors to push only the release branch (e.g., "git push origin
release-0.7") and then trigger the release workflow ("Run the release workflow
from the release branch") so the workflow creates and pushes the tag/release
automatically; alternatively, make the step conditional (only tag manually if
the automated workflow is disabled).
---
Outside diff comments:
In `@README.md`:
- Around line 153-156: Update the README's "Available variables" entry for
CLAUDIO_IMAGE to reflect the actual default value used by the CI template:
replace "override the claudio image (default: current release version)" with a
line stating the real default "override the claudio image (default:
quay.io/aipcc-cicd/claudio:latest)" so CLAUDIO_IMAGE accurately documents the
template behavior.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 7a287990-01eb-44aa-a1dc-3d06629f0f3c
📒 Files selected for processing (7)
.github/workflows/build.yml.github/workflows/release.ymlMakefileREADME.mdintegrations/gitlab-ci/claudio.ymlintegrations/gitlab-ci/template/claudio.ymlrenovate.json
💤 Files with no reviewable changes (2)
- integrations/gitlab-ci/template/claudio.yml
- renovate.json
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v6 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify all unpinned action references in workflows.
rg -nP '^\s*uses:\s*[^@]+@v[0-9]+' .github/workflowsRepository: aipcc-cicd/claudio
Length of output: 1116
Pin GitHub Actions uses: to immutable commit SHAs
Workflow steps use floating version tags (not commit SHAs). Update each uses: to a full commit SHA (or other pinned ref) in:
.github/workflows/release.yml: 33 (actions/checkout@v6), 49 (actions/upload-artifact@v7), 63 (actions/checkout@v6), 66 (actions/download-artifact@v8), 71 (docker/login-action@v4).github/workflows/push-pr-images.yml: 29 (actions/checkout@v6), 32 (actions/download-artifact@v8), 80 (docker/login-action@v4).github/workflows/build.yml: 28 (actions/checkout@v6), 51 (actions/upload-artifact@v7), 64 (actions/download-artifact@v8), 73 (actions/upload-artifact@v7), 89 (actions/checkout@v6), 92 (actions/download-artifact@v8), 97 (docker/login-action@v4)
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 32-33: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 33-33: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 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 at line 33, Replace all floating GitHub
Actions refs with immutable commit SHAs (or other pinned refs) for each usage of
the actions listed: actions/checkout@v6, actions/upload-artifact@v7,
actions/download-artifact@v8, and docker/login-action@v4; locate every
occurrence of those strings in the workflow files and update the uses: lines to
a full commit SHA or pinned tag (e.g., actions/checkout@<commit-sha>) and ensure
consistency across release.yml, push-pr-images.yml, and build.yml.
jrusz
left a comment
There was a problem hiding this comment.
Self-review — 4 findings (2 major, 2 minor).
Minor (outside diff) — README.md:155: CLAUDIO_IMAGE description says "(default: current release version)" but the actual default is now quay.io/aipcc-cicd/claudio:latest. Should match reality.
d42c636 to
fb057f5
Compare
fb057f5 to
48b7fd2
Compare
4934b6d to
7846e90
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
.github/workflows/release.yml (1)
1-113:⚠️ Potential issue | 🟠 Major | ⚡ Quick winSet explicit workflow-level and job-level permissions.
The workflow lacks an explicit top-level
permissions:block, and thebuild-and-uploadjob inherits default (permissive) permissions. Setpermissions: {}at the workflow level and grant minimal permissions explicitly at each job level to follow the principle of least privilege.🔒 Proposed fix
name: Release +permissions: {} + on: workflow_dispatch:jobs: build-and-upload: name: Build Images runs-on: ${{ matrix.runner }} + permissions: + contents: read strategy:🤖 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 1 - 113, Add an explicit workflow-level permissions block and tighten each job to least privilege: add a top-level line permissions: {} under env, then add permissions: contents: read to the build-and-upload job (it only checks out code and uploads artifacts), add permissions: contents: read to the push-quay job (it only needs read access for checkout/download), and leave the create-release job's existing permissions: contents: write as-is; reference the job identifiers build-and-upload, push-quay and create-release to locate where to add these permissions.Containerfile (1)
88-96:⚠️ Potential issue | 🔴 CriticalFix Claude plugin ref syntax for branch installs in Containerfile
- In
claude plugin marketplace add,#<ref>is for full Git repo URLs, whileowner/reposhorthands must use@<ref>—so the branch caseaipcc-cicd/claudio-skills#${CS_REF}should beaipcc-cicd/claudio-skills@${CS_REF}.- Keep the existing
@${CS_REF}usage for tags/commits.🤖 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 `@Containerfile` around lines 88 - 96, The branch-install branch of the conditional uses the wrong ref separator: replace the marketplace add call that currently uses "aipcc-cicd/claudio-skills#${CS_REF}" with the shorthand form using "@" so it becomes "claude plugin marketplace add aipcc-cicd/claudio-skills@${CS_REF}" in the Containerfile; keep the existing "@${CS_REF}" usage for the other branch/commit/tag case and leave the PR/local install branch unchanged (refer to CS_REF_TYPE, CS_REF and the claude plugin marketplace add invocation to locate the lines to change).
🧹 Nitpick comments (1)
integrations/gitlab-ci/claudio.yml (1)
26-26: The:latesttag introduces non-reproducibility risk.Using
:latestmeans downstream CI pipelines will automatically pick up new claudio releases, which could introduce breaking changes or unexpected behavior. While the template allows users to overrideCLAUDIO_IMAGEfor pinning, consider documenting best practices in the comment block (lines 16-18) to recommend explicit version pinning for production pipelines.🤖 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 `@integrations/gitlab-ci/claudio.yml` at line 26, The CLAUDIO_IMAGE default uses the unstable ":latest" tag which risks non-reproducible CI runs; update the template so the comment block that explains CLAUDIO_IMAGE recommends explicit version pinning for production (e.g., use a specific semver tag or digest) and optionally change the default value from "quay.io/aipcc-cicd/claudio:latest" to a pinned example like "quay.io/aipcc-cicd/claudio:vX.Y.Z" to encourage reproducible builds; reference the CLAUDIO_IMAGE variable in your edits and update the surrounding comment to document best-practices for pinning.
🤖 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/release.yml:
- Around line 104-112: The release step "Create release and tag" is vulnerable
because it expands `${{ inputs.version }}` directly into the shell; fix by
binding the input to an environment variable (e.g., RELEASE_VERSION: ${{
inputs.version }}) and then invoking the gh command with the env var properly
quoted (use "$RELEASE_VERSION" for the positional release name and for --title)
so the shell treats it as a single safe string; update the run that calls gh
release create to reference "$RELEASE_VERSION" (and keep other args quoted)
instead of expanding `${{ inputs.version }}` inline.
---
Outside diff comments:
In @.github/workflows/release.yml:
- Around line 1-113: Add an explicit workflow-level permissions block and
tighten each job to least privilege: add a top-level line permissions: {} under
env, then add permissions: contents: read to the build-and-upload job (it only
checks out code and uploads artifacts), add permissions: contents: read to the
push-quay job (it only needs read access for checkout/download), and leave the
create-release job's existing permissions: contents: write as-is; reference the
job identifiers build-and-upload, push-quay and create-release to locate where
to add these permissions.
In `@Containerfile`:
- Around line 88-96: The branch-install branch of the conditional uses the wrong
ref separator: replace the marketplace add call that currently uses
"aipcc-cicd/claudio-skills#${CS_REF}" with the shorthand form using "@" so it
becomes "claude plugin marketplace add aipcc-cicd/claudio-skills@${CS_REF}" in
the Containerfile; keep the existing "@${CS_REF}" usage for the other
branch/commit/tag case and leave the PR/local install branch unchanged (refer to
CS_REF_TYPE, CS_REF and the claude plugin marketplace add invocation to locate
the lines to change).
---
Nitpick comments:
In `@integrations/gitlab-ci/claudio.yml`:
- Line 26: The CLAUDIO_IMAGE default uses the unstable ":latest" tag which risks
non-reproducible CI runs; update the template so the comment block that explains
CLAUDIO_IMAGE recommends explicit version pinning for production (e.g., use a
specific semver tag or digest) and optionally change the default value from
"quay.io/aipcc-cicd/claudio:latest" to a pinned example like
"quay.io/aipcc-cicd/claudio:vX.Y.Z" to encourage reproducible builds; reference
the CLAUDIO_IMAGE variable in your edits and update the surrounding comment to
document best-practices for pinning.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ed853549-d46b-40f6-8e86-c70c3ec2d8d4
📒 Files selected for processing (8)
.github/workflows/build.yml.github/workflows/release.ymlContainerfileMakefileREADME.mdintegrations/gitlab-ci/claudio.ymlintegrations/gitlab-ci/template/claudio.ymlrenovate.json
💤 Files with no reviewable changes (2)
- integrations/gitlab-ci/template/claudio.yml
- renovate.json
✅ Files skipped from review due to trivial changes (1)
- README.md
🚧 Files skipped from review as they are similar to previous changes (2)
- Makefile
- .github/workflows/build.yml
c4ba079 to
b36225d
Compare
| make oci-save | ||
|
|
||
| - name: Upload image artifact | ||
| uses: actions/upload-artifact@v7 |
There was a problem hiding this comment.
My claude is flagging that actions/upload-artifact@v7 and actions/download-artifact@v8 must be the same version.
There was a problem hiding this comment.
These are separate actions with independent version lines — they don't need to match. The existing build.yml (already working in CI) uses the same combination: upload-artifact@v7 + download-artifact@v8. The release workflow just mirrors what's already there.
|
Also here, as for the other PR, there isn't any check on the input, |
b36225d to
7026778
Compare
|
I remembered we talked in the past about having the same release version for claudio and claudio-skills. Did you even considered that in the design? |
Hm, not really. I'm not sure if the versions should actually match... We don't really have rules around version numbers, we just kinda subjectively decide which version to use where and when. The scope of this change is to get rid of the manual release process. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/release.yml:
- Around line 10-13: Add early validation of the skills_ref input inside the
authorize function so bad refs fail fast; mirror the existing version validation
logic but target the skills_ref parameter (e.g., check it matches the expected
tag format like starting with "v" and a semantic-version pattern such as
vMAJOR.MINOR.PATCH) and throw or return an error from authorize when the check
fails so the workflow stops before matrix builds start; update both authorize
code paths that currently validate version (the same block that inspects
version) to also validate skills_ref and produce a clear error message when
invalid.
- Around line 44-50: The "Check release does not exist" step uses `gh release
view "${INPUT_VERSION}"` without repo context and the `authorize` step doesn't
validate `inputs.skills_ref`; update the `Check release does not exist` step
(the step named "Check release does not exist") to call `gh release view
"${INPUT_VERSION}" --repo "${{ github.repository }}"` so it can resolve repo
context when `authorize` hasn't checked out code, and add a quick validation in
the `authorize` step to ensure `inputs.skills_ref` is present and well-formed
(non-empty and matches the expected ref pattern) before proceeding so invalid
`skills_ref` values fail fast with a clear error message.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 341c1f8f-c773-4e3f-976f-60d8087b3d51
📒 Files selected for processing (8)
.github/workflows/build.yml.github/workflows/release.ymlContainerfileMakefileREADME.mdintegrations/gitlab-ci/claudio.ymlintegrations/gitlab-ci/template/claudio.ymlrenovate.json
💤 Files with no reviewable changes (2)
- integrations/gitlab-ci/template/claudio.yml
- renovate.json
✅ Files skipped from review due to trivial changes (1)
- README.md
🚧 Files skipped from review as they are similar to previous changes (3)
- integrations/gitlab-ci/claudio.yml
- .github/workflows/build.yml
- Makefile
| - name: Check release does not exist | ||
| env: | ||
| GH_TOKEN: ${{ secrets.RELEASE_PAT }} | ||
| INPUT_VERSION: ${{ inputs.version }} | ||
| run: | | ||
| if gh release view "${INPUT_VERSION}" &>/dev/null; then | ||
| echo "::error::Release ${INPUT_VERSION} already exists" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
ls -la .github/workflows || true
sed -n '1,200p' .github/workflows/release.yml
echo '---'
# Show the exact lines around the referenced snippet
nl -ba .github/workflows/release.yml | sed -n '35,80p'Repository: aipcc-cicd/claudio
Length of output: 4522
🌐 Web query:
GitHub CLI gh release view infer repository without git checkout --repo or env variables GH_REPO GITHUB_REPOSITORY
💡 Result:
Yes—gh release view can infer the repository from the local working directory when you’re in a local git repo; otherwise you must provide the repository explicitly (e.g., with --repo or via the GH_REPO env var). 1) What gh release view supports - gh release view has a --repo option: “Select another repository using the [HOST/]OWNER/REPO format” [1]. - If you don’t provide a tag argument, it shows the latest release for the project in that repository [1]. 2) How it infers the repository (no checkout required) - In general, gh determines “the repository for the current directory” when you omit --repo [2]. - For environment-variable use (e.g., in CI), gh documents that GH_REPO can be used to specify the GitHub repository for commands that otherwise operate on a local repository [3]. 3) About GITHUB_REPOSITORY vs GH_REPO - GitHub Actions sets GITHUB_REPOSITORY, but gh historically reads GH_REPO (not GITHUB_REPOSITORY) [4]. - A design discussion notes the intended precedence order when multiple repo lookup mechanisms are present: 1) --repo flag, 2) GH_REPO env var, 3) local git repo, 4) GITHUB_REPOSITORY env var [4]. Practical answers to your exact question - If you want to avoid “git checkout” but still want gh to infer the repo, you can run the command from within any existing local clone of the repo (even if you’re not on the release tag you’re viewing). gh will infer from the current directory’s repository context [2]. - If you’re not in a local git working directory for that repo, you can’t rely on inference; provide --repo [1] or set GH_REPO [3]. - Setting GITHUB_REPOSITORY alone may not work unless gh is also configured to read it for your gh version; gh’s own issue discussion indicates it may be a lower-precedence fallback compared with GH_REPO and local git repo [4].
Citations:
- 1: https://man.archlinux.org/man/gh-release-view.1.en
- 2: https://cli.github.com/manual/gh_release_create
- 3: Add the ability to checkout the latest release using
gh release checkoutcli/cli#6119 - 4: Use gh cli to download Github Release from public repo. cli/cli#3820
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n "skills_ref" .github/workflows || true
rg -n "CS_REF|CS_REF_TYPE|Validate.*skills|skills tag|skills_ref.*validate" .github/workflows || trueRepository: aipcc-cicd/claudio
Length of output: 415
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n "skills_ref" . || true
rg -n "Invalid.*skills|skills.*invalid|validate.*skills|CS_REF" . || trueRepository: aipcc-cicd/claudio
Length of output: 1593
Pin repo context for gh release view and validate skills_ref.
authorizedoesn’t checkout code, so theCheck release does not existstep’sgh release view "${INPUT_VERSION}"can’t reliably infer repo context; pass--repo "${{ github.repository }}"so the duplicate-release gate works.inputs.skills_refisn’t validated (onlyinputs.versionis), so invalid refs fail later in the build/container steps with unclear errors—add a quick format/emptiness check inauthorize.
Suggested fix
- name: Check release does not exist
env:
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
INPUT_VERSION: ${{ inputs.version }}
run: |
- if gh release view "${INPUT_VERSION}" &>/dev/null; then
+ if gh release view "${INPUT_VERSION}" --repo "${{ github.repository }}" &>/dev/null; then
echo "::error::Release ${INPUT_VERSION} already exists"
exit 1
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.
| - name: Check release does not exist | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_PAT }} | |
| INPUT_VERSION: ${{ inputs.version }} | |
| run: | | |
| if gh release view "${INPUT_VERSION}" &>/dev/null; then | |
| echo "::error::Release ${INPUT_VERSION} already exists" | |
| - name: Check release does not exist | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_PAT }} | |
| INPUT_VERSION: ${{ inputs.version }} | |
| run: | | |
| if gh release view "${INPUT_VERSION}" --repo "${{ github.repository }}" &>/dev/null; then | |
| echo "::error::Release ${INPUT_VERSION} already exists" | |
| exit 1 | |
| 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/release.yml around lines 44 - 50, The "Check release does
not exist" step uses `gh release view "${INPUT_VERSION}"` without repo context
and the `authorize` step doesn't validate `inputs.skills_ref`; update the `Check
release does not exist` step (the step named "Check release does not exist") to
call `gh release view "${INPUT_VERSION}" --repo "${{ github.repository }}"` so
it can resolve repo context when `authorize` hasn't checked out code, and add a
quick validation in the `authorize` step to ensure `inputs.skills_ref` is
present and well-formed (non-empty and matches the expected ref pattern) before
proceeding so invalid `skills_ref` values fail fast with a clear error message.
| claude plugin marketplace add aipcc-cicd/claudio-skills@${CS_REF}; \ | ||
| elif [ "${CS_REF_TYPE}" != "pr" ]; then \ | ||
| claude plugin marketplace add aipcc-cicd/claudio-skills@v${CS_REF}; \ | ||
| claude plugin marketplace add aipcc-cicd/claudio-skills@${CS_REF}; \ |
There was a problem hiding this comment.
I added one if-else branch because of syntax difference. According to docs, the at sign is correct so you don't need to repeat the same command twice, it's enough to handle != "pr"
There was a problem hiding this comment.
Good catch — after the # → @ fix both branches were doing the same thing. Simplified to just check for pr (local install) vs everything else (@${CS_REF}).
7026778 to
7c7d733
Compare
- Add release.yml workflow: accepts version + skills_ref inputs, builds multi-arch images, pushes to Quay, creates GitHub Release - Remove tag trigger, push-quay, and create-release from build.yml (releases now fully owned by the new workflow) - Set Makefile defaults to dev mode: VERSION=dev, CS_REF=main (main always tracks latest claudio-skills, no manual bumps) - Replace generated integrations template with static file defaulting CLAUDIO_IMAGE to latest (consumers override to pin) - Remove CS_REF renovate manager (no longer a versioned ref) - Update README with new release process docs 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jakub Rusz <jrusz@redhat.com>
7c7d733 to
145bc03
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/release.yml:
- Around line 35-47: The authorize job currently only validates inputs and
membership but doesn't prevent workflow_dispatch from running against arbitrary
refs, so add a gate that verifies the workflow was triggered for an allowed ref
(e.g., refs/heads/main or an allowlist) before proceeding to release creation;
implement this by adding a step in the authorize job (near the existing
"Validate inputs" step) that reads github.ref (or GITHUB_REF) and checks it
matches "refs/heads/main" or matches an allowlist variable (e.g., ALLOWED_REFS)
and fails with an error if not matched, so that the later create-release step
(which runs gh release create --target ${{ github.sha }}) cannot create releases
for disallowed branches.
- Around line 27-33: The Verify team membership step currently treats any
membership record as valid; change the script to capture the JSON output of gh
api "orgs/aipcc-cicd/teams/aipcc-productization/memberships/${ACTOR}" into a
variable, parse the membership state (e.g., using jq or gh api --jq '.state'),
and only succeed when the state equals "active" (otherwise echo an error and
exit 1). Ensure the step still uses the GH_TOKEN/ACTOR env vars and clearly logs
the actor and the returned state when rejecting non-active memberships.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f7bc90d2-772c-4a40-8ad8-b4c8ac6c92ae
📒 Files selected for processing (8)
.github/workflows/build.yml.github/workflows/release.ymlContainerfileMakefileREADME.mdintegrations/gitlab-ci/claudio.ymlintegrations/gitlab-ci/template/claudio.ymlrenovate.json
💤 Files with no reviewable changes (2)
- renovate.json
- integrations/gitlab-ci/template/claudio.yml
✅ Files skipped from review due to trivial changes (2)
- integrations/gitlab-ci/claudio.yml
- README.md
🚧 Files skipped from review as they are similar to previous changes (3)
- Containerfile
- Makefile
- .github/workflows/build.yml
| - name: Verify team membership | ||
| env: | ||
| GH_TOKEN: ${{ secrets.RELEASE_PAT }} | ||
| ACTOR: ${{ github.actor }} | ||
| run: | | ||
| gh api "orgs/aipcc-cicd/teams/aipcc-productization/memberships/${ACTOR}" --silent \ | ||
| || (echo "::error::${ACTOR} is not a member of aipcc-cicd/aipcc-productization" && exit 1) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the referenced portion of the workflow (with line numbers)
nl -ba .github/workflows/release.yml | sed -n '1,120p'
# Narrow to the Verify team membership step (lines 20-60 if present)
nl -ba .github/workflows/release.yml | sed -n '20,70p'
# Show any "authorize" job/steps to confirm how this check is used
rg -n "authorize|Verify team membership|team membership|memberships/" .github/workflows/release.ymlRepository: aipcc-cicd/claudio
Length of output: 105
🌐 Web query:
GitHub REST API team memberships endpoint response fields state active pending
💡 Result:
In the GitHub REST API, the state field within team and organization membership objects indicates the current status of the user's membership [1][2][3]. This field is a string with two possible values: active and pending [1][3][4]. The pending state typically indicates that an invitation has been sent to the user, but they have not yet accepted it [1][4]. Once the user accepts the invitation, the state transitions to active [1]. Key API endpoints that include this state field include: - Get team membership for a user: GET /orgs/{org}/teams/{team_slug}/memberships/{username} [1][2] - Get organization membership for a user: GET /orgs/{org}/memberships/{username} [3][4] - List organization memberships for the authenticated user: GET /user/memberships/orgs [5] When querying organization memberships, if a state parameter is available in the request, it can be used to filter results; if left unspecified, the API commonly returns both active and pending memberships [3][5].
Citations:
- 1: https://docs.github.com/en/rest/teams/members?apiVersion=2026-03-10
- 2: https://docs.github.com/rest/teams/members
- 3: https://docs.github.com/v3/orgs/members
- 4: https://github.apidog.io/api-3489080
- 5: https://docs.github.com/en/enterprise-server@3.8/rest/orgs/members
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Verify team membership step context ==="
# Show a small window around the step by line numbers (cat -n since nl is unavailable)
cat -n .github/workflows/release.yml | sed -n '1,120p' | sed -n '/Verify team membership/,+20p'
echo "=== Exact step block ==="
rg -n --context=2 "name: Verify team membership|memberships/\\$\\{ACTOR\\}|GH_TOKEN: \\$\\{\\{ secrets\\.RELEASE_PAT \\}\\}" .github/workflows/release.ymlRepository: aipcc-cicd/claudio
Length of output: 1776
🏁 Script executed:
rg -n "\bjq\b|--jq" .github/workflows/release.ymlRepository: aipcc-cicd/claudio
Length of output: 44
Require an active team membership (not just any membership record).
The “Verify team membership” step currently authorizes on any successful response from gh api .../memberships/${ACTOR} and never checks the membership state (active vs pending), so a pending membership could still pass.
Suggested fix
- name: Verify team membership
env:
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
ACTOR: ${{ github.actor }}
run: |
- gh api "orgs/aipcc-cicd/teams/aipcc-productization/memberships/${ACTOR}" --silent \
- || (echo "::error::${ACTOR} is not a member of aipcc-cicd/aipcc-productization" && exit 1)
+ membership_state="$(gh api "orgs/aipcc-cicd/teams/aipcc-productization/memberships/${ACTOR}" --jq '.state' 2>/dev/null || true)"
+ if [[ "${membership_state}" != "active" ]]; then
+ echo "::error::${ACTOR} does not have an active aipcc-cicd/aipcc-productization membership"
+ exit 1
+ 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/release.yml around lines 27 - 33, The Verify team
membership step currently treats any membership record as valid; change the
script to capture the JSON output of gh api
"orgs/aipcc-cicd/teams/aipcc-productization/memberships/${ACTOR}" into a
variable, parse the membership state (e.g., using jq or gh api --jq '.state'),
and only succeed when the state equals "active" (otherwise echo an error and
exit 1). Ensure the step still uses the GH_TOKEN/ACTOR env vars and clearly logs
the actor and the returned state when rejecting non-active memberships.
| - name: Validate inputs | ||
| env: | ||
| INPUT_VERSION: ${{ inputs.version }} | ||
| INPUT_SKILLS_REF: ${{ inputs.skills_ref }} | ||
| run: | | ||
| if [[ ! "${INPUT_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then | ||
| echo "::error::Invalid version '${INPUT_VERSION}'. Expected format: v0.8.0 or v0.8.0-rc1" | ||
| exit 1 | ||
| fi | ||
| if [[ ! "${INPUT_SKILLS_REF}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then | ||
| echo "::error::Invalid skills_ref '${INPUT_SKILLS_REF}'. Expected format: v0.5.5 or v0.5.5-rc1" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
ls -la
fd -a -t f "release.yml" .github/workflows || true
sed -n '1,200p' .github/workflows/release.ymlRepository: aipcc-cicd/claudio
Length of output: 5418
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n "authorize|gh release create|--target|workflow_dispatch|ref_name|github\\.sha|target \"\\$\\{\\{ github\\.sha \\}\\}\"" .github/workflows/release.yml
sed -n '200,400p' .github/workflows/release.ymlRepository: aipcc-cicd/claudio
Length of output: 221
Restrict manual release runs to an allowed ref (e.g., main) before creating the GitHub release
workflow_dispatch has no branch restriction, and the authorize job only validates inputs + team membership. Since create-release uses gh release create ... --target ${{ github.sha }}, a release will be created for the SHA from whatever branch the operator chose. Add a ref/name gate in authorize (main or allowlist).
Suggested fix
- name: Validate inputs
env:
+ INPUT_REF_NAME: ${{ github.ref_name }}
INPUT_VERSION: ${{ inputs.version }}
INPUT_SKILLS_REF: ${{ inputs.skills_ref }}
run: |
+ if [[ "${INPUT_REF_NAME}" != "main" ]]; then
+ echo "::error::Releases must be cut from 'main'. Current ref: '${INPUT_REF_NAME}'"
+ exit 1
+ fi
if [[ ! "${INPUT_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
echo "::error::Invalid version '${INPUT_VERSION}'. Expected format: v0.8.0 or v0.8.0-rc1"
exit 1
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/release.yml around lines 35 - 47, The authorize job
currently only validates inputs and membership but doesn't prevent
workflow_dispatch from running against arbitrary refs, so add a gate that
verifies the workflow was triggered for an allowed ref (e.g., refs/heads/main or
an allowlist) before proceeding to release creation; implement this by adding a
step in the authorize job (near the existing "Validate inputs" step) that reads
github.ref (or GITHUB_REF) and checks it matches "refs/heads/main" or matches an
allowlist variable (e.g., ALLOWED_REFS) and fails with an error if not matched,
so that the later create-release step (which runs gh release create --target ${{
github.sha }}) cannot create releases for disallowed branches.
Summary
Replaces the manual release process (cut commits, version bumps, tag pushes) with a single
workflow_dispatchtrigger. Followup on this Slack thread.release.ymlworkflow: acceptsversion+skills_refinputs → builds multi-arch images → pushes to Quay → creates git tag + GitHub Release. Zero manual commits.build.ymlsimplified: tag trigger and Quay push jobs removed (now owned by release workflow). Only handles PR and main branch builds to GHCR.VERSION=dev,CS_REF_TYPE=branch,CS_REF=main. Main always tracks latest claudio-skills. No more forgotten version bumps.CLAUDIO_IMAGEdefaulting tolatest. Consumers who need pinning setCLAUDIO_IMAGEexplicitly. Removedmake integrations-update.mainbranch, not a versioned tag.New release flow
0.8.0) and claudio-skills ref (e.g.0.5.5)Patch releases (Z-streams)
Create a release branch retroactively from the tag, cherry-pick fixes, tag manually.
Supersedes #137.
Test plan
make oci-buildworks with default Makefile values (CS_REF=main)VERSION=0.8.0 CS_REF_TYPE=tag CS_REF=0.5.5 make oci-build🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Changes
Removals
Documentation