Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
b34b8c6
Initial commit
don-petry Jun 28, 2026
a72f1a0
feat: implement issue #9 — [Fleet Monitor] petry-projects/repo-templa…
don-petry Jul 1, 2026
9b965a7
chore: re-seed sonarcloud.yml from standards/ (template-drift fix)
don-petry Jul 1, 2026
55f9136
docs(bootstrap): full SonarCloud project setup steps (#13)
don-petry Jul 2, 2026
fd26732
chore: re-seed org baseline scaffold to align with standards
don-petry Jul 8, 2026
c02f488
chore: re-seed org baseline file scaffold from current standards
don-petry Jul 13, 2026
a0599fa
fix: re-pin agent_ref inputs to v-form (missed by #657 uses:-only re-…
don-petry Jul 14, 2026
7d408cb
feat: implement issue #60 — [Fleet Monitor] petry-projects/repo-templ…
don-petry Jul 19, 2026
ca5159c
feat: implement issue #64 — Sync pr-review-mention + sonarcloud stubs…
don-petry Jul 19, 2026
4f79772
feat: implement issue #49 — [Fleet Monitor] petry-projects/repo-templ…
don-petry Jul 21, 2026
19c1cc7
chore: sync 4 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Jul 21, 2026
e99b011
chore: sync 1 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Jul 21, 2026
8013d07
chore: seed org baseline scaffold with versioned stable channels
don-petry Jul 22, 2026
203d76e
chore: sync 2 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Jul 22, 2026
dd1f792
chore: sync 1 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Jul 22, 2026
9e817ac
chore: sync 4 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Jul 22, 2026
4e3855f
chore: seed org baseline file scaffold (#86)
don-petry Jul 22, 2026
c4c11e7
chore: sync dependabot-rebase.yml from standards-derived baseline
don-petry Jul 23, 2026
ceb2e47
chore: sync dev-lead.yml from standards-derived baseline
don-petry Jul 23, 2026
5a2e8ef
chore: sync pr-review-mention.yml from standards-derived baseline
don-petry Jul 23, 2026
42e3347
chore: converge workflow stubs to major-scoped v-form channel pins [#…
don-petry Jul 23, 2026
392fed1
feat: implement issue #89 — Compliance: gitignore_baseline (#90)
don-petry Jul 24, 2026
ac56559
chore: seed org baseline file scaffold
don-petry Jul 24, 2026
6e49f46
chore(deps): bump SonarSource/sonarqube-scan-action from 8.2.0 to 8.2…
dependabot[bot] Jul 26, 2026
4208633
feat: implement issue #73 — SonarCloud: GitHub Actions / dependency h…
don-petry Jul 28, 2026
cfb5b9a
chore: sync 8 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Jul 28, 2026
391cc91
feat: implement issue #98 — SonarCloud: miscellaneous findings (#100)
don-petry Jul 28, 2026
0604da4
chore: seed org baseline file scaffold (#87)
don-petry Jul 28, 2026
84d316f
chore: re-seed template from updated standards/ (fix drift)
don-petry Jul 31, 2026
33c0c05
chore: seed org baseline file scaffold
don-petry Jul 31, 2026
1d542f6
feat: implement issue #109 — Compliance: gitignore_baseline (#116)
don-petry Jul 31, 2026
32177f0
feat: implement issue #105 — Compliance: non-stub-dependabot-automerg…
don-petry Jul 31, 2026
bcc51df
feat: implement issue #108 — Compliance: dev-lead-stub-agent-ref (#114)
don-petry Jul 31, 2026
5c4205f
feat: implement issue #106 — Compliance: non-stub-agent-shield.yml (#…
don-petry Jul 31, 2026
93846c2
chore: seed org baseline file scaffold (#117)
don-petry Aug 2, 2026
b00f1e1
chore(deps): bump actions/checkout from 6.0.2 to 7.0.1 (#119)
dependabot[bot] Aug 2, 2026
34edfce
feat: implement issue #121 — [Fleet Monitor] petry-projects/repo-temp…
don-petry Aug 2, 2026
4a08570
chore: re-seed copilot-setup-steps.yml + sonarcloud.yml from standard…
don-petry Aug 2, 2026
4146c40
fix: repin auto-rebase and dependency-audit stubs to major-scoped cha…
don-petry Aug 2, 2026
e44ae16
chore: seed org baseline file scaffold (#123)
don-petry Aug 3, 2026
0ebe1b0
feat: implement issue #104 — Compliance: non-stub-dependency-audit.ym…
don-petry Aug 3, 2026
2363249
feat: implement issue #103 — Compliance: non-stub-auto-rebase.yml (#115)
don-petry Aug 3, 2026
69b45b4
chore: sync 1 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Aug 3, 2026
59e4115
feat: implement issue #107 — Compliance: dev-lead-stub-pin (#111)
don-petry Aug 4, 2026
cb7e686
chore: seed org baseline file scaffold (#72)
don-petry Aug 4, 2026
a700e4c
chore(deps): bump actions/checkout from 7.0.0 to 7.0.1 (#132)
dependabot[bot] Aug 4, 2026
ed88f63
feat: implement issue #28 — SonarCloud: S7635 secrets-inherit caller …
don-petry Aug 4, 2026
7d1c293
chore: seed org baseline file scaffold
don-petry Aug 6, 2026
8190e03
chore: seed org baseline file scaffold (#136)
don-petry Aug 7, 2026
78bfbc9
chore: seed org baseline file scaffold (#135)
don-petry Aug 7, 2026
5f6caf9
chore: seed org baseline file scaffold (auto-rebase/v2-stable, depend…
don-petry Aug 7, 2026
0686521
feat: implement issue #17 — Compliance: missing-code-quality (#77)
don-petry Aug 8, 2026
9bef0b5
chore: sync workflow stubs to major-scoped channel tags and fix test …
don-petry Aug 12, 2026
b21f9b4
chore: seed org baseline file scaffold (#157)
don-petry Aug 14, 2026
f8c4e51
feat: implement issue #143 — Compliance: missing-github-actions-ecosy…
don-petry Aug 14, 2026
626c9e8
chore(deps): bump actions/setup-java from 5.2.0 to 5.7.0 (#160)
dependabot[bot] Aug 14, 2026
0145998
seed .github/workflows/agent-shield.yml
don-petry Aug 14, 2026
9871974
seed .github/workflows/auto-rebase.yml
don-petry Aug 14, 2026
12425d6
seed .github/workflows/copilot-setup-steps.yml
don-petry Aug 14, 2026
43fc567
seed .github/workflows/dependabot-automerge.yml
don-petry Aug 14, 2026
02bcc8e
seed .github/workflows/dependabot-rebase.yml
don-petry Aug 14, 2026
6db2426
seed .github/workflows/dependency-audit.yml
don-petry Aug 14, 2026
b304ad6
seed .github/workflows/dev-lead.yml
don-petry Aug 14, 2026
242417c
seed .github/workflows/pr-review-mention.yml
don-petry Aug 14, 2026
24903dc
seed .github/workflows/sonarcloud.yml
don-petry Aug 14, 2026
8d78f3b
seed AGENTS.md
don-petry Aug 14, 2026
ba40716
seed CLAUDE.md
don-petry Aug 14, 2026
3480ee3
seed .github/CODEOWNERS
don-petry Aug 14, 2026
73b319a
seed .github/dependabot.yml
don-petry Aug 14, 2026
9b94875
seed .gitleaks.toml
don-petry Aug 14, 2026
d1a715d
seed sonar-project.properties
don-petry Aug 14, 2026
21588d1
seed LICENSE
don-petry Aug 14, 2026
42a508c
seed SECURITY.md
don-petry Aug 14, 2026
c471462
seed README.md
don-petry Aug 14, 2026
088695d
seed BOOTSTRAP.md
don-petry Aug 14, 2026
e8d668b
chore: dev-lead update (review-changes) [skip ci-relay]
donpetry-bot Aug 14, 2026
2391cfa
chore(deps): bump actions/checkout from 7.0.0 to 7.0.1 (#159)
dependabot[bot] Aug 14, 2026
4152d4d
fix(reviews): address review comments [skip ci-relay]
donpetry-bot Aug 14, 2026
6d8d1b7
Merge branch 'main' into seed-scaffold/2026-08-14
don-petry Aug 15, 2026
0fab1a6
Merge branch 'main' into seed-scaffold/2026-08-14
don-petry Aug 16, 2026
af0b1ba
Merge branch 'main' into seed-scaffold/2026-08-14
don-petry Aug 19, 2026
c7d95f2
Merge branch 'main' into seed-scaffold/2026-08-14
don-petry Aug 19, 2026
7835902
Merge branch 'main' into seed-scaffold/2026-08-14
don-petry Aug 20, 2026
89e72f2
Merge branch 'main' into seed-scaffold/2026-08-14
don-petry Aug 20, 2026
3d5e67f
Merge branch 'main' into seed-scaffold/2026-08-14
don-petry Aug 21, 2026
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
6 changes: 3 additions & 3 deletions .github/workflows/add-to-project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# • This file is a THIN CALLER STUB. All noise-gate / reconcile logic lives
# in the reusable workflow above.
# • You MAY change: nothing in normal use. The `uses:` ref and `agent_ref`
# are pinned to the `add-to-project/v1-stable` channel and move with it — do
# are pinned to the `add-to-project/stable` channel and move with it — do
# not change them to `@main` or a SHA (see ci-standards.md → Reusable
# workflow versioning).
# • You MUST NOT change: trigger events, the concurrency group, or the
Expand Down Expand Up @@ -47,11 +47,11 @@ jobs:
add-to-project:
permissions:
contents: read
uses: petry-projects/.github/.github/workflows/add-to-project-reusable.yml@add-to-project/v1-stable # NOSONAR(githubactions:S7637) first-party channel ref
uses: petry-projects/.github/.github/workflows/add-to-project-reusable.yml@add-to-project/stable # NOSONAR(githubactions:S7637) first-party channel ref
with:
project_id: PVT_kwDOD2inqs4BZq3-
project_url: https://github.com/orgs/petry-projects/projects/1
agent_ref: add-to-project/v1-stable
agent_ref: add-to-project/stable
# Pass only the secrets the reusable declares (least privilege; avoids
# `secrets: inherit` handing the reusable every org secret).
secrets:
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/auto-rebase.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
#
# Auto-rebase non-Dependabot PRs — thin caller for the org-level reusable.
# To adopt: copy this file to .github/workflows/auto-rebase.yml in your repo.
# No secrets required — uses GITHUB_TOKEN only.
# No explicit secret mapping is required. Available secrets are inherited by the
# first-party reusable workflow.
#
# By default the reusable updates *every* behind PR (`eligibility: all`). The
# `eligibility` input is a tunable extension point for future modes; to select
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/pr-auto-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ permissions: {}

jobs:
pr-auto-review:
# Fork `pull_request` events (including dependabot[bot] and other external
# contributors) run with a read-only token and NO access to org secrets, so
# `secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS` is empty, the
# reusable's GH_TOKEN is blank, and every gh call exits 4. Readiness for fork
# PRs is still evaluated on the secret-bearing workflow_run / check_suite events
# (which run in the base-repo context), so skip the token-less pull_request run —
# it yields a `skipped`, not `failure`, conclusion. Scoped to the pull_request
# event so workflow_run / check_suite runs still execute.
if: github.event_name != 'pull_request' || github.repository == github.event.pull_request.head.repo.full_name # NOSONAR — availability guard, not a security gate; worst case is a skipped run, not a privilege grant
permissions:
pull-requests: read
checks: read
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
persist-credentials: false
- name: Set up JDK 21
id: setup_java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,4 @@ coverage/

# Logs
*.log

3 changes: 2 additions & 1 deletion tests/auto-rebase-stub.bats
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ STUB="${BATS_TEST_DIRNAME}/../.github/workflows/auto-rebase.yml"
#
# Auto-rebase non-Dependabot PRs — thin caller for the org-level reusable.
# To adopt: copy this file to .github/workflows/auto-rebase.yml in your repo.
# No secrets required — uses GITHUB_TOKEN only.
# No explicit secret mapping is required. Available secrets are inherited by the
# first-party reusable workflow.
#
# By default the reusable updates *every* behind PR (`eligibility: all`). The
# `eligibility` input is a tunable extension point for future modes; to select
Expand Down
175 changes: 175 additions & 0 deletions tests/dev-lead-stub.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#!/usr/bin/env bats
# Drift & compliance regression guard for the dev-lead thin caller stub.
#
# .github/workflows/dev-lead.yml is copied VERBATIM from the canonical org
# template (petry-projects/.github → standards/workflows/dev-lead.yml) and must
# stay byte-identical across every adopting repo, modulo the per-repo channel/ring
# pin on the `uses:` ref and its MATCHING `agent_ref`. Any other diff is drift —
# the silent-revert class of failure the fleet stub-drift monitor exists to catch
# (fleet_stub_drift.sh).
#
# This guard specifically pins the compliance-audit `dev-lead-stub-agent-ref`
# invariant (ci-standards.md → dev-lead-agent): the stub MUST pass
# `with: agent_ref: dev-lead/v<M>-<channel>` — a MAJOR-SCOPED channel tag
# (e.g. dev-lead/v1-stable), not the unversioned `dev-lead/stable` — so the
# reusable checks out its own scripts/prompts from the same major-scoped channel
# as the `uses:` ref. The bare `dev-lead/stable` form is a compliance failure.

STUB="${BATS_TEST_DIRNAME}/../.github/workflows/dev-lead.yml"

@test "dev-lead stub exists" {
[ -f "$STUB" ]
}

@test "dev-lead stub is byte-identical to the canonical template" {
# Inline canonical snapshot — update this heredoc whenever the central template
# (petry-projects/.github/standards/workflows/dev-lead.yml) changes.
# The channel pin (e.g. dev-lead/v1-stable, dev-lead/v1-next) is the only
# permitted per-repo diff; normalize it in both canonical and stub before
# comparison so adopters using any major-scoped channel pass the test.
local channel
channel=$(grep 'agent_ref:' "$STUB" | grep -oE 'dev-lead/v[0-9]+[^[:space:]]*' | head -1)
if [ -z "$channel" ]; then
echo "Could not extract channel from stub agent_ref" >&2
return 1
fi
local canon canon_norm stub_norm
canon="$(mktemp)"
canon_norm="$(mktemp)"
stub_norm="$(mktemp)"
# The canonical template ends with a single trailing newline, so reconstruct it
# with printf '%s\n' (command substitution strips the heredoc's trailing newline,
# which printf then restores) to stay byte-faithful to the committed stub the
# fleet stub-drift monitor compares SHAs against.
printf '%s\n' "$(cat << 'CANONICAL'
# ─────────────────────────────────────────────────────────────────────────────
# Dev-Lead Agent — thin caller stub
# Standard: petry-projects/.github/standards/ci-standards.md#5-dev-lead-agent
# Reusable: petry-projects/.github-private/.github/workflows/dev-lead-reusable.yml
#
# ADOPTING THIS WORKFLOW:
# 1. Copy this file verbatim to .github/workflows/dev-lead.yml in your repo.
# 2. Ensure CLAUDE_CODE_OAUTH_TOKEN is set as an org or repo secret.
# 3. Optionally set GH_PAT_WORKFLOWS (required if Claude pushes workflow files).
# 4. Optionally set vars.DEV_LEAD_ENGINE = "claude" | "gemini" | "copilot".
# 5. SonarCloud-gated repo? Nothing to do — the `uses:` line below already
# carries the inline `# NOSONAR(githubactions:S7637)` marker. The ref is a
# first-party reusable pinned to a moving channel/ring tag, so without the
# marker SonarCloud's githubactions:S7637 would fail the Quality Gate. The
# marker travels with this file on copy; no sonar-project.properties entry
# is needed. See https://github.com/petry-projects/.github/blob/main/standards/ci-standards.md#sonarcloud-exemption-first-party-reusable-ref-s7637.
#
# This stub is copied VERBATIM and is full-file identical across every adopting
# repo, modulo the per-repo ring/channel pin on the `uses:` ref and its matching
# `agent_ref` (below). Any other diff is drift, not a repo-specific liberty:
# `on:`, `permissions:`, and `concurrency:` are NOT repo-adjustable — do not trim
# a trigger, narrow a permission, or add a concurrency block on a PR branch. The
# behavior lives in the reusable, so change it there (or via a standards PR) and
# let the channel tag promote it centrally — never by editing this caller. See
# https://github.com/petry-projects/.github/blob/main/standards/ci-standards.md#centralization-tiers and
# https://github.com/petry-projects/.github/blob/main/standards/ci-standards.md#reusable-workflow-versioning--the-stable-channel.
#
# REQUIRED secrets: CLAUDE_CODE_OAUTH_TOKEN
# OPTIONAL secrets: GH_PAT_WORKFLOWS, GOOGLE_API_KEY, GH_PAT
# ─────────────────────────────────────────────────────────────────────────────

name: Dev-Lead Agent

on:
pull_request:
branches: [main]
types: [opened, reopened, synchronize]
pull_request_review:
types: [submitted]
pull_request_review_comment:
types: [created]
issue_comment:
types: [created]
issues:
types: [labeled]
check_run:
types: [completed]
repository_dispatch:
types: [dev-lead-ci-failure, dev-lead-reviews-retry, dev-lead-issue-retry]

permissions: {}

# Concurrency is centralised in the reusable workflow (dev-lead-reusable.yml) with
# per-issue / per-PR lanes, so issue pickups are never cancelled by PR follow-up
# traffic and the grouping can't drift per-repo. See petry-projects/.github#402.

jobs:
dev-lead:
# Pinned to the moving dev-lead/v1-stable channel tag, not @main, so a broken
# change to dev-lead can no longer gate its own fix (the self-host circular
# dependency). Promotion is done by moving the dev-lead/v1-stable tag centrally; this
# caller is never edited on release. agent_ref threads the same channel into
# dev-lead's own scripts/prompts checkout. See https://github.com/petry-projects/.github/blob/main/standards/ci-standards.md#dev-lead-agent.
uses: petry-projects/.github-private/.github/workflows/dev-lead-reusable.yml@dev-lead/v1-stable # NOSONAR(githubactions:S7637) first-party channel ref
with:
agent_ref: dev-lead/v1-stable
secrets: inherit # NOSONAR(githubactions:S7635) first-party trusted reusable
permissions:
contents: write
pull-requests: write
issues: write
actions: read
checks: read
statuses: read
CANONICAL
)" | sed "s|dev-lead/v1-stable|${channel}|g" > "$canon"
sed -E 's#(dev-lead/v[0-9]+-(stable|next|ring[0-9]+))([[:space:]]|$)#dev-lead/vX-CHANNEL\3#g' "$canon" > "$canon_norm"
sed -E 's#(dev-lead/v[0-9]+-(stable|next|ring[0-9]+))([[:space:]]|$)#dev-lead/vX-CHANNEL\3#g' "$STUB" > "$stub_norm"
run diff -u "$canon_norm" "$stub_norm"
rm -f "$canon" "$canon_norm" "$stub_norm"
[ "$status" -eq 0 ] || {
echo "stub drifted from canonical:"
echo "$output"
return 1
}
}

@test "with: agent_ref is pinned to the major-scoped dev-lead/v1-stable channel (dev-lead-stub-agent-ref)" {
# The compliance check requires the dev-lead/v<M>-<channel> form. Anchor the end
# so a suffix like dev-lead/v1-stable-rogue cannot slip through.
grep -qE '^[[:space:]]+agent_ref:[[:space:]]+dev-lead/v1-stable([[:space:]]|$)' "$STUB" || {
echo "agent_ref must be the major-scoped channel 'dev-lead/v1-stable', not the unversioned 'dev-lead/stable'." >&2
return 1
}
}

@test "with: agent_ref is not the unversioned dev-lead/stable form" {
if grep -qE '^[[:space:]]+agent_ref:[[:space:]]+dev-lead/(stable|next)([[:space:]]|$|#)' "$STUB"; then
echo "Error: agent_ref is the unversioned dev-lead/<channel> form — it must carry the v<M> major scope (e.g. dev-lead/v1-stable)." >&2
return 1
fi
}

@test "uses: ref is pinned to the dev-lead/v1-stable channel and matches agent_ref" {
grep -qE '^[[:space:]]+uses:[[:space:]]+petry-projects/\.github-private/\.github/workflows/dev-lead-reusable\.yml@dev-lead/v1-stable([[:space:]]|$)' "$STUB" || {
echo "uses: ref must be pinned to the major-scoped dev-lead/v1-stable channel." >&2
return 1
}
}

@test "uses: ref is not repointed to the unversioned channel, @main, a SHA, or a frozen @vN" {
if grep -qE 'dev-lead-reusable\.yml@(main|[0-9a-f]{7,40}|v[0-9]+|dev-lead/(stable|next|ring[0-9]+)|dev-lead/v[0-9]+)([[:space:]]|$)' "$STUB"; then
echo "Error: The uses: ref in $STUB is pointed to a forbidden ref (main, SHA, frozen vN, or unversioned channel)." >&2
echo "It must be pinned to the dev-lead/v1-stable channel." >&2
return 1
fi
}

@test "top-level permissions are locked down to {}" {
grep -q '^permissions: {}' "$STUB" || { echo "Top-level permissions are not locked down to {}"; return 1; }
}

@test "core trigger events are present" {
grep -qE '^ pull_request:' "$STUB" || { echo "Missing pull_request trigger"; return 1; }
grep -qE '^ pull_request_review:' "$STUB" || { echo "Missing pull_request_review trigger"; return 1; }
grep -qE '^ pull_request_review_comment:' "$STUB" || { echo "Missing pull_request_review_comment trigger"; return 1; }
grep -qE '^ issue_comment:' "$STUB" || { echo "Missing issue_comment trigger"; return 1; }
grep -qE '^ issues:' "$STUB" || { echo "Missing issues trigger"; return 1; }
grep -qE '^ check_run:' "$STUB" || { echo "Missing check_run trigger"; return 1; }
grep -qE '^ repository_dispatch:' "$STUB" || { echo "Missing repository_dispatch trigger"; return 1; }
}
Loading