From 3af7b21fb403ae1ab52b8cf9ed26ffb71f5ae13d Mon Sep 17 00:00:00 2001 From: "v.razuvaev" Date: Mon, 3 Aug 2026 18:27:32 +0300 Subject: [PATCH] CI: add zizmor security workflow and path-aware job gating Mirror the templates/.github/workflows hardening (piloted on yii3-utm): - zizmor.yml (new): SHA-pinned zizmorcore/zizmor-action v0.6.2 audits .github/**/*.yml on change (persona auditor, advanced-security off, annotations on, online-audits off). - build.yml / static-analysis.yml: a `changes` gate job skips the heavy downstream jobs when the diff touches only irrelevant paths (docs, examples, etc.); the workflow always starts, so required checks stay mergeable and the gate is fail-open. - release.yml: inline-comment the job-level `contents: write` so zizmor reports 0 findings. --- .github/workflows/build.yml | 48 +++++++++++++++++++++++++++ .github/workflows/release.yml | 2 +- .github/workflows/static-analysis.yml | 42 +++++++++++++++++++++++ .github/workflows/zizmor.yml | 38 +++++++++++++++++++++ CHANGELOG.md | 6 ++++ 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/zizmor.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ab5b0c4..f72cc7d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,8 +14,50 @@ concurrency: cancel-in-progress: true jobs: + + changes: + name: Relevant changes + runs-on: ubuntu-latest + + outputs: + run: ${{ steps.filter.outputs.run }} + + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Detect relevant changes + id: filter + env: + EVENT_NAME: ${{ github.event_name }} + BEFORE_SHA: ${{ github.event.before }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + if [ "$EVENT_NAME" = "pull_request" ]; then + BASE="$BASE_SHA" + elif [ "$BEFORE_SHA" = "0000000000000000000000000000000000000000" ]; then + echo "run=true" >> "$GITHUB_OUTPUT" + exit 0 + else + BASE="$BEFORE_SHA" + fi + + if git diff --quiet "$BASE" "$GITHUB_SHA" -- \ + src tests config examples composer.json testo.php psalm.xml \ + rector.php .php-cs-fixer.php infection.json5 \ + .github/workflows/build.yml; then + echo "run=false" >> "$GITHUB_OUTPUT" + else + echo "run=true" >> "$GITHUB_OUTPUT" + fi + build: name: PHP ${{ matrix.php }} + needs: changes + if: ${{ !cancelled() && (needs.changes.result != 'success' || needs.changes.outputs.run == 'true') }} runs-on: ubuntu-latest strategy: @@ -55,6 +97,8 @@ jobs: prefer-lowest: name: Prefer lowest + needs: changes + if: ${{ !cancelled() && (needs.changes.result != 'success' || needs.changes.outputs.run == 'true') }} runs-on: ubuntu-latest steps: @@ -86,6 +130,8 @@ jobs: coverage: name: Coverage & Mutation + needs: changes + if: ${{ !cancelled() && (needs.changes.result != 'success' || needs.changes.outputs.run == 'true') }} runs-on: ubuntu-latest steps: @@ -120,6 +166,8 @@ jobs: compatibility: name: Backward compatibility + needs: changes + if: ${{ !cancelled() && (needs.changes.result != 'success' || needs.changes.outputs.run == 'true') }} runs-on: ubuntu-latest steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a920837..234d11d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest permissions: # creating a Release object is a write to the repository - contents: write + contents: write # Needed to create the GitHub release steps: - name: Checkout diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index b44e7d3..aab627e 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -14,8 +14,50 @@ concurrency: cancel-in-progress: true jobs: + + changes: + name: Relevant changes + runs-on: ubuntu-latest + + outputs: + run: ${{ steps.filter.outputs.run }} + + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Detect relevant changes + id: filter + env: + EVENT_NAME: ${{ github.event_name }} + BEFORE_SHA: ${{ github.event.before }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + if [ "$EVENT_NAME" = "pull_request" ]; then + BASE="$BASE_SHA" + elif [ "$BEFORE_SHA" = "0000000000000000000000000000000000000000" ]; then + echo "run=true" >> "$GITHUB_OUTPUT" + exit 0 + else + BASE="$BEFORE_SHA" + fi + + if git diff --quiet "$BASE" "$GITHUB_SHA" -- \ + src tests config examples composer.json testo.php psalm.xml \ + rector.php .php-cs-fixer.php infection.json5 \ + .github/workflows/static-analysis.yml; then + echo "run=false" >> "$GITHUB_OUTPUT" + else + echo "run=true" >> "$GITHUB_OUTPUT" + fi + psalm: name: Psalm + needs: changes + if: ${{ !cancelled() && (needs.changes.result != 'success' || needs.changes.outputs.run == 'true') }} runs-on: ubuntu-latest steps: diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000..f2bfb70 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,38 @@ +name: GitHub Actions security + +on: + pull_request: + paths: &paths + - '.github/**/*.yml' + - '.github/**/*.yaml' + push: + branches: + - master + paths: *paths + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + zizmor: + name: zizmor + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + + - name: Audit GitHub Actions + uses: zizmorcore/zizmor-action@3dc1ecc9bcb9e94e9b2c709687979e1298497054 # v0.6.2 + with: + advanced-security: false + annotations: true + online-audits: false + persona: auditor + version: 1.25.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index e68a4c1..d148bd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Changed + +- Add a `zizmor` GitHub Actions security audit workflow and skip heavy CI jobs on irrelevant changes via a path-aware gate. + ## 1.1.0 — 2026-07-25 - Ship an AI agent skill (`resources/skills/rasuvaeff-specification/SKILL.md`