From 8fccc7de5d2139990507c8cb3304d55a8dfa19af Mon Sep 17 00:00:00 2001 From: Tony Meyer Date: Sat, 21 Mar 2026 14:04:12 +1300 Subject: [PATCH 1/6] ci: add zizmor workflow --- .github/workflows/zizmor.yaml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/zizmor.yaml diff --git a/.github/workflows/zizmor.yaml b/.github/workflows/zizmor.yaml new file mode 100644 index 000000000..22176723b --- /dev/null +++ b/.github/workflows/zizmor.yaml @@ -0,0 +1,34 @@ +name: Workflow static checks + +on: + push: + branches: ["master"] + pull_request: + branches: ["**"] + +permissions: {} + +jobs: + zizmor: + runs-on: ubuntu-latest + permissions: + security-events: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install uv + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + + - name: Run zizmor + run: uvx zizmor@v1.23.1 --format=sarif . > results.sarif + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif + category: zizmor From 2eb91a4e78f69129108f06dde3e9b4f8449d81ae Mon Sep 17 00:00:00 2001 From: Tony Meyer Date: Sat, 21 Mar 2026 14:04:55 +1300 Subject: [PATCH 2/6] ci: use environment variables to prevent injection --- .github/workflows/ci.yaml | 36 ++++++++++++++++++------- .github/workflows/test-interface.yaml | 13 ++++++--- .github/workflows/test-package.yaml | 39 ++++++++++++++++++--------- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d7d1002ca..781c0729e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -34,22 +34,31 @@ jobs: - name: Calculate reference for git diff id: ref if: github.event_name == 'pull_request' + env: + BASE_REF: ${{ github.event.pull_request.base.ref }} run: | set -xueo pipefail - echo "result=$(git merge-base origin/${{ github.event.pull_request.base.ref }} HEAD)" >> "$GITHUB_OUTPUT" + echo "result=$(git merge-base origin/$BASE_REF HEAD)" >> "$GITHUB_OUTPUT" - uses: astral-sh/setup-uv@v7 - name: Collect changed packages id: packages - run: .github/get-changed.py packages ${{ steps.ref.outputs.result }} + env: + REF_RESULT: ${{ steps.ref.outputs.result }} + run: .github/get-changed.py packages $REF_RESULT - name: Collect changed interfaces id: interfaces - run: .github/get-changed.py interfaces ${{ steps.ref.outputs.result }} --name-only + env: + REF_RESULT: ${{ steps.ref.outputs.result }} + run: .github/get-changed.py interfaces $REF_RESULT --name-only - name: Collect packages that would be published on merge id: publish + env: + EVENT_NAME: ${{ github.event_name }} + REF_RESULT: ${{ steps.ref.outputs.result }} run: | set -xueo pipefail - if [ ${{ github.event_name }} = 'pull_request' ]; then - PACKAGES=$(.scripts/ls.py packages ${{ steps.ref.outputs.result }} --exclude-examples --exclude-placeholders --only-if-version-changed) + if [ "$EVENT_NAME" = 'pull_request' ]; then + PACKAGES=$(.scripts/ls.py packages $REF_RESULT --exclude-examples --exclude-placeholders --only-if-version-changed) else PACKAGES='[]' fi @@ -74,8 +83,10 @@ jobs: steps: - name: Fail if any tests failed if: ${{ needs.package.result != 'success' && needs.package.result != 'skipped' }} + env: + NEEDS_JSON: ${{ toJSON(needs) }} run: | - echo '${{ toJSON(needs) }}' | jq # logging + echo "$NEEDS_JSON" | jq # logging exit 1 interface: @@ -96,8 +107,10 @@ jobs: steps: - name: Fail if any interface tests failed if: ${{ needs.interface.result != 'success' && needs.interface.result != 'skipped' }} + env: + NEEDS_JSON: ${{ toJSON(needs) }} run: | - echo '${{ toJSON(needs) }}' | jq # logging + echo "$NEEDS_JSON" | jq # logging exit 1 interfaces-json-up-to-date: @@ -161,9 +174,12 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Ensure CHANGELOG.md has been updated + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + PACKAGE: ${{ matrix.package }} run: | set -xueo pipefail - if git diff --name-only ${{ github.event.pull_request.base.sha }} | grep -q '^${{ matrix.package }}/CHANGELOG.md$'; then + if git diff --name-only "$BASE_SHA" | grep -q "^${PACKAGE}/CHANGELOG.md$"; then : 'CHANGELOG.md updated :)' else : 'CHANGELOG.md must be updated before merging :(' @@ -177,8 +193,10 @@ jobs: steps: - name: Fail if any required changelogs are not updated if: ${{ needs.changelog-updated.result != 'success' && needs.changelog-updated.result != 'skipped' }} + env: + NEEDS_JSON: ${{ toJSON(needs) }} run: | - echo '${{ toJSON(needs) }}' | jq # logging + echo "$NEEDS_JSON" | jq # logging exit 1 zizmor: diff --git a/.github/workflows/test-interface.yaml b/.github/workflows/test-interface.yaml index be418c86c..2df15b79a 100644 --- a/.github/workflows/test-interface.yaml +++ b/.github/workflows/test-interface.yaml @@ -62,11 +62,16 @@ jobs: persist-credentials: false - uses: astral-sh/setup-uv@v7 - name: Run interface tests + env: + VERSION: ${{ matrix.version }} + ROLE: ${{ matrix.role }} + CHARM_NAME: ${{ matrix.charm_name }} + ENDPOINT: ${{ matrix.endpoint }} run: | set -xueo pipefail .scripts/run-interface-tests.py \ "$INTERFACE" \ - ${{ matrix.version }} \ - ${{ matrix.role }} \ - ${{ matrix.charm_name }} \ - ${{ matrix.endpoint }} + "$VERSION" \ + "$ROLE" \ + "$CHARM_NAME" \ + "$ENDPOINT" diff --git a/.github/workflows/test-package.yaml b/.github/workflows/test-package.yaml index 82a9bed93..26e8c22c2 100644 --- a/.github/workflows/test-package.yaml +++ b/.github/workflows/test-package.yaml @@ -25,6 +25,9 @@ on: permissions: {} +env: + PACKAGE: ${{ inputs.package }} + jobs: init: runs-on: ubuntu-latest @@ -53,14 +56,14 @@ jobs: - name: Check which Python versions this package supports id: python - run: uv run --no-project --script .github/get-supported-python-versions.py ${{ inputs.package }} + run: uv run --no-project --script .github/get-supported-python-versions.py "$PACKAGE" - name: Check which test suites this package has id: tests run: | tests=() for test in unit functional integration; do - if [ -d ${{ inputs.package }}/tests/$test ]; then + if [ -d "$PACKAGE/tests/$test" ]; then tests+=($test) fi done @@ -71,7 +74,7 @@ jobs: - name: Check requirements for functional tests id: functional if: contains(fromJson(steps.tests.outputs.tests), 'functional') - run: uv run --no-project --script .github/get-functional-test-matrix.py ${{ inputs.package }} + run: uv run --no-project --script .github/get-functional-test-matrix.py "$PACKAGE" - name: Check substrates needed for integration tests id: integration-substrates @@ -80,7 +83,7 @@ jobs: substrates=() for substrate in k8s machine; do set +e # don't abort if the next process has a non-zero exit code - uvx --from rust-just just integration-$substrate ${{ inputs.package }} --collect-only -q + uvx --from rust-just just integration-$substrate "$PACKAGE" --collect-only -q case $? in 0) substrates+=($substrate);; 5) echo "No tests for $substrate";; @@ -98,7 +101,7 @@ jobs: shell: python run: | import json, os, pathlib, tomllib - pyproject_toml = tomllib.loads(pathlib.Path('${{ inputs.package }}', 'pyproject.toml').read_text()) + pyproject_toml = tomllib.loads(pathlib.Path(os.environ['PACKAGE'], 'pyproject.toml').read_text()) tags = pyproject_toml.get('tool', {}).get('charmlibs', {}).get('integration', {}).get('tags') or [''] line = f'tags={json.dumps(tags)}' print(line) @@ -122,7 +125,9 @@ jobs: uses: astral-sh/setup-uv@v7 - name: Run static analysis and other checks - run: uvx --from rust-just just python=${{ matrix.python }} lint ${{ inputs.package }} + env: + PYTHON: ${{ matrix.python }} + run: uvx --from rust-just just python="$PYTHON" lint "$PACKAGE" unit: needs: init @@ -141,7 +146,9 @@ jobs: uses: astral-sh/setup-uv@v7 - name: Run unit tests - run: uvx --from rust-just just python=${{ matrix.python }} unit ${{ inputs.package }} + env: + PYTHON: ${{ matrix.python }} + run: uvx --from rust-just just python="$PYTHON" unit "$PACKAGE" functional: needs: init @@ -164,18 +171,20 @@ jobs: - name: Install Pebble if: matrix.pebble != 'no-pebble' - run: go install github.com/canonical/pebble/cmd/${{ matrix.pebble }} + env: + PEBBLE: ${{ matrix.pebble }} + run: go install "github.com/canonical/pebble/cmd/$PEBBLE" - name: Install uv uses: astral-sh/setup-uv@v7 - name: Run functional tests if: matrix.sudo == 'no-sudo' - run: uvx --from rust-just just python=python3 functional ${{ inputs.package }} + run: uvx --from rust-just just python=python3 functional "$PACKAGE" - name: Run functional tests with sudo if: matrix.sudo != 'no-sudo' - run: sudo env "PATH=$PATH" uvx --from rust-just just python=python3 functional ${{ inputs.package }} + run: sudo env "PATH=$PATH" uvx --from rust-just just python=python3 functional "$PACKAGE" integration: needs: init @@ -207,7 +216,13 @@ jobs: - name: Pack charms if: ${{ hashFiles(format('{0}/tests/integration/pack.sh', inputs.package)) != '' }} - run: uvx --from rust-just just tag='${{ matrix.tag }}' pack-${{ matrix.substrate }} ${{ inputs.package }} + env: + TAG: ${{ matrix.tag }} + SUBSTRATE: ${{ matrix.substrate }} + run: uvx --from rust-just just tag="$TAG" "pack-$SUBSTRATE" "$PACKAGE" - name: Run Juju integration tests - run: uvx --from rust-just just tag='${{ matrix.tag }}' integration-${{ matrix.substrate }} ${{ inputs.package }} + env: + TAG: ${{ matrix.tag }} + SUBSTRATE: ${{ matrix.substrate }} + run: uvx --from rust-just just tag="$TAG" "integration-$SUBSTRATE" "$PACKAGE" From a1d6989d8fe6850e76a98a1482178665e4e26a20 Mon Sep 17 00:00:00 2001 From: Tony Meyer Date: Sat, 21 Mar 2026 14:09:54 +1300 Subject: [PATCH 3/6] ci: fix default branch name --- .github/workflows/zizmor.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/zizmor.yaml b/.github/workflows/zizmor.yaml index 22176723b..aeac1c8fc 100644 --- a/.github/workflows/zizmor.yaml +++ b/.github/workflows/zizmor.yaml @@ -2,7 +2,7 @@ name: Workflow static checks on: push: - branches: ["master"] + branches: ["main"] pull_request: branches: ["**"] From 3a028878da5f3145ef92949d7e5cf9c24997b386 Mon Sep 17 00:00:00 2001 From: Tony Meyer Date: Sat, 21 Mar 2026 15:35:28 +1300 Subject: [PATCH 4/6] Allow any version of Go, to avoid needing to sync with pebble@master. --- .github/workflows/test-package.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test-package.yaml b/.github/workflows/test-package.yaml index a79081433..19e4289c3 100644 --- a/.github/workflows/test-package.yaml +++ b/.github/workflows/test-package.yaml @@ -178,6 +178,7 @@ jobs: if: matrix.pebble != 'no-pebble' env: PEBBLE: ${{ matrix.pebble }} + GOTOOLCHAIN: auto run: go install "github.com/canonical/pebble/cmd/$PEBBLE" - name: Install uv From 96a31cab58f237dbd75fdf291c6c9e81699bf0d7 Mon Sep 17 00:00:00 2001 From: Tony Meyer Date: Sat, 21 Mar 2026 15:42:08 +1300 Subject: [PATCH 5/6] Use v4 for sarif upload. --- .github/workflows/zizmor.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/zizmor.yaml b/.github/workflows/zizmor.yaml index aeac1c8fc..6e143adfa 100644 --- a/.github/workflows/zizmor.yaml +++ b/.github/workflows/zizmor.yaml @@ -28,7 +28,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@v4 with: sarif_file: results.sarif category: zizmor From 751ad1764f1989dbef1ed3557c356a37203c6a68 Mon Sep 17 00:00:00 2001 From: Tony Meyer Date: Mon, 23 Mar 2026 12:42:44 +1300 Subject: [PATCH 6/6] Apply suggestions from code review Co-authored-by: James Garner --- .github/workflows/zizmor.yaml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/zizmor.yaml b/.github/workflows/zizmor.yaml index 6e143adfa..4bcf458a4 100644 --- a/.github/workflows/zizmor.yaml +++ b/.github/workflows/zizmor.yaml @@ -4,7 +4,6 @@ on: push: branches: ["main"] pull_request: - branches: ["**"] permissions: {} @@ -14,21 +13,14 @@ jobs: permissions: security-events: write steps: - - name: Checkout repository - uses: actions/checkout@v4 + - uses: actions/checkout@v4 with: persist-credentials: false - - - name: Install uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 - - - name: Run zizmor - run: uvx zizmor@v1.23.1 --format=sarif . > results.sarif + - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + - run: uvx zizmor@v1.23.1 --format=sarif . > results.sarif env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@v4 + - uses: github/codeql-action/upload-sarif@v4 with: sarif_file: results.sarif category: zizmor