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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions .github/workflows/pr-chart-delete.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
name: PR Chart Delete
on:
workflow_dispatch:
inputs:
chart:
description: 'Chart name'
required: true
type: string
version:
description: 'Chart version'
required: true
type: string
component_repo:
description: 'Source component repository (for PR title/body)'
required: false
type: string
default: 'kuadrant'

jobs:
create-chart-delete-pr:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
env:
CHART_NAME: ${{ github.event.inputs.chart }}
CHART_VERSION: ${{ github.event.inputs.version }}
COMPONENT_REPO: ${{ github.event.inputs.component_repo }}
BRANCH_NAME: "delete/${{ github.event.inputs.chart }}-${{ github.event.inputs.version }}"
Comment on lines +25 to +29

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Unvalidated dispatch inputs still interpolated via ${{ }} throughout the job — duplicate of prior finding.

CHART_NAME/CHART_VERSION/COMPONENT_REPO come straight from workflow_dispatch inputs with no format check, and every downstream run: step (lines 45, 50-51, 73-74, 101-108, 121-132, 150, 160, 166-167, 173, 180) re-expands them via ${{ env.X }} rather than reading the already-exported shell variable. GitHub performs literal text substitution for ${{ }} before the shell parses the script, so a value containing a quote/backtick can inject arbitrary commands that run with the privileged KUADRANT_DEV_PAT. It also enables path traversal (e.g. CHART_NAME=../../secret) into the charts/$CHART_NAME-$CHART_VERSION.tgz path built at line 50.

