-
Notifications
You must be signed in to change notification settings - Fork 7
feat: automate releases via workflow_dispatch #151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,159 @@ | ||||||||||||||||||||||||||||||||||
| name: Release | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||||||||
| version: | ||||||||||||||||||||||||||||||||||
| description: 'Release version (e.g. v0.8.0)' | ||||||||||||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||||||
| skills_ref: | ||||||||||||||||||||||||||||||||||
| description: 'claudio-skills tag to pin (e.g. v0.5.5)' | ||||||||||||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| permissions: {} | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||
| QUAY_REGISTRY: quay.io | ||||||||||||||||||||||||||||||||||
| QUAY_IMAGE_REPO: quay.io/aipcc-cicd/claudio | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||
| authorize: | ||||||||||||||||||||||||||||||||||
| name: Authorize | ||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-24.04 | ||||||||||||||||||||||||||||||||||
| environment: release | ||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||
| - 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) | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+27
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 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:
💡 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.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 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 |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - 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 | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+35
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 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 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 |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - 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" | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+49
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 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:
💡 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 || 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
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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| build-and-upload: | ||||||||||||||||||||||||||||||||||
| name: Build Images | ||||||||||||||||||||||||||||||||||
| needs: authorize | ||||||||||||||||||||||||||||||||||
| runs-on: ${{ matrix.runner }} | ||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||
| strategy: | ||||||||||||||||||||||||||||||||||
| matrix: | ||||||||||||||||||||||||||||||||||
| include: | ||||||||||||||||||||||||||||||||||
| - arch: amd64 | ||||||||||||||||||||||||||||||||||
| runner: ubuntu-24.04 | ||||||||||||||||||||||||||||||||||
| - arch: arm64 | ||||||||||||||||||||||||||||||||||
| runner: ubuntu-24.04-arm | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||
| - name: Checkout code | ||||||||||||||||||||||||||||||||||
| uses: actions/checkout@v6 | ||||||||||||||||||||||||||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 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 Workflow steps use floating version tags (not commit SHAs). Update each
🧰 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 |
||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||
| persist-credentials: false | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Build image (${{ matrix.arch }}) | ||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||
| VERSION: ${{ inputs.version }} | ||||||||||||||||||||||||||||||||||
| CS_REF_TYPE: tag | ||||||||||||||||||||||||||||||||||
| CS_REF: ${{ inputs.skills_ref }} | ||||||||||||||||||||||||||||||||||
| IMAGE_REPO: ${{ env.QUAY_IMAGE_REPO }} | ||||||||||||||||||||||||||||||||||
| IMAGE_TAG: ${{ inputs.version }} | ||||||||||||||||||||||||||||||||||
| IMAGE_NAME: ${{ env.QUAY_IMAGE_REPO }}:${{ inputs.version }}-${{ matrix.arch }} | ||||||||||||||||||||||||||||||||||
| ARTIFACT_NAME: claudio-${{ matrix.arch }} | ||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||
| make oci-build | ||||||||||||||||||||||||||||||||||
| make oci-save | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Upload image artifact | ||||||||||||||||||||||||||||||||||
| uses: actions/upload-artifact@v7 | ||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My claude is flagging that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||
| name: claudio-${{ matrix.arch }} | ||||||||||||||||||||||||||||||||||
| path: claudio-${{ matrix.arch }}.tar | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| push-quay: | ||||||||||||||||||||||||||||||||||
| name: Push to Quay | ||||||||||||||||||||||||||||||||||
| needs: build-and-upload | ||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-24.04 | ||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||
| - name: Checkout code | ||||||||||||||||||||||||||||||||||
| uses: actions/checkout@v6 | ||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||
| persist-credentials: false | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Download claudio images | ||||||||||||||||||||||||||||||||||
| uses: actions/download-artifact@v8 | ||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||
| pattern: claudio-* | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Log in to Quay Container Registry | ||||||||||||||||||||||||||||||||||
| uses: docker/login-action@v4 | ||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||
| registry: ${{ env.QUAY_REGISTRY }} | ||||||||||||||||||||||||||||||||||
| username: ${{ secrets.QUAY_USERNAME }} | ||||||||||||||||||||||||||||||||||
| password: ${{ secrets.QUAY_PASSWORD }} | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Load and push images to Quay | ||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||
| IMAGE_REPO: ${{ env.QUAY_IMAGE_REPO }} | ||||||||||||||||||||||||||||||||||
| IMAGE_TAG: ${{ inputs.version }} | ||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||
| make oci-load | ||||||||||||||||||||||||||||||||||
| make oci-push-arch | ||||||||||||||||||||||||||||||||||
| make oci-manifest-build | ||||||||||||||||||||||||||||||||||
| make oci-manifest-push | ||||||||||||||||||||||||||||||||||
|
jrusz marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - name: Tag and push as latest | ||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||
| IMAGE_REPO: ${{ env.QUAY_IMAGE_REPO }} | ||||||||||||||||||||||||||||||||||
| IMAGE_TAG: latest | ||||||||||||||||||||||||||||||||||
| IMAGE_SOURCE_TAG: ${{ inputs.version }} | ||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||
| make oci-manifest-build | ||||||||||||||||||||||||||||||||||
| make oci-manifest-push | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| create-release: | ||||||||||||||||||||||||||||||||||
| name: Create GitHub Release | ||||||||||||||||||||||||||||||||||
| needs: push-quay | ||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-24.04 | ||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||
| contents: write | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||
| - name: Create release and tag | ||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||||||||||||||
| RELEASE_VERSION: ${{ inputs.version }} | ||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||
| gh release create "$RELEASE_VERSION" \ | ||||||||||||||||||||||||||||||||||
| --repo "${{ github.repository }}" \ | ||||||||||||||||||||||||||||||||||
| --target "${{ github.sha }}" \ | ||||||||||||||||||||||||||||||||||
| --title "$RELEASE_VERSION" \ | ||||||||||||||||||||||||||||||||||
| --generate-notes | ||||||||||||||||||||||||||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.