-
Notifications
You must be signed in to change notification settings - Fork 52
Add two-phase release workflow #634
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,31 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| RELEASE_YAML="${1:-release.yaml}" | ||
|
|
||
| if [[ ! -f "$RELEASE_YAML" ]]; then | ||
| echo "::error::File not found: $RELEASE_YAML" | ||
| exit 1 | ||
| fi | ||
|
|
||
| VERSION=$(yq '.authorino.version' "$RELEASE_YAML") | ||
| if [[ -z "$VERSION" || "$VERSION" == "null" ]]; then | ||
| echo "::error::No version found in $RELEASE_YAML under authorino.version" | ||
| exit 1 | ||
| fi | ||
|
|
||
| if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then | ||
| echo "::error::Invalid semver: $VERSION" | ||
| exit 1 | ||
| fi | ||
|
|
||
| MAJOR=$(echo "$VERSION" | cut -d. -f1) | ||
| MINOR=$(echo "$VERSION" | cut -d. -f2) | ||
| PATCH=$(echo "$VERSION" | cut -d. -f3 | cut -d- -f1) | ||
| RELEASE_BRANCH="release-${MAJOR}.${MINOR}" | ||
|
|
||
| echo "version=$VERSION" >> "${GITHUB_OUTPUT:-/dev/stdout}" | ||
| echo "major=$MAJOR" >> "${GITHUB_OUTPUT:-/dev/stdout}" | ||
| echo "minor=$MINOR" >> "${GITHUB_OUTPUT:-/dev/stdout}" | ||
| echo "patch=$PATCH" >> "${GITHUB_OUTPUT:-/dev/stdout}" | ||
| echo "release-branch=$RELEASE_BRANCH" >> "${GITHUB_OUTPUT:-/dev/stdout}" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| BRANCH="${1:?Branch name required}" | ||
| ORG="${2:-Kuadrant}" | ||
| RELEASE_YAML="${3:-release.yaml}" | ||
|
|
||
| if [[ ! -f "$RELEASE_YAML" ]]; then | ||
| echo "::error::File not found: $RELEASE_YAML" | ||
| exit 1 | ||
| fi | ||
|
|
||
| VERSION=$(yq '.authorino.version' "$RELEASE_YAML") | ||
|
|
||
| if [[ "$BRANCH" != "main" && "$VERSION" == "0.0.0" ]]; then | ||
| echo "::error::release.yaml version is 0.0.0 on branch '$BRANCH' -- must specify a release version on non-main branches" | ||
| exit 1 | ||
| fi | ||
|
|
||
| DEPS=$(yq '.dependencies | keys | .[]' "$RELEASE_YAML" 2>/dev/null || true) | ||
| for dep in $DEPS; do | ||
| dep_version=$(yq ".dependencies.${dep}" "$RELEASE_YAML") | ||
| if [[ "$dep_version" != "0.0.0" && "$dep_version" != "null" && -n "$dep_version" ]]; then | ||
| if ! gh release view "v${dep_version}" --repo "${ORG}/${dep}" &>/dev/null; then | ||
| echo "::error::Dependency '${dep}' targets version '${dep_version}', but release v${dep_version} does not exist in ${ORG}/${dep}" | ||
| exit 1 | ||
| fi | ||
| fi | ||
| done | ||
|
|
||
| echo "release.yaml validation passed" | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,6 +6,16 @@ on: | |||||||||||||||||||||||||||||||||||
| - 'main' | ||||||||||||||||||||||||||||||||||||
| - 'master' | ||||||||||||||||||||||||||||||||||||
| workflow_dispatch: {} | ||||||||||||||||||||||||||||||||||||
| workflow_call: | ||||||||||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||||||||||
| version: | ||||||||||||||||||||||||||||||||||||
| description: "Release version (e.g. 0.26.0)" | ||||||||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||||||||||||||
| ref: | ||||||||||||||||||||||||||||||||||||
| description: "Git ref to build from (e.g. v0.26.0)" | ||||||||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||
| IMG_TAGS: ${{ github.sha }} | ||||||||||||||||||||||||||||||||||||
|
|
@@ -29,7 +39,10 @@ jobs: | |||||||||||||||||||||||||||||||||||
| - name: Set Authorino build info | ||||||||||||||||||||||||||||||||||||
| id: build-info | ||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||
| if [[ ${GITHUB_REF_NAME/\//-} =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-.+)?$ ]]; then | ||||||||||||||||||||||||||||||||||||
| if [[ -n "${{ inputs.version }}" ]]; then | ||||||||||||||||||||||||||||||||||||
| echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||||||||||||||
| echo "version_tag=v${{ inputs.version }}" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||||||||||||||
| elif [[ ${GITHUB_REF_NAME/\//-} =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-.+)?$ ]]; then | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+42
to
+45
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. 🔒 Security & Privacy | 🔴 Critical 🧩 Analysis chain🏁 Script executed: cat -n .github/workflows/build-images.yaml | sed -n '1,50p'Repository: Kuadrant/authorino Length of output: 2070 🏁 Script executed: cat -n .github/workflows/build-images.yaml | sed -n '9,18p;75,76p;130,132p'Repository: Kuadrant/authorino Length of output: 837 🏁 Script executed: # Check if there are any uses of inputs.version elsewhere in the workflow
rg 'inputs\.version' .github/workflows/build-images.yamlRepository: Kuadrant/authorino Length of output: 347 Harden Lines 39–41 interpolate Suggested fix - name: Set Authorino build info
id: build-info
+ env:
+ INPUT_VERSION: ${{ inputs.version }}
run: |
- if [[ -n "${{ inputs.version }}" ]]; then
- echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
- echo "version_tag=v${{ inputs.version }}" >> $GITHUB_OUTPUT
+ if [[ -n "$INPUT_VERSION" ]]; then
+ if ! [[ "$INPUT_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
+ echo "::error::Invalid version input: $INPUT_VERSION"
+ exit 1
+ fi
+ printf 'version=%s\n' "$INPUT_VERSION" >> "$GITHUB_OUTPUT"
+ printf 'version_tag=v%s\n' "$INPUT_VERSION" >> "$GITHUB_OUTPUT"
elif [[ ${GITHUB_REF_NAME/\/,-} =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-.+)?$ ]]; then📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.26.1)[error] 39-39: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) [error] 40-40: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) [error] 41-41: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||||||||
| tag=${GITHUB_REF_NAME/\//-} | ||||||||||||||||||||||||||||||||||||
| echo "version=${tag#v}" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||||||||||||||
| echo "version_tag=${tag}" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||||||||||||||
|
|
@@ -62,6 +75,8 @@ jobs: | |||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||
| - name: Check out code | ||||||||||||||||||||||||||||||||||||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # ratchet:actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||
| ref: ${{ inputs.ref || '' }} | ||||||||||||||||||||||||||||||||||||
| - name: Set up Docker Buildx | ||||||||||||||||||||||||||||||||||||
| uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # ratchet:docker/setup-buildx-action@v3 | ||||||||||||||||||||||||||||||||||||
| - name: Login to registry | ||||||||||||||||||||||||||||||||||||
|
|
@@ -119,9 +134,9 @@ jobs: | |||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||
| images: ${{ env.IMG_REGISTRY_HOST }}/${{ env.IMG_REGISTRY_ORG }}/authorino | ||||||||||||||||||||||||||||||||||||
| tags: | | ||||||||||||||||||||||||||||||||||||
| type=raw,value=${{ github.ref_name }},enable={{is_not_default_branch}} | ||||||||||||||||||||||||||||||||||||
| type=raw,value=${{ github.sha }},enable={{is_default_branch}} | ||||||||||||||||||||||||||||||||||||
| type=raw,value=latest,enable={{is_default_branch}} | ||||||||||||||||||||||||||||||||||||
| type=raw,value=${{ needs.prepare.outputs.version_tag }} | ||||||||||||||||||||||||||||||||||||
| type=raw,value=${{ github.sha }},enable=${{ needs.prepare.outputs.version_tag == 'latest' }} | ||||||||||||||||||||||||||||||||||||
| type=raw,value=latest,enable=${{ needs.prepare.outputs.version_tag == 'latest' }} | ||||||||||||||||||||||||||||||||||||
| - name: Login to registry | ||||||||||||||||||||||||||||||||||||
| if: ${{ !env.ACT }} | ||||||||||||||||||||||||||||||||||||
| uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # ratchet:docker/login-action@v3 | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| name: Pre-release | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: "Release version (semver, e.g. 1.5.0)" | ||
| required: true | ||
| type: string | ||
| source-branch: | ||
|
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. Every workflow_dispatch already has a source branch field. Can't that one be used instead?
Member
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. Possible yes, but also maybe not. The scenario I am thinking that it is required is doing back ports to older releases. We will want to make sure that the workflow is ran from the branch that the backport is targeted at, but that would be different than the source-branch to run the workflow against. Does that make sense?
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. It makes sense. For the workflow to run, I think it needs to be defined in the branch we pick in that field from the workflow_dispatch form. It would be hard to pre-release a patch on a version from when the workflow originally didn't exist yet. We would have to back port the workflow itself to all maintained versions. Having the not-so-redundant field also gives us the option to run the latest version of the workflow (as in the one in I guess having to type the name of the branch again isn't the end of the world. We just need to be careful about typos – which arguably we could validate in a step of the workflow (if not already). |
||
| description: "Branch to base the pre-release changes on (default: main)" | ||
| required: false | ||
| type: string | ||
| default: "main" | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| setup: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| version: ${{ steps.validate.outputs.version }} | ||
| release-branch: ${{ steps.validate.outputs.release-branch }} | ||
| steps: | ||
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # ratchet:actions/checkout@v4 | ||
| with: | ||
| ref: ${{ inputs.source-branch }} | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Validate version format | ||
| id: validate | ||
| run: | | ||
| VERSION="${{ inputs.version }}" | ||
| if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then | ||
| echo "::error::Invalid semver version: $VERSION" | ||
| exit 1 | ||
| fi | ||
| MAJOR=$(echo "$VERSION" | cut -d. -f1) | ||
| MINOR=$(echo "$VERSION" | cut -d. -f2) | ||
| RELEASE_BRANCH="release-${MAJOR}.${MINOR}" | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
| echo "release-branch=$RELEASE_BRANCH" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Create or verify release branch | ||
| run: | | ||
| RELEASE_BRANCH="${{ steps.validate.outputs.release-branch }}" | ||
| if git ls-remote --exit-code origin "refs/heads/${RELEASE_BRANCH}" >/dev/null 2>&1; then | ||
| echo "Release branch '${RELEASE_BRANCH}' already exists" | ||
| else | ||
| echo "Creating release branch '${RELEASE_BRANCH}' from '${{ inputs.source-branch }}'" | ||
| git checkout -b "${RELEASE_BRANCH}" | ||
| git push origin "${RELEASE_BRANCH}" | ||
| fi | ||
|
|
||
| prepare-release: | ||
| needs: setup | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # ratchet:actions/checkout@v4 | ||
| with: | ||
| ref: ${{ needs.setup.outputs.release-branch }} | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Create pre-release branch | ||
| run: | | ||
| PRE_RELEASE_BRANCH="pre-release-v${{ needs.setup.outputs.version }}" | ||
| if git ls-remote --exit-code origin "refs/heads/${PRE_RELEASE_BRANCH}" >/dev/null 2>&1; then | ||
| echo "::error::Pre-release branch '${PRE_RELEASE_BRANCH}' already exists. Delete it first or use a different version." | ||
| exit 1 | ||
| fi | ||
| git checkout -b "${PRE_RELEASE_BRANCH}" | ||
|
|
||
| - name: Update release.yaml | ||
| run: | | ||
| VERSION="${{ needs.setup.outputs.version }}" | ||
| yq -i ".authorino.version = \"${VERSION}\"" release.yaml | ||
|
|
||
| - name: Set up Go | ||
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # ratchet:actions/setup-go@v5 | ||
| with: | ||
| go-version-file: go.mod | ||
|
|
||
| - name: Run code generation | ||
| run: | | ||
| make generate | ||
| make manifests | ||
|
|
||
| - name: Commit and push changes | ||
| run: | | ||
| VERSION="${{ needs.setup.outputs.version }}" | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add -A | ||
| if git diff --cached --quiet; then | ||
| echo "No changes to commit" | ||
| else | ||
| git commit -m "chore: prepare release v${VERSION}" | ||
| fi | ||
| git push origin "pre-release-v${VERSION}" | ||
|
|
||
| open-pr: | ||
| needs: [setup, prepare-release] | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # ratchet:actions/checkout@v4 | ||
|
|
||
| - name: Open pull request | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| VERSION="${{ needs.setup.outputs.version }}" | ||
| RELEASE_BRANCH="${{ needs.setup.outputs.release-branch }}" | ||
|
|
||
| gh pr create \ | ||
| --base "${RELEASE_BRANCH}" \ | ||
| --head "pre-release-v${VERSION}" \ | ||
| --title "Release v${VERSION}" \ | ||
| --body "$(cat <<EOF | ||
| ## Release v${VERSION} | ||
|
|
||
| This PR prepares the release of v${VERSION}. | ||
|
|
||
| ### Pre-release changes | ||
| - Updated \`release.yaml\` version to \`${VERSION}\` | ||
| - Ran \`make generate\` and \`make manifests\` | ||
|
|
||
| ### Checklist | ||
| - [ ] Version numbers are correct | ||
| - [ ] All pre-release modifications look correct | ||
| - [ ] CI checks pass | ||
| - [ ] Version gate check passes | ||
|
|
||
| ### Next steps | ||
| After merging this PR, run the **Release** workflow with branch \`${RELEASE_BRANCH}\`. | ||
| EOF | ||
|
Comment on lines
+122
to
+138
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. Won't this indentation be a problem for the body of the PR? I wonder if the text won't end up as all wrapped in a code block in markdown.
Member
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. The indentation is not a problem. You can see a PR that was open with this formatting here: Boomatang#2. |
||
| )" | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,133 @@ | ||||||||||||||||||||||||||||||
| name: Release | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||||
| release-branch: | ||||||||||||||||||||||||||||||
| description: "Release branch (e.g. release-1.5)" | ||||||||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||
| contents: write | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+13
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. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Reduce workflow token scope to least privilege.
Suggested fix permissions:
- contents: write
+ contents: read
jobs:
+ tag:
+ permissions:
+ contents: write
+ needs: [read-version, smoke-tests]
+ runs-on: ubuntu-latest
+ steps:
+ ...
+
+ create-release:
+ permissions:
+ contents: write
+ needs: [read-version, build-image]
+ runs-on: ubuntu-latest
+ steps:
+ ...🧰 Tools🪛 zizmor (1.26.1)[error] 12-12: overly broad permissions (excessive-permissions): contents: write is overly broad at the workflow level (excessive-permissions) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||
| read-version: | ||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||
| outputs: | ||||||||||||||||||||||||||||||
| version: ${{ steps.parse.outputs.version }} | ||||||||||||||||||||||||||||||
| major: ${{ steps.parse.outputs.major }} | ||||||||||||||||||||||||||||||
| minor: ${{ steps.parse.outputs.minor }} | ||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # ratchet:actions/checkout@v4 | ||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||
| ref: ${{ inputs.release-branch }} | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: Install yq | ||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||
| sudo wget -qO /usr/local/bin/yq \ | ||||||||||||||||||||||||||||||
| https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 | ||||||||||||||||||||||||||||||
| sudo chmod +x /usr/local/bin/yq | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: Parse version from release.yaml | ||||||||||||||||||||||||||||||
| id: parse | ||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||
| chmod +x .github/scripts/parse-version.sh | ||||||||||||||||||||||||||||||
| .github/scripts/parse-version.sh | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: Validate branch matches version | ||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||
| EXPECTED_BRANCH="release-${{ steps.parse.outputs.major }}.${{ steps.parse.outputs.minor }}" | ||||||||||||||||||||||||||||||
| if [[ "${{ inputs.release-branch }}" != "$EXPECTED_BRANCH" ]]; then | ||||||||||||||||||||||||||||||
| echo "::error::Branch '${{ inputs.release-branch }}' does not match version ${{ steps.parse.outputs.version }} (expected branch: $EXPECTED_BRANCH)" | ||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||
|
Comment on lines
+38
to
+43
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. 🔒 Security & Privacy | 🟠 Major 🧩 Analysis chain🏁 Script executed: # First, locate and examine the release.yaml file
git ls-files | grep -E 'release\.yaml|release\.yml'Repository: Kuadrant/authorino Length of output: 235 🏁 Script executed: # Check the content around lines 38-43 of the release.yaml file
cat -n .github/workflows/release.yaml | sed -n '30,50p'Repository: Kuadrant/authorino Length of output: 1127 🌐 Web query:
💡 Result: The primary risk of context interpolation in GitHub Actions arises because workflow expressions (the Citations:
🏁 Script executed: # Check the workflow trigger and input definitions
cat -n .github/workflows/release.yaml | sed -n '1,30p'Repository: Kuadrant/authorino Length of output: 1092 Pass Line 41–42 directly interpolates the workflow dispatch input into a bash script, which allows shell command injection if the input contains metacharacters. GitHub Actions evaluates Suggested fix - name: Validate branch matches version
+ env:
+ INPUT_RELEASE_BRANCH: ${{ inputs.release-branch }}
run: |
EXPECTED_BRANCH="release-${{ steps.parse.outputs.major }}.${{ steps.parse.outputs.minor }}"
- if [[ "${{ inputs.release-branch }}" != "$EXPECTED_BRANCH" ]]; then
- echo "::error::Branch '${{ inputs.release-branch }}' does not match version ${{ steps.parse.outputs.version }} (expected branch: $EXPECTED_BRANCH)"
+ if [[ "$INPUT_RELEASE_BRANCH" != "$EXPECTED_BRANCH" ]]; then
+ echo "::error::Branch '$INPUT_RELEASE_BRANCH' does not match version ${{ steps.parse.outputs.version }} (expected branch: $EXPECTED_BRANCH)"
exit 1
fi🧰 Tools🪛 zizmor (1.26.1)[info] 40-40: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) [info] 40-40: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) [error] 41-41: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) [error] 42-42: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) [info] 42-42: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: Check for existing release | ||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||
| VERSION="${{ steps.parse.outputs.version }}" | ||||||||||||||||||||||||||||||
| if gh release view "v${VERSION}" &>/dev/null; then | ||||||||||||||||||||||||||||||
| echo "::error::GitHub Release v${VERSION} already exists" | ||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| smoke-tests: | ||||||||||||||||||||||||||||||
| needs: read-version | ||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # ratchet:actions/checkout@v4 | ||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||
| ref: ${{ inputs.release-branch }} | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: Set up Go | ||||||||||||||||||||||||||||||
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # ratchet:actions/setup-go@v5 | ||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||
| go-version-file: go.mod | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: Lint | ||||||||||||||||||||||||||||||
| run: make lint | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: Unit tests | ||||||||||||||||||||||||||||||
| run: make test | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: CEL validation tests | ||||||||||||||||||||||||||||||
| run: make test-cel | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| tag: | ||||||||||||||||||||||||||||||
| needs: [read-version, smoke-tests] | ||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # ratchet:actions/checkout@v4 | ||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||
| ref: ${{ inputs.release-branch }} | ||||||||||||||||||||||||||||||
| fetch-depth: 0 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: Create and push tag | ||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||
| VERSION="${{ needs.read-version.outputs.version }}" | ||||||||||||||||||||||||||||||
| TAG="v${VERSION}" | ||||||||||||||||||||||||||||||
| if git rev-parse "$TAG" >/dev/null 2>&1; then | ||||||||||||||||||||||||||||||
| echo "::error::Tag $TAG already exists" | ||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
|
Comment on lines
+91
to
+94
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. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Make tag creation idempotent for safe reruns. If a previous run pushed the tag but failed later, reruns will always fail here and block recovery. Treat “tag already exists at HEAD” as success. Suggested fix if git rev-parse "$TAG" >/dev/null 2>&1; then
- echo "::error::Tag $TAG already exists"
- exit 1
+ TAG_SHA="$(git rev-list -n1 "$TAG")"
+ HEAD_SHA="$(git rev-parse HEAD)"
+ if [[ "$TAG_SHA" != "$HEAD_SHA" ]]; then
+ echo "::error::Tag $TAG already exists and points to $TAG_SHA, not $HEAD_SHA"
+ exit 1
+ fi
+ echo "Tag $TAG already exists at HEAD; continuing"
+ exit 0
fi📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| git config user.name "github-actions[bot]" | ||||||||||||||||||||||||||||||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||||||||||||||||||||||||||||||
| git tag -a "$TAG" -m "Release $TAG" | ||||||||||||||||||||||||||||||
| git push origin "$TAG" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| build-image: | ||||||||||||||||||||||||||||||
| needs: [read-version, tag] | ||||||||||||||||||||||||||||||
| uses: ./.github/workflows/build-images.yaml | ||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||
| version: ${{ needs.read-version.outputs.version }} | ||||||||||||||||||||||||||||||
| ref: v${{ needs.read-version.outputs.version }} | ||||||||||||||||||||||||||||||
| secrets: inherit | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| create-release: | ||||||||||||||||||||||||||||||
| needs: [read-version, build-image] | ||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # ratchet:actions/checkout@v4 | ||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||
| ref: ${{ inputs.release-branch }} | ||||||||||||||||||||||||||||||
| fetch-depth: 0 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - name: Create GitHub release | ||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||
| VERSION="${{ needs.read-version.outputs.version }}" | ||||||||||||||||||||||||||||||
| TAG="v${VERSION}" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| PREV_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || echo "") | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| NOTES_ARGS="--generate-notes" | ||||||||||||||||||||||||||||||
| if [[ -n "$PREV_TAG" ]]; then | ||||||||||||||||||||||||||||||
| NOTES_ARGS="$NOTES_ARGS --notes-start-tag $PREV_TAG" | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| gh release create "$TAG" \ | ||||||||||||||||||||||||||||||
| --title "Release $TAG" \ | ||||||||||||||||||||||||||||||
| $NOTES_ARGS | ||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
Repository: Kuadrant/authorino
Length of output: 197
🏁 Script executed:
Repository: Kuadrant/authorino
Length of output: 1386
🏁 Script executed:
Repository: Kuadrant/authorino
Length of output: 435
🏁 Script executed:
Repository: Kuadrant/authorino
Length of output: 241
🌐 Web query:
yq key quoting hyphenated keys bracket notation syntax💡 Result:
To access keys containing hyphens in yq, you must use bracket notation with quoted strings [1][2]. Because hyphenated keys can be misinterpreted by the parser as subtraction operations, wrapping the key name in quotes (either double or single) is necessary to ensure it is treated as a literal string [1][2]. The standard syntax for accessing such a key is: yq '.["your-hyphenated-key"]' file.yaml Alternatively, you can use the syntax: yq '."your-hyphenated-key"' file.yaml It is critical to use shell-level quoting (the outer single quotes) to prevent your shell from interpreting the brackets or quotes before they are passed to yq [1]. Common pitfalls: 1. Shell Interpretation: If you do not wrap the entire expression in single quotes (e.g., yq.["key-name"]), your shell may attempt to interpret the brackets or quotes, leading to errors. 2. Operator Confusion: If you omit quotes around the key name, yq may treat the hyphen as a subtraction operator rather than a character in the key name [1]. 3. Leading Dashes: If the key name itself starts with a hyphen, you may also need to use the flag terminator (--) to stop the command from misinterpreting the key as a command-line flag [3].
Citations:
🌐 Web query:
yq .dependencies.key-name vs .dependencies["key-name"] parsing difference💡 Result:
In yq, the primary difference between dot notation (e.g.,.dependencies.key-name) and bracket notation (e.g.,.dependencies["key-name"]) is how they handle key names containing special characters, such as dots, hyphens, or spaces [1][2][3]. Dot notation is designed for simple, alphanumeric key names [4]. When a key contains special characters like a period, hyphen, or space, yq may misinterpret these characters as part of the expression's syntax—for example, treating a dot as a nested object separator rather than part of the key name [2][5][3]. Bracket notation with quotes (e.g.,.dependencies["key-name"]) acts as a robust mechanism to treat the contents within the brackets as a literal string [1][3]. This allows you to access keys that would otherwise be syntactically ambiguous or invalid in dot notation [2][6]. Key takeaways: 1. Dot notation: Suitable for standard, simple key names without special characters [4]. It cannot correctly reference keys containing dots (e.g.,.a.b.c interprets b.c as a nested structure) or other reserved symbols [2][5]. 2. Bracket notation: Required for keys containing dots, spaces, or leading dashes [1][2][3][7]. It is generally safer to use bracket notation whenever you are uncertain if a key name might conflict with yq expression syntax [6]. 3. Shell considerations: When using bracket notation in a terminal, it is important to wrap the entire expression in single quotes (e.g., '.dependencies["key-name"]') to prevent the shell from interpreting the double quotes or brackets prematurely [2][5][8]. For example, if you have a key named b.c, you must use.["b.c"] or."b.c" to access it, as.b.c would attempt to look for a key named b containing a sub-key named c [2][5].
Citations:
🏁 Script executed:
Repository: Kuadrant/authorino
Length of output: 186
🏁 Script executed:
Repository: Kuadrant/authorino
Length of output: 218
Use bracket notation with quoted keys when querying yq for dynamic dependency names.
Line 22 currently builds
.dependencies.${dep}using dot notation, which fails when dependency names contain hyphens. The yq parser misinterprets hyphens as subtraction operators rather than literal characters. This causes dependency version checks to fail silently or be skipped entirely for dependencies likemy-service.🔧 Proposed fix
🤖 Prompt for AI Agents