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
2 changes: 1 addition & 1 deletion .github/workflows/agent-shield.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ permissions:

jobs:
agent-shield:
uses: petry-projects/.github/.github/workflows/agent-shield-reusable.yml@v1
uses: petry-projects/.github/.github/workflows/agent-shield-reusable.yml@ae9709f4466dec60a5733c9e7487f69dcd004e05 # v1
Comment on lines 31 to +33
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

standards/ci-standards.md and standards/workflows/agent-shield.yml currently define the Tier-1 stub as calling the reusable via ...@v1. This file now pins to a SHA, which means the “SOURCE OF TRUTH” template and documentation are out of sync with what compliance requires. Please reconcile by updating the standards template/docs (or the audit script) so downstream repos can adopt verbatim without failing audits.

Copilot uses AI. Check for mistakes.
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,34 @@ jobs:
- name: Run AgentShield
run: |
npx ecc-agentshield scan --path . --format json --min-severity high

secret-scan:
name: Secret scan (gitleaks)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout (full history)
# Pin to SHA per Action Pinning Policy (ci-standards.md#action-pinning-policy).
# Look up current SHA: gh api repos/actions/checkout/git/refs/tags/v4 --jq '.object.sha'
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

The checkout SHA comment and the “Look up current SHA” command disagree: it says to query refs/tags/v4, but the pinned version comment is # v6.0.2. Please update the lookup command (and/or version comment) so maintainers don’t fetch the wrong ref when refreshing the pin.

Suggested change
# Look up current SHA: gh api repos/actions/checkout/git/refs/tags/v4 --jq '.object.sha'
# Look up current SHA: gh api repos/actions/checkout/git/refs/tags/v6.0.2 --jq '.object.sha'

Copilot uses AI. Check for mistakes.
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0

- name: Install gitleaks
# Install gitleaks CLI via verified download (pinned version + checksum).
# Using the CLI directly avoids the gitleaks-action org license requirement.
# To update: gh api repos/gitleaks/gitleaks/releases/assets/<id> -H "Accept: application/octet-stream" | grep linux_x64
# Checksum source: gitleaks_8.24.0_checksums.txt (release asset ID 230829272)
run: |
GITLEAKS_VERSION="8.24.0"
GITLEAKS_SHA="cb49b7de5ee986510fe8666ca0273a6cc15eb82571f2f14832c9e8920751f3a4"
curl -sLo gitleaks.tar.gz \
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
echo "${GITLEAKS_SHA} gitleaks.tar.gz" | sha256sum -c -
tar xzf gitleaks.tar.gz gitleaks
chmod +x gitleaks
rm gitleaks.tar.gz

- name: Run gitleaks
run: ./gitleaks detect --source . --redact --verbose --exit-code 1
2 changes: 1 addition & 1 deletion .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ permissions: {}

jobs:
claude-code:
uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main
uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@ae9709f4466dec60a5733c9e7487f69dcd004e05 # v1
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

standards/ci-standards.md describes Tier-1 stub workflows as delegating to reusables via ...@v1, and standards/workflows/claude.yml also uses @v1. This stub is now SHA-pinned instead, which creates a standards/templates mismatch. Please update the standards template/docs (or the audit exemption rules) so adopters can still “copy verbatim” without creating drift.

Suggested change
uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@ae9709f4466dec60a5733c9e7487f69dcd004e05 # v1
uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@v1

Copilot uses AI. Check for mistakes.
secrets: inherit
permissions:
contents: write
Expand Down
223 changes: 19 additions & 204 deletions .github/workflows/dependency-audit.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
# Dependency vulnerability audit.
# Detects ecosystems and runs appropriate audit tools (npm, pnpm, Go, Rust, Python).
# Standard: https://github.com/petry-projects/.github/blob/main/standards/dependabot-policy.md#vulnerability-audit-ci-check
# ─────────────────────────────────────────────────────────────────────────────
# SOURCE OF TRUTH: petry-projects/.github/standards/workflows/dependency-audit.yml
# Standard: petry-projects/.github/standards/ci-standards.md#5-dependency-audit-dependency-auditym
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