Add a validation step (regex-check chart/version for a safe charset) before any shell use, and switch the run: steps to reference $CHART_NAME, $CHART_VERSION, etc. (they're already exported via env:) instead of ${{ env.X }}.

🤖 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/pr-chart-delete.yaml around lines 25 - 29, Validate the
workflow_dispatch values before any shell command uses them, restricting chart,
version, and component_repo to the required safe character set and failing on
invalid input. In all downstream run steps, including the path construction and
git/registry commands, replace `${{ env.CHART_NAME }}`, `${{ env.CHART_VERSION
}}`, `${{ env.COMPONENT_REPO }}`, and related interpolations with the
already-exported shell variables `$CHART_NAME`, `$CHART_VERSION`, and
`$COMPONENT_REPO`; keep BRANCH_NAME similarly shell-expanded.


steps:
- name: Set up Go 1.26.x
uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4
with:
go-version: 1.26.x

- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0

- name: Create branch for PR
run: |
git checkout -b "${{ env.BRANCH_NAME }}"

- name: Check if chart exists
id: chart-check
run: |
chart_file="charts/${{ env.CHART_NAME }}-${{ env.CHART_VERSION }}.tgz"
prov_file="charts/${{ env.CHART_NAME }}-${{ env.CHART_VERSION }}.tgz.prov"

if [[ -f "$chart_file" ]]; then
echo "chart_file=$chart_file" >> $GITHUB_OUTPUT
echo "prov_file=$prov_file" >> $GITHUB_OUTPUT
echo "Found chart: $chart_file"
if [[ -f "$prov_file" ]]; then
echo "Found provenance: $prov_file"
else
echo "Provenance file not found: $prov_file"
fi
else
echo "::error::Chart ${{ env.CHART_NAME }} v${{ env.CHART_VERSION }} not found in repository"
echo "::error::Expected file: $chart_file"
echo "This might be due to a typo in chart name or version"
exit 1
fi
Comment on lines +47 to +67

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not skip deletion when only provenance or index artefacts remain.

The workflow reports “not found” whenever the archive is absent, even if its .prov file or index.yaml entry remains. Detect all three artefact types and run deletion/index regeneration when any exists.

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 50-50: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[warning] 50-50: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[warning] 51-51: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[warning] 51-51: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 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/pr-chart-delete.yaml around lines 47 - 66, The chart-check
step currently detects only the archive, so deletion is skipped when provenance
or index artefacts remain. Update the chart existence logic in the “Check if
chart exists” step to detect the chart archive, its .prov file, and the
corresponding index.yaml entry, setting chart_exists=true and preserving the
deletion/regeneration path when any artefact exists.


- name: Delete chart package
run: |
echo "Deleting chart package and provenance file..."
make delete-chart \
CHART_NAME="${{ env.CHART_NAME }}" \
CHART_VERSION="${{ env.CHART_VERSION }}"

- name: Update local index
run: |
echo "Updating Helm repository index..."
make helm-index

- name: Check if changes exist
id: changes
run: |
if git diff --quiet; then
echo "::error::No changes detected after attempting to delete ${{ env.CHART_NAME }} v${{ env.CHART_VERSION }}"
echo "::error::This indicates the deletion failed or chart was already removed"
echo "Check if the chart files exist and deletion command worked correctly"
exit 1
else
echo "has_changes=true" >> $GITHUB_OUTPUT
echo "Changes detected - proceeding with PR creation"
git status --porcelain
Comment thread
Boomatang marked this conversation as resolved.
fi

- name: Commit changes
if: steps.changes.outputs.has_changes == 'true'
run: |
git config --global user.name "kuadrant-bot"
git config --global user.email "kuadrant-bot@users.noreply.github.com"
git add charts/
git commit -m "Remove ${{ env.CHART_NAME }} version ${{ env.CHART_VERSION }}

- Chart: ${{ env.CHART_NAME }}
- Version: ${{ env.CHART_VERSION }}
- Source: ${{ env.COMPONENT_REPO }}
- Removed files:
- ${{ steps.chart-check.outputs.chart_file }}
- ${{ steps.chart-check.outputs.prov_file }}"

- name: Push branch
if: steps.changes.outputs.has_changes == 'true'
run: |
git push origin "${{ env.BRANCH_NAME }}"

- name: Create Pull Request
if: steps.changes.outputs.has_changes == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr create \
--title "Remove chart: ${{ env.CHART_NAME }} v${{ env.CHART_VERSION }}" \
--body "$(cat <<EOF
## Chart Deletion

This PR removes a chart package from the repository.

- **Chart**: ${{ env.CHART_NAME }}
- **Version**: ${{ env.CHART_VERSION }}
- **Source Repository**: ${{ env.COMPONENT_REPO }}

### Changes
- Removed chart package: \`${{ env.CHART_NAME }}-${{ env.CHART_VERSION }}.tgz\`
- Removed provenance file: \`${{ env.CHART_NAME }}-${{ env.CHART_VERSION }}.tgz.prov\`
- Updated Helm repository index

### Validation
This PR will be validated by CI to ensure:
- Helm index consistency after deletion
- No broken references remain
- Deletion is clean and complete

### Warning
This action will permanently remove the chart from the public repository.
Ensure this deletion is intentional and authorized.

---
*This PR was created automatically by the chart deletion workflow.*
EOF
)" \
--head "${{ env.BRANCH_NAME }}" \
--base main

- name: Enable auto-merge
if: steps.changes.outputs.has_changes == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --head "${{ env.BRANCH_NAME }}" --json number --jq '.[0].number')
gh pr merge $PR_NUMBER --auto --squash


- name: Output auto-merge details
if: steps.changes.outputs.has_changes == 'true'
run: |
echo "Created deletion PR for ${{ env.CHART_NAME }} v${{ env.CHART_VERSION }}"
echo "Branch: ${{ env.BRANCH_NAME }}"
echo "Auto-merge enabled - PR will merge automatically after CI validation passes"

- name: No changes detected
if: steps.changes.outputs.has_changes == 'false'
run: |
echo "::error::No changes detected after attempting to delete ${{ env.CHART_NAME }} v${{ env.CHART_VERSION }}"
echo "::error::This indicates the deletion failed or chart was already removed"
echo "Check if the chart files exist and deletion command worked correctly"
exit 1
146 changes: 146 additions & 0 deletions .github/workflows/pr-chart-sync.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
name: PR Chart Sync

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh label list --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" | grep -iE 'chart-sync|chart-delete|automated'

Repository: Kuadrant/helm-charts

Length of output: 158


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- workflow label usage ---\n'
grep -nE 'chart-sync|chart-delete|automated|gh pr create|--label' .github/workflows/pr-chart-sync.yaml .github/workflows/pr-chart-delete.yaml || true

printf '\n--- label definitions in repo files ---\n'
rg -n --hidden --glob '!.git' --glob '!node_modules' --glob '!dist' --glob '!build' '^(chart-sync|chart-delete|automated)$|name:\s*(chart-sync|chart-delete|automated)\b|labels:' .

Repository: Kuadrant/helm-charts

Length of output: 249


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- relevant workflow lines ---'
sed -n '90,145p' .github/workflows/pr-chart-sync.yaml
printf '\n'
sed -n '108,165p' .github/workflows/pr-chart-delete.yaml

echo '\n--- repo label definitions ---'
fd -a -t f -I 'labels.*' .
rg -n --hidden --glob '!.git' --glob '!node_modules' --glob '!dist' --glob '!build' 'chart-sync|chart-delete|automated' .

Repository: Kuadrant/helm-charts

Length of output: 5154


Add the missing PR labels gh pr create --label requires pre-existing labels. chart-sync, chart-delete, and automated are not defined, so both workflows will fail at PR creation.

  • pr-chart-sync.yaml#L98-L134
  • pr-chart-delete.yaml#L115-L153
🤖 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/pr-chart-sync.yaml at line 1, Add the missing chart-sync,
chart-delete, and automated labels before the PR creation steps in both
workflows, pr-chart-sync.yaml and pr-chart-delete.yaml. Ensure each workflow
creates or verifies these labels before invoking gh pr create so label
assignment succeeds.

on:
workflow_dispatch:
inputs:
browser_download_url:
description: 'Browser download URL for the chart package'
required: true
type: string
chart:
description: 'Chart name'
required: true
type: string
version:
description: 'Chart version'
required: true
type: string
component_repo:
description: 'Source component repository (for PR title/body)'
required: false
type: string
default: 'kuadrant'

jobs:
create-chart-pr:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
env:
BROWSER_DOWNLOAD_URL: ${{ github.event.inputs.browser_download_url }}
CHART_NAME: ${{ github.event.inputs.chart }}
CHART_VERSION: ${{ github.event.inputs.version }}
COMPONENT_REPO: ${{ github.event.inputs.component_repo }}
BRANCH_NAME: "sync/${{ github.event.inputs.chart }}-${{ github.event.inputs.version }}"
Comment on lines +29 to +34

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Centralise validation of dispatch-controlled chart identifiers.

Both privileged workflows derive shell commands, paths and branch names from unchecked dispatch inputs.

  • .github/workflows/pr-chart-sync.yaml#L29-L34: validate chart, version and download URL before any shell use.
  • .github/workflows/pr-chart-delete.yaml#L25-L29: apply the same chart/version validation before checking or deleting files.
📍 Affects 2 files
  • .github/workflows/pr-chart-sync.yaml#L29-L34 (this comment)
  • .github/workflows/pr-chart-delete.yaml#L25-L29
🤖 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/pr-chart-sync.yaml around lines 29 - 34, Centralize
validation for dispatch-controlled chart identifiers before any shell use: in
.github/workflows/pr-chart-sync.yaml lines 29-34, validate chart, version, and
download URL before deriving BRANCH_NAME or executing commands; in
.github/workflows/pr-chart-delete.yaml lines 25-29, apply the same chart and
version validation before checking or deleting files. Reuse one shared
validation mechanism rather than duplicating inconsistent checks.

Source: Linters/SAST tools


steps:
- name: Set up Go 1.26.x
uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4
with:
go-version: 1.26.x
id: go

- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0

- name: Create branch for PR
run: |
git checkout -b "${{ env.BRANCH_NAME }}"

Comment on lines +50 to +52

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Prevent script injection by using native shell variables.

Using GitHub Actions expressions (${{ env.VAR }}) inside inline bash scripts interpolates the values before execution, which allows for script injection if the environment variables contain malicious or unexpected characters. Ensure you use native shell variables (e.g., "$VAR") which safely pass the values.

  • .github/workflows/pr-chart-sync.yaml#L50-L52: Replace "${{ env.BRANCH_NAME }}" with "$BRANCH_NAME".
  • .github/workflows/pr-chart-sync.yaml#L53-L60: Replace ${{ env.VAR }} interpolation with $VAR equivalents for the download URL, chart name, and version.
  • .github/workflows/pr-chart-sync.yaml#L65-L70: Replace ${{ env.VAR }} interpolation with $VAR equivalents for the chart name and version.
  • .github/workflows/pr-chart-sync.yaml#L80-L92: Replace ${{ env.VAR }} interpolations inside the git commit message with $VAR.
  • .github/workflows/pr-chart-sync.yaml#L93-L97: Replace "${{ env.BRANCH_NAME }}" with "$BRANCH_NAME".
  • .github/workflows/pr-chart-sync.yaml#L98-L133: Replace ${{ env.VAR }} interpolations in the gh pr create command and its heredoc body with $VAR equivalents (using ${VAR} inside backticks to preserve heredoc structure).
  • .github/workflows/pr-chart-sync.yaml#L145-L152: Replace ${{ env.VAR }} interpolations in the echo statements with $VAR.
  • .github/workflows/pr-chart-sync.yaml#L153-L158: Replace ${{ env.VAR }} interpolations in the echo statements with $VAR.
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 51-51: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

📍 Affects 1 file
  • .github/workflows/pr-chart-sync.yaml#L50-L52 (this comment)
  • .github/workflows/pr-chart-sync.yaml#L53-L60
  • .github/workflows/pr-chart-sync.yaml#L65-L70
  • .github/workflows/pr-chart-sync.yaml#L80-L92
  • .github/workflows/pr-chart-sync.yaml#L93-L97
  • .github/workflows/pr-chart-sync.yaml#L98-L133
  • .github/workflows/pr-chart-sync.yaml#L145-L152
  • .github/workflows/pr-chart-sync.yaml#L153-L158

Source: Linters/SAST tools

- name: Get chart package
working-directory: ${{ github.workspace }}
run: |
make get-chart \
BROWSER_DOWNLOAD_URL="${{ env.BROWSER_DOWNLOAD_URL }}" \
CHART_NAME="${{ env.CHART_NAME }}" \
CHART_VERSION="${{ env.CHART_VERSION }}"

- name: Check if changes exist
run: |
# Add files to staging to see changes
git add charts/
if git diff --staged --quiet; then
echo "::error::No changes detected for ${{ env.CHART_NAME }} v${{ env.CHART_VERSION }}"
echo "::error::Chart may already exist in the repository"
echo "Workflow expected to make changes but none were detected"
exit 1
fi

- name: Update local index
run: |
make helm-index

- name: Validate chart package
run: |
make validate-chart \
CHART_NAME="${{ env.CHART_NAME }}" \
CHART_VERSION="${{ env.CHART_VERSION }}"

- name: Commit changes
run: |
git config --global user.name "kuadrant-bot"
git config --global user.email "kuadrant-bot@users.noreply.github.com"
git add charts/
git commit -m "Add ${{ env.CHART_NAME }} version ${{ env.CHART_VERSION }}

- Chart: ${{ env.CHART_NAME }}
- Version: ${{ env.CHART_VERSION }}
- Source: ${{ env.COMPONENT_REPO }}
- Download URL: ${{ env.BROWSER_DOWNLOAD_URL }}"

- name: Push branch
run: |
git push origin "${{ env.BRANCH_NAME }}"

- name: Create Pull Request
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr create \
--title "Sync chart: ${{ env.CHART_NAME }} v${{ env.CHART_VERSION }}" \
--body "$(cat <<EOF
## Chart Sync

This PR synchronizes a new chart package from the component release workflow.

- **Chart**: ${{ env.CHART_NAME }}
- **Version**: ${{ env.CHART_VERSION }}
- **Source Repository**: ${{ env.COMPONENT_REPO }}
- **Download URL**: ${{ env.BROWSER_DOWNLOAD_URL }}

### Changes
- Added chart package: \`${{ env.CHART_NAME }}-${{ env.CHART_VERSION }}.tgz\`
- Added provenance file: \`${{ env.CHART_NAME }}-${{ env.CHART_VERSION }}.tgz.prov\`
- Updated Helm repository index

### Validation
This PR will be validated by CI to ensure:
- Chart package is well-formed
- Helm index is consistent
- Chart name and version match expectations
- Provenance signature is valid

---
*This PR was created automatically by the chart sync workflow.*
EOF
)" \
--head "${{ env.BRANCH_NAME }}" \
--base main

- name: Enable auto-merge
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --head "${{ env.BRANCH_NAME }}" --json number --jq '.[0].number')
gh pr merge $PR_NUMBER --auto --squash


- name: Output auto-merge details
run: |
echo "Created PR for ${{ env.CHART_NAME }} v${{ env.CHART_VERSION }}"
echo "Branch: ${{ env.BRANCH_NAME }}"
echo "Auto-merge enabled - PR will merge automatically after CI validation passes"

Loading