diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..5b43d577 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# CODEOWNERS +# Standard: use the @petry-projects/org-leads team for all code owner +# assignments. See petry-projects/.github standards/codeowners-standard.md + +* @petry-projects/org-leads diff --git a/.github/workflows/auto-rebase.yml b/.github/workflows/auto-rebase.yml index 32dc4e70..0925b268 100644 --- a/.github/workflows/auto-rebase.yml +++ b/.github/workflows/auto-rebase.yml @@ -7,10 +7,8 @@ # • This file is a THIN CALLER STUB. All branch-update logic lives in the # reusable workflow above. # • You MAY change: the SHA in the `uses:` line when upgrading the reusable -# workflow version (bump SHA to the commit that `auto-rebase/stable` points -# to in petry-projects/.github — pinned SHA is required for SonarCloud). -# • You MUST NOT change: the trigger event, -# the concurrency group name, +# workflow version (bump SHA to latest main of petry-projects/.github). +# • You MUST NOT change: trigger event, the concurrency group name, # or the job-level `permissions:` block — reusable workflows can be # granted no more permissions than the calling job has, so removing # the stanza breaks the reusable's gh API calls. @@ -21,16 +19,6 @@ # 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. -# -# By default the reusable only updates *review-ready* PRs: non-draft AND -# (carrying a current APPROVED review OR the `auto-rebase:ready` label). This -# keeps the workflow from fanning out branch-update CI runs to every behind PR. -# To tune it, pass inputs to the reusable, e.g.: -# -# with: -# eligibility: review-ready # default; or `all` to update every behind PR -# ready_label: auto-rebase:ready # label that opts a non-draft PR in -# name: Auto-rebase non-Dependabot PRs on: @@ -50,5 +38,5 @@ jobs: permissions: contents: write # update-branch via GITHUB_TOKEN (may touch .github/workflows/) pull-requests: write # post comments on PRs - uses: petry-projects/.github/.github/workflows/auto-rebase-reusable.yml@376a4fcb1117444595e3e702fa450873d0e54310 # auto-rebase/stable - secrets: inherit + uses: petry-projects/.github/.github/workflows/auto-rebase-reusable.yml@d3d768dabb7f28cc63283cdfe48630da53700e50 # v1 + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/dev-lead.yml b/.github/workflows/dev-lead.yml index 25cc7785..217398ed 100644 --- a/.github/workflows/dev-lead.yml +++ b/.github/workflows/dev-lead.yml @@ -20,7 +20,6 @@ name: Dev-Lead Agent on: pull_request: - branches: [main] types: [opened, reopened, synchronize] pull_request_review: types: [submitted] @@ -33,14 +32,10 @@ on: check_run: types: [completed] repository_dispatch: - types: [dev-lead-ci-failure, dev-lead-reviews-retry, dev-lead-issue-retry] + types: [dev-lead-ci-failure, dev-lead-reviews-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/stable channel tag, not @main, so a broken diff --git a/.github/workflows/pr-review-mention.yml b/.github/workflows/pr-review-mention.yml index d7cf51d1..2bc54fb0 100644 --- a/.github/workflows/pr-review-mention.yml +++ b/.github/workflows/pr-review-mention.yml @@ -41,3 +41,4 @@ jobs: statuses: read uses: petry-projects/.github/.github/workflows/pr-review-mention-reusable.yml@v2 secrets: inherit + diff --git a/.gitleaksignore b/.gitleaksignore index 7900acda..d12cd9ce 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -36,9 +36,9 @@ e8cc0956c901e454aed61e7b10857e6a1a412881:_bmad/_config/files-manifest.csv:generi e8cc0956c901e454aed61e7b10857e6a1a412881:_bmad/_config/files-manifest.csv:generic-api-key:409 e8cc0956c901e454aed61e7b10857e6a1a412881:_bmad/_config/files-manifest.csv:generic-api-key:433 -# Commit aec934f9: same _bmad/_config/files-manifest.csv CSV rows as above -# (SHA256 content checksums of BMAD skill files) appearing in a later commit -# that re-introduced the same content. Same false-positive rationale applies. +# Commit aec934f9: same _bmad/_config/files-manifest.csv SHA256-checksum rows as +# e8cc0956 above — identical false-positive pattern (file-content checksums, not +# API keys). Full-history CLI scan flags this ancestor commit independently. aec934f92f4174b89944ee57a3d5cf68737f71c9:_bmad/_config/files-manifest.csv:generic-api-key:281 aec934f92f4174b89944ee57a3d5cf68737f71c9:_bmad/_config/files-manifest.csv:generic-api-key:282 aec934f92f4174b89944ee57a3d5cf68737f71c9:_bmad/_config/files-manifest.csv:generic-api-key:284 @@ -85,25 +85,47 @@ c5099d1dfbc58bd65ddd0e4efd267666260bb3f6:_bmad/_config/files-manifest.csv:generi c5099d1dfbc58bd65ddd0e4efd267666260bb3f6:_bmad/_config/files-manifest.csv:generic-api-key:409 c5099d1dfbc58bd65ddd0e4efd267666260bb3f6:_bmad/_config/files-manifest.csv:generic-api-key:433 -# Commits 899ea777, 40bd4031, 4c9852dc: same _bmad/_config/files-manifest.csv CSV rows as -# above (SHA256 content checksums of BMAD skill files). Same false-positive rationale. -# These three commits appeared in the full-history scan triggered by PR #309 but were not -# yet suppressed; pattern is identical to the already-reviewed entries above. +# Commit 899ea777: same _bmad/_config/files-manifest.csv CSV rows as above +# (SHA256 content checksums of BMAD skill files). Same false-positive rationale. 899ea7773683bc45c329b6d5f413c8662c67d6f1:_bmad/_config/files-manifest.csv:generic-api-key:281 899ea7773683bc45c329b6d5f413c8662c67d6f1:_bmad/_config/files-manifest.csv:generic-api-key:282 899ea7773683bc45c329b6d5f413c8662c67d6f1:_bmad/_config/files-manifest.csv:generic-api-key:284 899ea7773683bc45c329b6d5f413c8662c67d6f1:_bmad/_config/files-manifest.csv:generic-api-key:300 899ea7773683bc45c329b6d5f413c8662c67d6f1:_bmad/_config/files-manifest.csv:generic-api-key:409 899ea7773683bc45c329b6d5f413c8662c67d6f1:_bmad/_config/files-manifest.csv:generic-api-key:433 + +# Commit 40bd403: same _bmad/_config/files-manifest.csv CSV rows as above +# (SHA256 content checksums of BMAD skill files). Same false-positive rationale. 40bd40314d66e26adc09503c098e34e4254a53a9:_bmad/_config/files-manifest.csv:generic-api-key:281 40bd40314d66e26adc09503c098e34e4254a53a9:_bmad/_config/files-manifest.csv:generic-api-key:282 40bd40314d66e26adc09503c098e34e4254a53a9:_bmad/_config/files-manifest.csv:generic-api-key:284 40bd40314d66e26adc09503c098e34e4254a53a9:_bmad/_config/files-manifest.csv:generic-api-key:300 40bd40314d66e26adc09503c098e34e4254a53a9:_bmad/_config/files-manifest.csv:generic-api-key:409 40bd40314d66e26adc09503c098e34e4254a53a9:_bmad/_config/files-manifest.csv:generic-api-key:433 + +# Commit 4c9852dc: same _bmad/_config/files-manifest.csv CSV rows as above +# (SHA256 content checksums of BMAD skill files). Same false-positive rationale. 4c9852dcd788730edfb9aaac3c7cca3a6777df9f:_bmad/_config/files-manifest.csv:generic-api-key:281 4c9852dcd788730edfb9aaac3c7cca3a6777df9f:_bmad/_config/files-manifest.csv:generic-api-key:282 4c9852dcd788730edfb9aaac3c7cca3a6777df9f:_bmad/_config/files-manifest.csv:generic-api-key:284 4c9852dcd788730edfb9aaac3c7cca3a6777df9f:_bmad/_config/files-manifest.csv:generic-api-key:300 4c9852dcd788730edfb9aaac3c7cca3a6777df9f:_bmad/_config/files-manifest.csv:generic-api-key:409 4c9852dcd788730edfb9aaac3c7cca3a6777df9f:_bmad/_config/files-manifest.csv:generic-api-key:433 + +# Commit da36d9b3: same _bmad/_config/files-manifest.csv CSV rows as above +# (SHA256 content checksums of BMAD skill files). Same false-positive rationale. +da36d9b36916087f02c4c367ad6107ab7dbdb152:_bmad/_config/files-manifest.csv:generic-api-key:281 +da36d9b36916087f02c4c367ad6107ab7dbdb152:_bmad/_config/files-manifest.csv:generic-api-key:282 +da36d9b36916087f02c4c367ad6107ab7dbdb152:_bmad/_config/files-manifest.csv:generic-api-key:284 +da36d9b36916087f02c4c367ad6107ab7dbdb152:_bmad/_config/files-manifest.csv:generic-api-key:300 +da36d9b36916087f02c4c367ad6107ab7dbdb152:_bmad/_config/files-manifest.csv:generic-api-key:409 +da36d9b36916087f02c4c367ad6107ab7dbdb152:_bmad/_config/files-manifest.csv:generic-api-key:433 + +# Commit 38e9f745: same _bmad/_config/files-manifest.csv CSV rows as above +# (SHA256 content checksums of BMAD skill files). Same false-positive rationale. +38e9f74523fb9c79fa465831381c3ce9ac050c29:_bmad/_config/files-manifest.csv:generic-api-key:281 +38e9f74523fb9c79fa465831381c3ce9ac050c29:_bmad/_config/files-manifest.csv:generic-api-key:282 +38e9f74523fb9c79fa465831381c3ce9ac050c29:_bmad/_config/files-manifest.csv:generic-api-key:284 +38e9f74523fb9c79fa465831381c3ce9ac050c29:_bmad/_config/files-manifest.csv:generic-api-key:300 +38e9f74523fb9c79fa465831381c3ce9ac050c29:_bmad/_config/files-manifest.csv:generic-api-key:409 +38e9f74523fb9c79fa465831381c3ce9ac050c29:_bmad/_config/files-manifest.csv:generic-api-key:433 diff --git a/scripts/apply-repo-settings.sh b/scripts/apply-repo-settings.sh index 34365411..c2392494 100755 --- a/scripts/apply-repo-settings.sh +++ b/scripts/apply-repo-settings.sh @@ -1,69 +1,21 @@ #!/usr/bin/env bash -# Apply repository-level standard settings via the GitHub API. +# Apply repository-level security settings via the GitHub API. # -# Applies security_and_analysis settings and disables check-suite auto-trigger -# for apps that queue suites on every push without completing them (Claude, -# CodeRabbit), which permanently blocks GitHub auto-merge. +# Called by the apply-repo-settings workflow on every push to main so that +# settings documented in .github/settings.yml stay in effect even if they +# are reset manually. # -# Standard: petry-projects/.github/standards/github-settings.md -# #check-suite-auto-trigger-preferences -# -# Usage: -# bash scripts/apply-repo-settings.sh # e.g. TalkTerm -# bash scripts/apply-repo-settings.sh -# GITHUB_REPOSITORY=owner/repo bash scripts/apply-repo-settings.sh # CI form -# -# Environment: -# GH_TOKEN GitHub token. The check-suites API rejects OAuth app -# tokens — use a classic PAT with `repo` scope (or admin). -# ORG GitHub org used to expand a bare repo name (default: -# petry-projects). -# GITHUB_REPOSITORY owner/repo, used when no positional argument is given -# (set automatically by GitHub Actions). -# -# The helpers below are pure and side-effect-free so they can be sourced and -# unit-tested; main only runs when the script is executed directly. +# Required token scope: administration:write +# Usage (local): GH_TOKEN= GITHUB_REPOSITORY=petry-projects/TalkTerm \ +# ./scripts/apply-repo-settings.sh +set -euo pipefail -# App IDs whose check-suite auto-trigger must be disabled. GitHub creates a -# queued suite on every push when auto-trigger is on; these apps never complete -# those suites, permanently blocking auto-merge. -readonly -a CHECK_SUITE_APP_IDS=(1236702 347564) # Claude, CodeRabbit +REPO="${GITHUB_REPOSITORY:?GITHUB_REPOSITORY must be set (e.g. petry-projects/TalkTerm)}" -# resolve_repo -# Resolves the target "owner/repo". Precedence: positional arg, then -# GITHUB_REPOSITORY, then REPO. A bare name is expanded to "/". -# Returns non-zero if no repo can be determined. -resolve_repo() { - local repo="${1:-}" - [ -z "$repo" ] && repo="${GITHUB_REPOSITORY:-}" - [ -z "$repo" ] && repo="${REPO:-}" - [ -z "$repo" ] && return 1 - case "$repo" in - */*) printf '%s' "$repo" ;; - *) printf '%s/%s' "${ORG:-petry-projects}" "$repo" ;; - esac -} - -# auto_trigger_status -# Echoes the current auto_trigger setting for app_id: "true", "false", or -# "missing" (app absent from preferences — never run in repo, so compliant). -auto_trigger_status() { - local json="${1:-}" app_id="$2" - if [ -z "$json" ]; then - printf 'missing' - return 0 - fi - printf '%s' "$json" | jq -r --argjson id "$app_id" \ - '.preferences.auto_trigger_checks // [] - | map(select(.app_id == $id)) - | if length == 0 then "missing" else (.[0].setting | tostring) end' -} +echo "Applying security_and_analysis settings to ${REPO} ..." -# apply_security_and_analysis -apply_security_and_analysis() { - local repo="$1" - echo "Applying security_and_analysis settings to ${repo} ..." - gh api -X PATCH "repos/${repo}" --input - <<'JSON' +gh api -X PATCH "repos/${REPO}" \ + --input - <<'JSON' { "security_and_analysis": { "secret_scanning": { "status": "enabled" }, @@ -74,53 +26,20 @@ apply_security_and_analysis() { } } JSON -} - -# apply_check_suite_prefs -# Disables auto-trigger for any configured app that currently has it enabled. -# Apps that are "missing" (never run) or already "false" are compliant and left -# untouched. The check-suites/preferences GET endpoint is PATCH-only on GitHub -# and returns 404, so when preferences cannot be read we conservatively apply -# the disabling PATCH for every configured app. -apply_check_suite_prefs() { - local repo="$1" - echo "Configuring check-suite auto-trigger preferences for ${repo} ..." - - local prefs status app_id - local -a to_disable=() - if prefs=$(gh api "repos/${repo}/check-suites/preferences" 2>/dev/null) && [ -n "$prefs" ]; then - for app_id in "${CHECK_SUITE_APP_IDS[@]}"; do - status=$(auto_trigger_status "$prefs" "$app_id") - case "$status" in - missing) echo " app ${app_id}: never run in repo — compliant, skipping" ;; - false) echo " app ${app_id}: already disabled — skipping" ;; - *) echo " app ${app_id}: auto-trigger enabled — disabling"; to_disable+=("$app_id") ;; - esac - done - else - echo " could not read current preferences — applying disable for all configured apps" - to_disable=("${CHECK_SUITE_APP_IDS[@]}") - fi - if [ "${#to_disable[@]}" -eq 0 ]; then - echo " already compliant — nothing to do" - return 0 - fi +echo "Disabling CodeRabbit (app 347564) and Claude (app 1236702) check-suite auto-trigger ..." - local payload - payload=$(printf '%s\n' "${to_disable[@]}" | - jq -Rcn '[inputs | tonumber] | map({app_id: ., setting: false}) | {auto_trigger_checks: .}') - gh api -X PATCH "repos/${repo}/check-suites/preferences" --input - <<<"$payload" +# These apps create queued check suites on every push that are never completed, +# which permanently blocks auto-merge. Disabling auto-trigger prevents GitHub +# from creating those ghost check suites. +gh api -X PATCH "repos/${REPO}/check-suites/preferences" \ + --input - <<'JSON' +{ + "auto_trigger_checks": [ + { "app_id": 347564, "setting": false }, + { "app_id": 1236702, "setting": false } + ] } +JSON -# Run main only when executed directly, so tests can source the helpers. -if [ "${BASH_SOURCE[0]:-$0}" = "$0" ]; then - set -euo pipefail - repo="$(resolve_repo "${1:-}")" || { - echo "Usage: $0 (or set GITHUB_REPOSITORY)" >&2 - exit 1 - } - apply_security_and_analysis "$repo" - apply_check_suite_prefs "$repo" - echo "Done." -fi +echo "Done."