The header’s “Standard:” link looks incorrect (#5-...dependency-auditym doesn’t match the actual “### 6. Dependency Audit (dependency-audit.yml)” section in standards/ci-standards.md). Please update this anchor so the reference is accurate and doesn’t 404/mislead future adopters.

Suggested change
# Standard: petry-projects/.github/standards/ci-standards.md#5-dependency-audit-dependency-auditym
# Standard: petry-projects/.github/standards/ci-standards.md#6-dependency-audit-dependency-audityml

Copilot uses AI. Check for mistakes.
# Reusable: petry-projects/.github/.github/workflows/dependency-audit-reusable.yml
#
# Auto-detects ecosystems present in the repository and runs the appropriate
# audit tool. Fails the build if any dependency has a known security advisory.
# AGENTS — READ BEFORE EDITING:
# • This file is a THIN CALLER STUB. All ecosystem-detection and audit logic
# lives in the reusable workflow above.
# • You MAY change: nothing in this file in normal use. Adopt verbatim.
# • You MUST NOT change: trigger events, the `uses:` line, or job name
# (used as a required status check).
# • If you need different behaviour (new ecosystem, tool version bump),
# open a PR against the reusable in the central repo.
# ─────────────────────────────────────────────────────────────────────────────
#
# Add "dependency-audit" as a required status check in branch protection.
#
# Pinned tool versions (update deliberately):
# govulncheck v1.1.4 | cargo-audit 0.22.1 | pip-audit 2.9.0
# Dependency vulnerability audit — thin caller for the org-level reusable.
# To adopt: copy this file to .github/workflows/dependency-audit.yml in your repo.
# Add "dependency-audit / Detect ecosystems" as a required status check
# in branch protection.
name: Dependency audit

on:
Expand All @@ -21,198 +29,5 @@ permissions:
contents: read

jobs:
detect:
name: Detect ecosystems
runs-on: ubuntu-latest
outputs:
npm: ${{ steps.check.outputs.npm }}
pnpm: ${{ steps.check.outputs.pnpm }}
gomod: ${{ steps.check.outputs.gomod }}
cargo: ${{ steps.check.outputs.cargo }}
pip: ${{ steps.check.outputs.pip }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

- name: Detect package ecosystems
id: check
run: |
# npm — look for package-lock.json anywhere (excluding node_modules)
if find . -name 'package-lock.json' -not -path '*/node_modules/*' | grep -q .; then
echo "npm=true" >> "$GITHUB_OUTPUT"
else
echo "npm=false" >> "$GITHUB_OUTPUT"
fi

# pnpm — look for pnpm-lock.yaml anywhere
if find . -name 'pnpm-lock.yaml' -not -path '*/node_modules/*' | grep -q .; then
echo "pnpm=true" >> "$GITHUB_OUTPUT"
else
echo "pnpm=false" >> "$GITHUB_OUTPUT"
fi

# Go modules — detect via go.mod (not go.sum, which may not exist)
if find . -name 'go.mod' -not -path '*/vendor/*' | grep -q .; then
echo "gomod=true" >> "$GITHUB_OUTPUT"
else
echo "gomod=false" >> "$GITHUB_OUTPUT"
fi

# Cargo — detect via Cargo.toml anywhere (lockfile may not exist for libraries)
if find . -name 'Cargo.toml' -not -path '*/target/*' | grep -q .; then
echo "cargo=true" >> "$GITHUB_OUTPUT"
else
echo "cargo=false" >> "$GITHUB_OUTPUT"
fi

# Python — detect pyproject.toml or requirements.txt anywhere
if find . -name 'pyproject.toml' -not -path '*/.venv/*' -not -path '*/venv/*' | grep -q . || \
find . -name 'requirements.txt' -not -path '*/.venv/*' -not -path '*/venv/*' | grep -q .; then
echo "pip=true" >> "$GITHUB_OUTPUT"
else
echo "pip=false" >> "$GITHUB_OUTPUT"
fi

audit-npm:
name: npm audit
needs: detect
if: needs.detect.outputs.npm == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "lts/*"

- name: Audit npm dependencies
run: |
# Audit each package-lock.json found in the repo
status=0
while IFS= read -r dir; do
echo "::group::npm audit $dir"
if ! (cd "$dir" && npm audit --audit-level=low); then
status=1
fi
echo "::endgroup::"
done < <(find . -name 'package-lock.json' -not -path '*/node_modules/*' -exec dirname {} \;)
exit $status

audit-pnpm:
name: pnpm audit
needs: detect
if: needs.detect.outputs.pnpm == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

- uses: pnpm/action-setup@91ab88e2619ed1f46221f0ba42d1492c02baf788 # v4

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "lts/*"

- name: Audit pnpm dependencies
run: |
# Audit each pnpm-lock.yaml found in the repo
status=0
while IFS= read -r dir; do
echo "::group::pnpm audit $dir"
if ! (cd "$dir" && pnpm audit --audit-level low); then
status=1
fi
echo "::endgroup::"
done < <(find . -name 'pnpm-lock.yaml' -not -path '*/node_modules/*' -exec dirname {} \;)
exit $status

audit-go:
name: govulncheck
needs: detect
if: needs.detect.outputs.gomod == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v5
with:
go-version: "stable"

- name: Install govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4

- name: Audit Go dependencies
run: |
status=0
while IFS= read -r dir; do
echo "::group::govulncheck $dir"
if ! (cd "$dir" && govulncheck ./...); then
status=1
fi
echo "::endgroup::"
done < <(find . -name 'go.mod' -not -path '*/vendor/*' -exec dirname {} \;)
exit $status

audit-cargo:
name: cargo audit
needs: detect
if: needs.detect.outputs.cargo == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

- uses: dtolnay/rust-toolchain@stable

- name: Install cargo-audit
run: cargo install cargo-audit@0.22.1 --locked

- name: Audit Cargo dependencies
run: |
# cargo audit operates on Cargo.lock at workspace root
# For workspaces, a single audit at root covers all crates
status=0
while IFS= read -r dir; do
echo "::group::cargo audit $dir"
if ! (cd "$dir" && cargo generate-lockfile 2>/dev/null; cargo audit); then
status=1
fi
echo "::endgroup::"
done < <(find . -name 'Cargo.toml' -not -path '*/target/*' -exec dirname {} \; | sort -u)
exit $status

audit-pip:
name: pip-audit
needs: detect
if: needs.detect.outputs.pip == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.x"

- name: Install pip-audit
run: pip install pip-audit==2.9.0

- name: Audit Python dependencies
run: |
status=0
# Audit each Python project found in the repo
while IFS= read -r dir; do
echo "::group::pip-audit $dir"
if [ -f "$dir/pyproject.toml" ]; then
if ! pip-audit "$dir"; then
status=1
fi
elif [ -f "$dir/requirements.txt" ]; then
if ! pip-audit -r "$dir/requirements.txt"; then
status=1
fi
fi
echo "::endgroup::"
done < <(
{
find . -name 'pyproject.toml' -not -path '*/.venv/*' -not -path '*/venv/*' -exec dirname {} \;
find . -name 'requirements.txt' -not -path '*/.venv/*' -not -path '*/venv/*' -exec dirname {} \;
} | sort -u
)
exit $status
dependency-audit:
uses: petry-projects/.github/.github/workflows/dependency-audit-reusable.yml@ae9709f4466dec60a5733c9e7487f69dcd004e05 # v1
Comment on lines +32 to +33
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

This stub claims standards/workflows/dependency-audit.yml as the “SOURCE OF TRUTH”, but that template currently uses @v1 (tag) while this file pins the reusable to a commit SHA. Please reconcile this by updating the standards template (and any related docs) to match the SHA-pinning requirement, otherwise future “copy verbatim” adoptions will drift and/or fail the compliance audit.

Copilot uses AI. Check for mistakes.
16 changes: 10 additions & 6 deletions standards/ci-standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ where to send a fix when behavior needs to change.

| Tier | Examples | What lives in `standards/workflows/` | Where logic lives | Edits allowed in adopting repo |
|---|---|---|---|---|
| **1. Stub** | `claude.yml`, `dependency-audit.yml`, `dependabot-automerge.yml`, `dependabot-rebase.yml`, `agent-shield.yml`, `feature-ideation.yml` | A thin caller stub that delegates via `uses: petry-projects/.github/.github/workflows/<name>-reusable.yml@v1` | The matching `*-reusable.yml` in this repo (single source of truth) | **None** in normal use. May tune `with:` inputs where the reusable exposes them (e.g. `agent-shield` accepts `min-severity`, `required-files`; `feature-ideation` requires `project_context`). To change behavior, open a PR against the reusable in this repo — repos on `@v1` pick it up after the `v1` tag is bumped; repos on `@main` pick it up on their next run. |
| **1. Stub** | `claude.yml`, `dependency-audit.yml`, `dependabot-automerge.yml`, `dependabot-rebase.yml`, `agent-shield.yml`, `feature-ideation.yml` | A thin caller stub that delegates via `uses: petry-projects/.github/.github/workflows/<name>-reusable.yml@<SHA> # v1` (SHA-pinned per Action Pinning Policy). **Exception:** `claude.yml` uses `@v1` (not a SHA) due to the Anthropic OIDC token constraint — see the OIDC exemption note in `standards/workflows/claude.yml`. | The matching `*-reusable.yml` in this repo (single source of truth) | **None** in normal use. May tune `with:` inputs where the reusable exposes them (e.g. `agent-shield` accepts `min-severity`, `required-files`; `feature-ideation` requires `project_context`). To change behavior, open a PR against the reusable in this repo — the change propagates everywhere on next run. |
| **2. Per-repo template** | `ci.yml`, `sonarcloud.yml` | _(no template — see the patterns documented below)_ | In each repo, because the workflow is tech-stack-specific (language matrix, build tool, test framework) | **Limited.** Each adopting repo carries its own copy. Stay within the patterns in this document; do not change action SHAs, permission scopes, trigger events, or job names without raising a standards PR first. |
| **GitHub-managed** | CodeQL default setup | _(no workflow file — managed via repo Settings → Code security)_ | GitHub | None. Configured via `apply-repo-settings.sh`; per-repo `codeql.yml` files are treated as drift by the compliance audit. See [§2 CodeQL Analysis](#2-codeql-analysis-github-managed-default-setup). |
| **3. Free per-repo** | `release.yml`, project-specific automation | _(out of scope for this standard)_ | Per-repo | Free, but must still comply with the [Action Pinning Policy](#action-pinning-policy) and the [Required Workflows](#required-workflows) constraints. |
Expand All @@ -33,11 +33,15 @@ file with that header, **stop and read the header first** — if the change
isn't allowed by the contract, the right move is a PR against the central
reusable, not a local edit.

> **Why pin to `@v1`?** Stubs reference reusables by tag, not `@main`, so a
> bad commit on the central repo's `main` branch cannot break every
> downstream repo simultaneously. The `v1` tag is bumped deliberately when
> a backward-compatible release is ready; breaking changes will publish a
> `v2` tag that downstream repos opt into explicitly.
> **Why SHA-pin reusable workflow refs?** The [Action Pinning Policy](#action-pinning-policy)
> requires all `uses:` references to be pinned to a commit SHA, including
> reusable workflow references. The SHA in the template corresponds to the `v1`
> annotated tag commit — the version comment `# v1` documents this for human
> readability. Dependabot keeps the SHA current via the `github-actions` ecosystem
> entry in `dependabot.yml`. Using a SHA instead of `@main` also ensures that a
> bad commit on the central repo's `main` branch cannot break every downstream
> repo simultaneously; breaking changes are published as a new `v2` tag, and
> downstream repos opt in explicitly when Dependabot proposes the bump.

### Available templates

Expand Down
2 changes: 1 addition & 1 deletion standards/workflows/agent-shield.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ permissions:

jobs:
agent-shield:
uses: petry-projects/.github/.github/workflows/agent-shield-reusable.yml@v1
uses: petry-projects/.github/.github/workflows/agent-shield-reusable.yml@ae9709f4466dec60a5733c9e7487f69dcd004e05 # v1
4 changes: 2 additions & 2 deletions standards/workflows/dependency-audit.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ─────────────────────────────────────────────────────────────────────────────
# SOURCE OF TRUTH: petry-projects/.github/standards/workflows/dependency-audit.yml
# Standard: petry-projects/.github/standards/ci-standards.md#5-dependency-audit-dependency-auditym
# Standard: petry-projects/.github/standards/ci-standards.md#6-dependency-audit-dependency-audityml
# Reusable: petry-projects/.github/.github/workflows/dependency-audit-reusable.yml
#
# AGENTS — READ BEFORE EDITING:
Expand Down Expand Up @@ -30,4 +30,4 @@ permissions:

jobs:
dependency-audit:
uses: petry-projects/.github/.github/workflows/dependency-audit-reusable.yml@v1
uses: petry-projects/.github/.github/workflows/dependency-audit-reusable.yml@ae9709f4466dec60a5733c9e7487f69dcd004e05 # v1