Skip to content

feat: automate releases via workflow_dispatch#151

Merged
jrusz merged 1 commit into
aipcc-cicd:mainfrom
jrusz:worktree-impl-claudio-release-automation
May 27, 2026
Merged

feat: automate releases via workflow_dispatch#151
jrusz merged 1 commit into
aipcc-cicd:mainfrom
jrusz:worktree-impl-claudio-release-automation

Conversation

@jrusz

@jrusz jrusz commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Replaces the manual release process (cut commits, version bumps, tag pushes) with a single workflow_dispatch trigger. Followup on this Slack thread.

  • New release.yml workflow: accepts version + skills_ref inputs → builds multi-arch images → pushes to Quay → creates git tag + GitHub Release. Zero manual commits.
  • build.yml simplified: tag trigger and Quay push jobs removed (now owned by release workflow). Only handles PR and main branch builds to GHCR.
  • Makefile permanently in dev mode: VERSION=dev, CS_REF_TYPE=branch, CS_REF=main. Main always tracks latest claudio-skills. No more forgotten version bumps.
  • Integrations template simplified: merged template into static file with CLAUDIO_IMAGE defaulting to latest. Consumers who need pinning set CLAUDIO_IMAGE explicitly. Removed make integrations-update.
  • Renovate CS_REF manager removed: no longer applicable since main tracks main branch, not a versioned tag.

New release flow

  1. Go to Actions → Release → Run workflow
  2. Enter version (e.g. 0.8.0) and claudio-skills ref (e.g. 0.5.5)
  3. Done — CI handles everything

Patch releases (Z-streams)

Create a release branch retroactively from the tag, cherry-pick fixes, tag manually.

Supersedes #137.

Test plan

  • Verify make oci-build works with default Makefile values (CS_REF=main)
  • Verify env var override: VERSION=0.8.0 CS_REF_TYPE=tag CS_REF=0.5.5 make oci-build
  • After merge: trigger release workflow with a test version and verify end-to-end
  • Verify downstream CI template still works (CLAUDIO_IMAGE override)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a manual Release workflow to build multi-arch images and publish GitHub releases.
  • Changes

    • CI no longer auto-publishes on tag pushes; publishing moved to the manual workflow with gated authorization.
    • Default local/dev image tag now used; downstream CI defaults to :latest.
    • Image tagging defaults set to "dev" for local builds.
  • Removals

    • Removed legacy integrations-update step and reusable GitLab CI job/template.
  • Documentation

    • README updated with new release and testing guidance.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR moves automated tag-based release steps out of build.yml into a manual .github/workflows/release.yml, removes tag triggers and automated Quay/GitHub jobs from build.yml, updates Makefile/Containerfile defaults for dev usage, and updates CI templates, Renovate config, and docs.

Changes

Release Workflow Migration and Dev Defaults

Layer / File(s) Summary
Manual release workflow and jobs
.github/workflows/release.yml
Adds a workflow_dispatch Release workflow with version and skills_ref inputs that authorizes the actor, builds amd64/arm64 OCI images, uploads artifacts, pushes per-arch images and a multi-arch manifest to Quay (and latest), and creates a GitHub Release.
Build workflow cleanup
.github/workflows/build.yml
Removes v* push filter, deletes Quay global env vars, changes image selection branching to check github.event_name == "pull_request", and removes automated push-quay/create-release jobs.
Build defaults and Containerfile
Makefile, Containerfile
VERSION default → dev; IMAGE_TAG stops prefixing v; CS_REF_TYPE/CS_REF defaults → branch/main; removed integrations-update target; Containerfile uses aipcc-cicd/claudio-skills@${CS_REF} for non-PR refs.
Docs, GitLab template, Renovate
README.md, integrations/gitlab-ci/claudio.yml, integrations/gitlab-ci/template/claudio.yml, renovate.json
README updated for manual release flow and dev image examples; GitLab template CLAUDIO_IMAGE default → quay.io/aipcc-cicd/claudio:latest; removed .claudio template from template/claudio.yml; removed Claudio Skills custom manager from renovate.json.

Sequence Diagram

sequenceDiagram
  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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • ktdreyer
  • rishupk

Poem

🐇 I hopped from tags to manual cheer,
A button pressed — a release draws near.
Dev defaults snug, templates aligned,
Artifacts packed, manifests signed.
Hop — a tidy flow: release by hand, refined.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: automating releases via workflow_dispatch instead of manual processes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 win

Update CLAUDIO_IMAGE default description to match template behavior.

README still says the default is “current release version”, but integrations/gitlab-ci/claudio.yml now defaults to quay.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

📥 Commits

Reviewing files that changed from the base of the PR and between cd655b5 and d42c636.

📒 Files selected for processing (7)
  • .github/workflows/build.yml
  • .github/workflows/release.yml
  • Makefile
  • README.md
  • integrations/gitlab-ci/claudio.yml
  • integrations/gitlab-ci/template/claudio.yml
  • renovate.json
💤 Files with no reviewable changes (2)
  • integrations/gitlab-ci/template/claudio.yml
  • renovate.json

Comment thread .github/workflows/release.yml

steps:
- name: Checkout code
uses: actions/checkout@v6

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify all unpinned action references in workflows.
rg -nP '^\s*uses:\s*[^@]+@v[0-9]+' .github/workflows

