Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
a853492
feat: initial BMad Operations Suite module
Apr 4, 2026
30d90f5
refactor: rename module from ops to bmad-bgreat-suite (bgr)
Apr 4, 2026
7007ad0
feat: enhance workflow output templates with advanced operational sec…
Apr 4, 2026
b34744f
Fix PR review feedback: table formatting, code fence tag, duplicate s…
Apr 4, 2026
74bd8bb
fix: resolve markdown formatting issues flagged in review
Apr 4, 2026
56c819b
fix: add language tag to remaining fenced code block in observability…
Apr 4, 2026
1cfea7f
feat: add CI workflows, dependabot config, and CODEOWNERS (#29)
don-petry Apr 5, 2026
09a41d6
chore: add Claude Code workflow per org CI standard (#39)
don-petry Apr 5, 2026
a8a6aad
feat: split Claude workflow into interactive + issue automation jobs …
don-petry Apr 6, 2026
c08e8e3
feat: harden Riley DevOps enforcement — zero manual changes, environm…
don-petry Apr 6, 2026
2cfc82a
feat: switch to org-level reusable Claude Code workflow
don-petry Apr 6, 2026
55c1c1e
chore(workflows): adopt centralized stubs from petry-projects/.github…
don-petry Apr 8, 2026
8a3e7ec
chore(workflows): adopt centralized claude.yml stub (#81)
don-petry Apr 8, 2026
12e8fcd
ci: add auto-rebase workflow and check_run trigger to claude.yml (#126)
don-petry Apr 21, 2026
5007e9a
chore(dev-lead): remove claude.yml — replaced by dev-lead.yml (#151)
don-petry May 16, 2026
30a59b7
chore: remove stray codeql.yml workflow (#96)
don-petry May 16, 2026
f3d78a8
chore: remove stray codeql.yml (CodeQL via default setup) (#105)
don-petry May 20, 2026
27ea9f9
feat: implement issue #146 — Compliance: secret_scanning_non_provider…
don-petry May 20, 2026
ae6f0ae
feat: implement issue #84 — Compliance: unpinned-actions-claude.yml (…
don-petry May 21, 2026
61dd9e6
feat: implement issue #83 — Compliance: unpinned-actions-agent-shield…
don-petry May 21, 2026
5bb76da
feat: implement issue #85 — Compliance: unpinned-actions-dependabot-a…
don-petry May 21, 2026
f80a6b7
feat: implement issue #86 — Compliance: unpinned-actions-dependency-a…
don-petry May 21, 2026
3db971e
feat: implement issue #140 — Compliance: check-suite-auto-trigger-347…
don-petry May 21, 2026
bbbfde9
feat: implement issue #200 — [Fleet Monitor] petry-projects/bmad-bgre…
don-petry May 24, 2026
7e06961
chore(deps): bump petry-projects/.github/.github/workflows/claude-cod…
dependabot[bot] May 24, 2026
f195067
chore(compliance): add in-progress label to labels.yml (#117)
don-petry May 24, 2026
4c5aaa6
rollout: deploy pr-review-mention standard workflow (#236)
don-petry May 31, 2026
f1c08b1
chore(deps): bump gitleaks/gitleaks-action from 2.3.9 to 3.0.0 (#235)
dependabot[bot] May 31, 2026
523d067
feat: add pr-auto-review.yml workflow (compliance automation Phase 2)…
don-petry Jun 1, 2026
86c7f90
chore(deps): bump petry-projects/.github/.github/workflows/pr-review-…
dependabot[bot] Jun 1, 2026
1aac672
fix: correct pr-auto-review reusable workflow reference (#238)
don-petry Jun 1, 2026
1e42a03
feat: implement issue #216 — Compliance: copilot-instructions-missing…
don-petry Jun 2, 2026
b225555
chore(deps): bump SonarSource/sonarqube-scan-action from 7.1.0 to 8.0…
dependabot[bot] Jun 2, 2026
2cbc4eb
feat: implement issue #83 — Compliance: unpinned-actions-agent-shield…
don-petry Jun 10, 2026
75a490d
feat: implement issue #212 — Compliance: non-stub-agent-shield.yml (#…
don-petry Jun 10, 2026
5fcfc40
feat: implement issue #91 — Compliance: stray-codeql-workflow (#241)
don-petry Jun 10, 2026
a07fd99
feat: implement issue #84 — Compliance: unpinned-actions-claude.yml (…
don-petry Jun 10, 2026
7507a68
feat: implement issue #90 — Compliance: codeql-default-setup-not-conf…
don-petry Jun 10, 2026
cded0f3
feat: implement issue #219 — Compliance: secret_scanning_non_provider…
don-petry Jun 14, 2026
bcc9ad9
feat: implement issue #314 — [Fleet Monitor] petry-projects/bmad-bgre…
don-petry Jun 14, 2026
8db8d39
feat: implement issue #184 — [Fleet Monitor] petry-projects/bmad-bgre…
don-petry Jun 16, 2026
6940b71
chore(deps): bump petry-projects/.github/.github/workflows/claude-cod…
dependabot[bot] Jun 21, 2026
967c613
feat: implement issue #141 — Compliance: secret_scan_ci_job_present (…
don-petry Jun 21, 2026
2739722
feat: implement issue #305 — [Fleet Monitor] petry-projects/bmad-bgre…
don-petry Jul 4, 2026
2e6a8bd
chore(deps): bump petry-projects/.github/.github/workflows/claude-cod…
dependabot[bot] Jul 5, 2026
4c4bc5d
ci: remove deprecated claude.yml (decommission claude-code, #665) (#365)
don-petry Jul 11, 2026
9826e98
feat: initial BMad Operations Suite module
Apr 4, 2026
80cdab4
refactor: rename module from ops to bmad-bgreat-suite (bgr)
Apr 4, 2026
b8bca8d
feat: enhance workflow output templates with advanced operational sec…
Apr 4, 2026
b408529
Fix PR review feedback: table formatting, code fence tag, duplicate s…
Apr 4, 2026
3d4da30
feat: add CI workflows, dependabot config, and CODEOWNERS (#29)
don-petry Apr 5, 2026
329a5ac
chore: add Claude Code workflow per org CI standard (#39)
don-petry Apr 5, 2026
a761969
feat: split Claude workflow into interactive + issue automation jobs …
don-petry Apr 6, 2026
cfa8eb4
feat: switch to org-level reusable Claude Code workflow
don-petry Apr 6, 2026
19f9a4d
chore(workflows): adopt centralized stubs from petry-projects/.github…
don-petry Apr 8, 2026
dfb4a18
chore(workflows): adopt centralized claude.yml stub (#81)
don-petry Apr 8, 2026
7be977f
ci: add auto-rebase workflow and check_run trigger to claude.yml (#126)
don-petry Apr 21, 2026
fe9969d
chore(dev-lead): remove claude.yml — replaced by dev-lead.yml (#151)
don-petry May 16, 2026
c3cceed
chore: remove stray codeql.yml workflow (#96)
don-petry May 16, 2026
8b51047
chore: remove stray codeql.yml (CodeQL via default setup) (#105)
don-petry May 20, 2026
782c48f
feat: implement issue #146 — Compliance: secret_scanning_non_provider…
don-petry May 20, 2026
240929a
feat: implement issue #84 — Compliance: unpinned-actions-claude.yml (…
don-petry May 21, 2026
cd073cb
feat: implement issue #83 — Compliance: unpinned-actions-agent-shield…
don-petry May 21, 2026
e2b7bc6
feat: implement issue #85 — Compliance: unpinned-actions-dependabot-a…
don-petry May 21, 2026
a9ce688
feat: implement issue #86 — Compliance: unpinned-actions-dependency-a…
don-petry May 21, 2026
f027103
feat: implement issue #140 — Compliance: check-suite-auto-trigger-347…
don-petry May 21, 2026
f8633b9
feat: implement issue #200 — [Fleet Monitor] petry-projects/bmad-bgre…
don-petry May 24, 2026
f517719
chore(deps): bump petry-projects/.github/.github/workflows/claude-cod…
dependabot[bot] May 24, 2026
d70616b
chore(compliance): add in-progress label to labels.yml (#117)
don-petry May 24, 2026
4083080
rollout: deploy pr-review-mention standard workflow (#236)
don-petry May 31, 2026
d337a0d
chore(deps): bump gitleaks/gitleaks-action from 2.3.9 to 3.0.0 (#235)
dependabot[bot] May 31, 2026
9fa1e75
feat: add pr-auto-review.yml workflow (compliance automation Phase 2)…
don-petry Jun 1, 2026
1dfb561
chore(deps): bump petry-projects/.github/.github/workflows/pr-review-…
dependabot[bot] Jun 1, 2026
b4c0229
fix: correct pr-auto-review reusable workflow reference (#238)
don-petry Jun 1, 2026
5938f60
feat: implement issue #216 — Compliance: copilot-instructions-missing…
don-petry Jun 2, 2026
65fcd74
chore(deps): bump SonarSource/sonarqube-scan-action from 7.1.0 to 8.0…
dependabot[bot] Jun 2, 2026
8d55001
feat: implement issue #83 — Compliance: unpinned-actions-agent-shield…
don-petry Jun 10, 2026
bcb3c7e
feat: implement issue #212 — Compliance: non-stub-agent-shield.yml (#…
don-petry Jun 10, 2026
a5cd081
feat: implement issue #91 — Compliance: stray-codeql-workflow (#241)
don-petry Jun 10, 2026
e4b76aa
feat: implement issue #84 — Compliance: unpinned-actions-claude.yml (…
don-petry Jun 10, 2026
49d7589
feat: implement issue #184 — [Fleet Monitor] petry-projects/bmad-bgre…
don-petry Jun 16, 2026
6789d36
chore(deps): bump petry-projects/.github/.github/workflows/claude-cod…
dependabot[bot] Jun 21, 2026
f5eefbd
feat: implement issue #305 — [Fleet Monitor] petry-projects/bmad-bgre…
don-petry Jul 4, 2026
792d5bb
chore(deps): bump petry-projects/.github/.github/workflows/claude-cod…
dependabot[bot] Jul 5, 2026
051bc8e
fix: remove duplicate code blocks in test-repo-settings.sh
donpetry-bot Jul 13, 2026
c4e2992
fix: remove github.event.discussion.user.type check in feature-ideati…
donpetry-bot Jul 13, 2026
e60f146
fix(bot): address bot feedback [skip ci-relay]
donpetry-bot Jul 14, 2026
e1a0fee
Merge branch 'main' into dev-lead/issue-361-20260710-1444
don-petry Jul 15, 2026
4200daf
chore: dev-lead update (review-changes) [skip ci-relay]
donpetry-bot Jul 15, 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
68 changes: 68 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# ─────────────────────────────────────────────────────────────────────────────
# SOURCE OF TRUTH: petry-projects/.github/standards/workflows/claude.yml
# Standard: petry-projects/.github/standards/ci-standards.md#4-claude-code-claudeyml
# Reusable: petry-projects/.github/.github/workflows/claude-code-reusable.yml
#
# AGENTS — READ BEFORE EDITING:
# • This file is a THIN CALLER STUB. All Claude Code logic, the prompt,
# allowedTools, and trigger gating live in the reusable workflow above.
# • You MAY change: nothing in this file in normal use. Adopt verbatim.
# • You MUST NOT change: trigger events, job permissions, the `uses:` line,
# or `secrets: inherit`. These are required for the reusable to work.
# • If you need different behaviour, open a PR against the reusable in the
# central repo. The change will propagate everywhere on next run.
#
# WHY THIS FILE IS IMMUTABLE (agents: read before opening any PR here):
# Anthropic's OIDC token endpoint validates that this file on a PR branch
# is byte-for-byte identical to the file on the default branch. Any diff —
# even a whitespace or comment change — causes the token exchange to fail:
# "401 Unauthorized — Workflow validation failed"
# Claude Code will not run on that PR. Do not open compliance PRs against
# this file. Do not SHA-pin the `uses:` line — internal reusable workflow
# refs are exempt from the Action Pinning Policy (ci-standards.md
# §Action Pinning Policy). The @v1 tag is the correct, stable reference.
#
# NARROW GUARD: The paths-ignore setting (lines 38-39) under pull_request
# prevents the workflow from triggering only when the PR's entire changeset
# is limited to claude.yml alone. PRs that modify claude.yml *plus other
# files* will still trigger the workflow and hit the 401 error at token
# exchange. Other triggers (issue_comment, pull_request_review_comment,
# issues, check_run) are unaffected by paths-ignore and run as configured.
# ─────────────────────────────────────────────────────────────────────────────
#
# Claude Code — thin caller that delegates to the org-level reusable workflow.
# To adopt: copy this file to .github/workflows/claude.yml in your repo.
# Required org/repo secret: CLAUDE_CODE_OAUTH_TOKEN
# Optional org/repo secret: GH_PAT_WORKFLOWS (PAT with `workflow` scope —
# required if Claude needs to push changes to .github/workflows/*.yml)

name: Claude Code

on:
pull_request:
branches: [main]
types: [opened, reopened, synchronize]
paths-ignore:
- '.github/workflows/claude.yml' # OIDC invariant — see header above
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [labeled]
check_run:
types: [completed]

permissions: {}

jobs:
claude-code:
uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@v2
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Comment thread
don-petry marked this conversation as resolved.
secrets: inherit
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Comment thread
don-petry marked this conversation as resolved.
permissions:
contents: write
id-token: write
pull-requests: write
issues: write
actions: read
checks: read
33 changes: 28 additions & 5 deletions .github/workflows/feature-ideation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,7 @@ jobs:
redispatch:
if: >-
github.event_name == 'discussion' &&
github.event.discussion.category.slug == 'ideas' &&
github.event.discussion.user.type != 'Bot' &&
(github.event.discussion.author_association == 'OWNER' ||
github.event.discussion.author_association == 'MEMBER' ||
github.event.discussion.author_association == 'COLLABORATOR')
github.event.discussion.category.slug == 'ideas'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions: {}
Expand All @@ -116,6 +112,33 @@ jobs:
echo "::error::GH_PAT_WORKFLOWS is required — a workflow_dispatch fired with GITHUB_TOKEN will not start a run."
exit 1
fi
- name: Verify author permissions
env:
GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }}
REPO: ${{ github.repository }}
USERNAME: ${{ github.event.sender.login }}
run: |
# Verify author has required permissions via API (author_association event metadata is deprecated).
# Check for admin/write collaborator access OR org membership/ownership.
PERMISSION=$(gh api repos/$REPO/collaborators/$USERNAME/permission --jq '.permission' --silent 2>/dev/null) || PERMISSION="none"
case "$PERMISSION" in
admin|maintain|write)
exit 0
;;
*)
# Check if user is an owner or org member
OWNER_LOGIN=$(gh api repos/$REPO --jq '.owner.login')
if [[ "$OWNER_LOGIN" == "$USERNAME" ]]; then
exit 0
fi
# Check org membership if repo is org-owned
if [[ "$OWNER_LOGIN" != "$REPO" ]]; then
gh api orgs/$OWNER_LOGIN/members/$USERNAME --silent >/dev/null 2>&1 && exit 0
fi
echo "::error::User $USERNAME does not have required permissions to trigger workflow"
exit 1
;;
esac
- name: Re-dispatch under workflow_dispatch
env:
GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }}
Expand Down
12 changes: 10 additions & 2 deletions sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ sonar.exclusions=_bmad/**,_bmad-output/**,.claude/**,.github/workflows/pr-review
# file individually; ci.yml / sonarcloud.yml and any third-party `uses:` keep
# full SHA-pin enforcement — do NOT replace these with a blanket
# `workflows/*.yml` resourceKey.
sonar.issue.ignore.multicriteria=s7637_agentshield,s7637_prreviewmention,s7637_prautoreview,s7637_autorebase,s7637_dependabotrebase,s7637_dependabotautomerge,s7637_dependencyaudit,s7637_addtoproject,s7637_devlead,s7637_initiativeplanner,s7637_initiativetriage,s7637_featureideation,s7635_initiativeplanner,s7635_initiativetriage,s7637_cifailureanalyst,s7637_ideatriage
sonar.issue.ignore.multicriteria=s7637_agentshield,s7637_prreviewmention,s7637_prautoreview,s7637_autorebase,s7637_dependabotrebase,s7637_dependabotautomerge,s7637_dependencyaudit,s7637_addtoproject,s7637_devlead,s7637_initiativeplanner,s7637_initiativetriage,s7637_featureideation,s7635_initiativeplanner,s7635_initiativetriage,s7637_cifailureanalyst,s7637_ideatriage,s7637_claudecode,s7635_claudecode

sonar.issue.ignore.multicriteria.s7637_agentshield.ruleKey=githubactions:S7637
sonar.issue.ignore.multicriteria.s7637_agentshield.resourceKey=**/.github/workflows/agent-shield.yml
Expand Down Expand Up @@ -64,4 +64,12 @@ sonar.issue.ignore.multicriteria.s7635_initiativetriage.resourceKey=**/.github/w
sonar.issue.ignore.multicriteria.s7637_cifailureanalyst.ruleKey=githubactions:S7637
sonar.issue.ignore.multicriteria.s7637_cifailureanalyst.resourceKey=**/ci-failure-analyst.yml
sonar.issue.ignore.multicriteria.s7637_ideatriage.ruleKey=githubactions:S7637
sonar.issue.ignore.multicriteria.s7637_ideatriage.resourceKey=**/idea-triage.yml
sonar.issue.ignore.multicriteria.s7637_ideatriage.resourceKey=**/idea-triage.yml

# claude.yml is declared IMMUTABLE in its header (Anthropic OIDC validates byte-for-byte identity);
# inline NOSONAR comments are not permitted. Suppress S7637 (first-party channel ref @v2) and
# S7635 (secrets:inherit to a fully-trusted first-party reusable) via project-level exemptions.
sonar.issue.ignore.multicriteria.s7637_claudecode.ruleKey=githubactions:S7637
sonar.issue.ignore.multicriteria.s7637_claudecode.resourceKey=**/.github/workflows/claude.yml
sonar.issue.ignore.multicriteria.s7635_claudecode.ruleKey=githubactions:S7635
sonar.issue.ignore.multicriteria.s7635_claudecode.resourceKey=**/.github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ lastUpdated: ""
- **Blocking policy**: Always block on detected secrets
- **Remediation**: Rotate exposed secret + revoke


## 8. Developer Experience Considerations

### 8.1 Local Development Parity
Expand Down
76 changes: 0 additions & 76 deletions tools/test-repo-settings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -174,82 +174,6 @@ if ! grep -q 'automated-security-fixes' "$SCRIPT"; then
fi
echo " done."

echo ""

# Check that CodeQL default setup is configured in the script
echo "Check 4: CodeQL default setup is configured"
if ! grep -q 'code-scanning/default-setup' "$SCRIPT"; then
error "$SCRIPT does not contain a code-scanning/default-setup API call"
elif ! grep -E -q 'state=configured|"state":"configured"' "$SCRIPT"; then
error "$SCRIPT references code-scanning/default-setup but does not set state to configured"
elif ! grep -E -q 'query_suite=default|"query_suite":"default"' "$SCRIPT"; then
error "$SCRIPT references code-scanning/default-setup but does not set query_suite to default"
fi
echo " done."

echo ""

# Check that secret_scanning_non_provider_patterns is enabled in the script
echo "Check 3: secret_scanning_non_provider_patterns is set to enabled"
if ! grep -q 'secret_scanning_non_provider_patterns' "$SCRIPT"; then
error "$SCRIPT does not contain a secret_scanning_non_provider_patterns API call"
elif ! grep -E -q '"secret_scanning_non_provider_patterns"[[:space:]]*:[[:space:]]*\{[[:space:]]*"status"[[:space:]]*:[[:space:]]*"enabled"[[:space:]]*\}' "$SCRIPT"; then
error "$SCRIPT references secret_scanning_non_provider_patterns but does not set status to enabled"
fi
echo " done."

# Check that every permissions: scope in the workflow is a valid GitHub Actions
# scope. An invalid scope (e.g. `administration`, which is not a GITHUB_TOKEN
# permission) makes the whole file an "invalid workflow file" that fails at
# startup with 0s duration on every run.
echo ""
echo "Check 6: apply-repo-settings.yml uses only valid permissions scopes"
if [[ ! -f "$WORKFLOW" ]]; then
error "Missing $WORKFLOW"
elif ! command -v python3 >/dev/null 2>&1 || ! python3 -c "import yaml" >/dev/null 2>&1; then
echo " python3/PyYAML unavailable — skipping permissions-scope validation"
else
invalid_scopes=$(python3 - "$WORKFLOW" <<'PY'
import sys, yaml

# Valid GITHUB_TOKEN permission scopes accepted in a workflow `permissions:` block.
ALLOWED = {
"actions", "attestations", "checks", "contents", "deployments",
"discussions", "id-token", "issues", "models", "packages", "pages",
"pull-requests", "repository-projects", "security-events", "statuses",
}

with open(sys.argv[1]) as fh:
wf = yaml.safe_load(fh)

if not isinstance(wf, dict):
wf = {}

def scopes(perms):
# A mapping of scope -> level; a bare string ("read-all"/"write-all") or
# empty mapping declares no individual scopes to validate.
return set(perms) if isinstance(perms, dict) else set()

bad = set()
bad |= scopes(wf.get("permissions"))
jobs = wf.get("jobs")
if isinstance(jobs, dict):
for job in jobs.values():
if isinstance(job, dict):
bad |= scopes(job.get("permissions"))
bad -= ALLOWED
print("\n".join(sorted(bad)))
PY
)
if [[ -n "$invalid_scopes" ]]; then
while IFS= read -r scope; do
[[ -z "$scope" ]] && continue
error "$WORKFLOW declares invalid permissions scope '$scope' — GitHub rejects this as an invalid workflow file, causing every run to fail at startup"
done <<< "$invalid_scopes"
fi
fi
echo " done."

echo ""
if [[ "$ERRORS" -gt 0 ]]; then
echo "Settings coverage check failed with $ERRORS error(s)" >&2
Expand Down
Loading