Repository: 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.

Comment thread README.md Outdated

@jrusz jrusz left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Comment thread README.md Outdated
Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml Outdated
@jrusz jrusz force-pushed the worktree-impl-claudio-release-automation branch from d42c636 to fb057f5 Compare May 26, 2026 19:31
@jrusz jrusz marked this pull request as draft May 26, 2026 20:01
@jrusz jrusz force-pushed the worktree-impl-claudio-release-automation branch from fb057f5 to 48b7fd2 Compare May 27, 2026 05:14
@jrusz jrusz force-pushed the worktree-impl-claudio-release-automation branch 2 times, most recently from 4934b6d to 7846e90 Compare May 27, 2026 07:10
@jrusz jrusz marked this pull request as ready for review May 27, 2026 07:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 win

Set explicit workflow-level and job-level permissions.

The workflow lacks an explicit top-level permissions: block, and the build-and-upload job inherits default (permissive) permissions. Set permissions: {} 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 | 🔴 Critical

Fix Claude plugin ref syntax for branch installs in Containerfile

  • In claude plugin marketplace add, #<ref> is for full Git repo URLs, while owner/repo shorthands must use @<ref>—so the branch case aipcc-cicd/claudio-skills#${CS_REF} should be aipcc-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 :latest tag introduces non-reproducibility risk.

Using :latest means downstream CI pipelines will automatically pick up new claudio releases, which could introduce breaking changes or unexpected behavior. While the template allows users to override CLAUDIO_IMAGE for 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

📥 Commits

Reviewing files that changed from the base of the PR and between d42c636 and 7846e90.

📒 Files selected for processing (8)
  • .github/workflows/build.yml
  • .github/workflows/release.yml
  • Containerfile
  • Makefile
  • README.md
  • integrations/gitlab-ci/claudio.yml
  • integrations/gitlab-ci/template/claudio.yml
  • renovate.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

Comment thread .github/workflows/release.yml
@jrusz jrusz force-pushed the worktree-impl-claudio-release-automation branch 2 times, most recently from c4ba079 to b36225d Compare May 27, 2026 07:55
make oci-save

- name: Upload image artifact
uses: actions/upload-artifact@v7

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

My claude is flagging that actions/upload-artifact@v7 and actions/download-artifact@v8 must be the same version.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

@gnaponie

gnaponie commented May 27, 2026

Copy link
Copy Markdown
Collaborator

Also here, as for the other PR, there isn't any check on the input, version or skills-ref have no validation.

@jrusz jrusz force-pushed the worktree-impl-claudio-release-automation branch from b36225d to 7026778 Compare May 27, 2026 08:43
@gnaponie

Copy link
Copy Markdown
Collaborator

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?

@jrusz

jrusz commented May 27, 2026

Copy link
Copy Markdown
Contributor Author

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7846e90 and 7026778.

📒 Files selected for processing (8)
  • .github/workflows/build.yml
  • .github/workflows/release.yml
  • Containerfile
  • Makefile
  • README.md
  • integrations/gitlab-ci/claudio.yml
  • integrations/gitlab-ci/template/claudio.yml
  • renovate.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

Comment thread .github/workflows/release.yml
Comment on lines +44 to +50
- 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"

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

🧩 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:


🏁 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 || true

Repository: 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" . || true

Repository: aipcc-cicd/claudio

Length of output: 1593


Pin repo context for gh release view and validate skills_ref.

  • authorize doesn’t checkout code, so the Check release does not exist step’s gh release view "${INPUT_VERSION}" can’t reliably infer repo context; pass --repo "${{ github.repository }}" so the duplicate-release gate works.
  • inputs.skills_ref isn’t validated (only inputs.version is), so invalid refs fail later in the build/container steps with unclear errors—add a quick format/emptiness check in authorize.
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.

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

Comment thread Containerfile Outdated
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}; \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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}).

@jrusz jrusz force-pushed the worktree-impl-claudio-release-automation branch from 7026778 to 7c7d733 Compare May 27, 2026 09:23
Comment thread .github/workflows/release.yml Outdated
- 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>
@jrusz jrusz force-pushed the worktree-impl-claudio-release-automation branch from 7c7d733 to 145bc03 Compare May 27, 2026 10:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7026778 and 145bc03.

📒 Files selected for processing (8)
  • .github/workflows/build.yml
  • .github/workflows/release.yml
  • Containerfile
  • Makefile
  • README.md
  • integrations/gitlab-ci/claudio.yml
  • integrations/gitlab-ci/template/claudio.yml
  • renovate.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

Comment on lines +27 to +33
- 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)

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

🧩 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.yml

Repository: 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:


🏁 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.yml

Repository: aipcc-cicd/claudio

Length of output: 1776


🏁 Script executed:

rg -n "\bjq\b|--jq" .github/workflows/release.yml

Repository: 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.

Comment on lines +35 to +47
- 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

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

🧩 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.yml

Repository: 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.yml

Repository: 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.

@jrusz jrusz merged commit f7420fc into aipcc-cicd:main May 27, 2026
6 checks passed
@jrusz jrusz deleted the worktree-impl-claudio-release-automation branch May 28, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants