Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
ace54d8
chore: add Dependabot with auto-merge via GitHub App (#2)
don-petry Mar 23, 2026
014699f
fix: remove gradle ecosystem from Dependabot config (#4)
don-petry Mar 24, 2026
92edb32
chore: add AGPL-3.0 + commercial dual licensing and CLA
Mar 25, 2026
b435f90
fix: address review feedback — fix naming, wording, and license format
Mar 25, 2026
21059fe
fix: standardize LICENSE file format and add copyright notice (#7)
don-petry Mar 26, 2026
5d2657d
chore: enable CodeRabbit for AI-powered PR reviews (#8)
don-petry Mar 26, 2026
3402b87
chore: refine CodeRabbit config to exclude non-code directories (#10)
don-petry Mar 26, 2026
80e9f3f
Add Claude Code GitHub Action (#12)
don-petry Mar 27, 2026
f43da46
fix: address OpenSSF Scorecard findings (#20)
don-petry Mar 28, 2026
993db98
ci: skip Claude Code reviewer on Dependabot PRs (#36)
don-petry Apr 1, 2026
624999a
chore(deps): bump actions/checkout from 4.3.1 to 6.0.2 (#34)
dependabot[bot] Apr 1, 2026
8c10bf3
chore(deps): bump anthropics/claude-code-action from 1.0.80 to 1.0.82…
dependabot[bot] Apr 1, 2026
03dbf79
ci: move Dependabot exclusion to step-level in Claude workflow (#37)
don-petry Apr 1, 2026
6c37021
chore(deps): bump anthropics/claude-code-action from 1.0.80 to 1.0.88…
dependabot[bot] Apr 4, 2026
ce26aa6
chore: enable Claude issue trigger per org CI standard (#53)
don-petry Apr 5, 2026
fa72f5e
fix: add checkout step to Claude workflow for issue-triggered mode (#54)
don-petry Apr 5, 2026
9da7497
feat: split Claude workflow into interactive + issue automation jobs …
don-petry Apr 6, 2026
19b5481
feat: switch to org-level reusable Claude Code workflow (#64)
don-petry Apr 6, 2026
ab0ac7a
chore: add CODEOWNERS file for code owner review enforcement
github-actions[bot] Apr 6, 2026
9c23b7b
chore(workflows): adopt centralized stubs from petry-projects/.github…
don-petry Apr 8, 2026
c16396f
chore(workflows): bump claude.yml stub to @v1 and add SOURCE OF TRUTH…
don-petry Apr 8, 2026
1d2e6ec
chore(deps): bump github/codeql-action from 3.35.1 to 4.35.2 (#134)
dependabot[bot] Apr 20, 2026
33d1e19
fix: correct reusable workflow path (remove duplicate .github/) (#140)
don-petry Apr 21, 2026
0a00882
Revert "fix: correct reusable workflow path (remove duplicate .github…
Apr 21, 2026
aeb4ab4
ci: add auto-rebase workflow and check_run trigger to claude.yml
don-petry Apr 21, 2026
8112f60
chore: add bot accounts to CODEOWNERS for auto-merge support
don-petry May 3, 2026
f63bc20
chore(deps): bump github/codeql-action from 4.35.2 to 4.35.3 (#150)
dependabot[bot] May 4, 2026
0677685
chore: standardize CODEOWNERS on @petry-projects/org-leads (#153)
don-petry May 4, 2026
ee1d765
docs(codeowners): tighten comment to match org standard format (#160)
don-petry May 10, 2026
a28bd49
chore(deps): bump github/codeql-action from 4.35.3 to 4.35.4 (#169)
dependabot[bot] May 11, 2026
88c623b
fix: move CODEOWNERS to repo root for compliance audit compatibility …
don-petry May 12, 2026
50fbb12
chore(dev-lead): remove claude.yml — replaced by dev-lead.yml (#174)
don-petry May 16, 2026
03f6720
chore(deps): bump github/codeql-action from 4.35.4 to 4.35.5 (#179)
dependabot[bot] May 19, 2026
b7d94e0
compliance: confirm allow_auto_merge is enabled (closes #89) (#122)
don-petry May 19, 2026
4a93db0
compliance: confirm allow_auto_merge is enabled (#103)
don-petry May 19, 2026
08fa387
compliance: confirm allow_auto_merge is enabled (closes #89) (#130)
don-petry May 19, 2026
18c8258
feat: implement issue #93 — Compliance: stray-codeql-workflow (#196)
don-petry May 23, 2026
3fb4a1f
feat: implement issue #249 — [Fleet Monitor] petry-projects/markets —…
don-petry Jun 3, 2026
16dd6c2
feat: implement issue #96 — Compliance: secret_scan_ci_job_present (#…
don-petry Jun 10, 2026
b1a9122
chore: sync 8 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Jul 13, 2026
4021264
fix: re-pin agent_ref inputs to v-form (missed by #657 uses:-only re-…
don-petry Jul 14, 2026
a48a934
feat: implement issue #325 — Compliance: ruleset-drift-pr-quality-req…
donpetry-bot Jul 21, 2026
bfed23d
chore: dev-lead update (review-changes) [skip ci-relay]
donpetry-bot Jul 21, 2026
41309ec
chore: sync 1 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Jul 22, 2026
7d9322e
chore: sync 2 org-standard workflow stub(s) from petry-projects/.gith…
don-petry Jul 23, 2026
52f0ac2
chore: dev-lead update (review-changes) [skip ci-relay]
donpetry-bot Aug 2, 2026
0b80714
fix(bot): address bot feedback [skip ci-relay]
donpetry-bot Aug 2, 2026
4d866bf
feat: implement issue #329 — Compliance: stub-surface-drift-feature-i…
don-petry Aug 2, 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
41 changes: 14 additions & 27 deletions .github/scripts/apply-pr-quality-ruleset.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
# apply-pr-quality-ruleset.sh — Idempotently create/update the pr-quality ruleset
#
# This script creates (or updates) the `pr-quality` repository ruleset that
# enforces pull-request quality gates on the default branch of
# enforces pull-request review quality gates on the default branch of
# petry-projects/markets.
#
# Pull-request rule parameters configured (codified standard, source of truth:
# petry-projects/.github/standards/rulesets/pr-quality.json — see #323, #324):
# - required_approving_review_count: 1
# - require_code_owner_review: true (drifted to false — issue #323)
# - required_review_thread_resolution: true
# - dismiss_stale_reviews_on_push: true (the drifted parameter — issue #324)
# - require_last_push_approval: true
# - allowed_merge_methods: ["squash"]
# petry-projects/.github/standards/rulesets/pr-quality.json — see #575/#580):
# - required_approving_review_count: 1 at least one approving review
# - require_code_owner_review: true CODEOWNERS must approve
# - required_review_thread_resolution: true all review threads resolved
# - dismiss_stale_reviews_on_push: true new pushes invalidate approvals
# - require_last_push_approval: true someone other than the last pusher
# must approve (drift fix — see #325)
# - allowed_merge_methods: ["squash"] squash-only merges
#
# Standard reference:
# https://github.com/petry-projects/.github/blob/main/standards/github-settings.md#pr-quality--standard-ruleset-all-repositories
Expand Down Expand Up @@ -40,8 +41,8 @@ export GH_TOKEN
EXISTING_ID=$(gh api "repos/$REPO/rulesets" \
--jq ".[] | select(.name == \"$RULESET_NAME\") | .id")

PAYLOAD=$(jq -n --arg name "$RULESET_NAME" '{
name: $name,
PAYLOAD=$(jq -n '{
name: "pr-quality",
target: "branch",
enforcement: "active",
conditions: {
Expand Down Expand Up @@ -82,21 +83,7 @@ if [ -n "$EXISTING_ID" ]; then
echo "Done — ruleset updated: https://github.com/$REPO/rules/$EXISTING_ID"
else
echo "Creating $RULESET_NAME ruleset ..."
# Capture stderr so a 422 conflict from concurrent creation doesn't terminate the script.
# On conflict, re-fetch the ID created by the concurrent run and update instead.
if RESULT=$(echo "$PAYLOAD" | gh api -X POST "repos/$REPO/rulesets" --input - 2>&1); then
NEW_ID=$(echo "$RESULT" | jq -r '.id')
echo "Done — ruleset created: https://github.com/$REPO/rules/$NEW_ID"
else
EXISTING_ID=$(gh api "repos/$REPO/rulesets" \
--jq ".[] | select(.name == \"$RULESET_NAME\") | .id")
if [ -z "$EXISTING_ID" ]; then
echo "ERROR: POST failed and no existing $RULESET_NAME ruleset found" >&2
echo "$RESULT" >&2
exit 1
fi
echo "Concurrent creation detected — updating $RULESET_NAME ruleset (id=$EXISTING_ID) ..."
echo "$PAYLOAD" | gh api -X PUT "repos/$REPO/rulesets/$EXISTING_ID" --input - > /dev/null
echo "Done — ruleset updated: https://github.com/$REPO/rules/$EXISTING_ID"
fi
RESULT=$(echo "$PAYLOAD" | gh api -X POST "repos/$REPO/rulesets" --input -)
NEW_ID=$(echo "$RESULT" | jq -r '.id')
echo "Done — ruleset created: https://github.com/$REPO/rules/$NEW_ID"
fi
2 changes: 1 addition & 1 deletion .github/scripts/apply-repo-settings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ echo "Applying code-quality required-status-checks ruleset ..."

"$SCRIPT_DIR/apply-code-quality-ruleset.sh"

echo "Applying pr-quality pull-request review ruleset ..."
echo "Applying pr-quality ruleset ..."

"$SCRIPT_DIR/apply-pr-quality-ruleset.sh"

Expand Down
87 changes: 50 additions & 37 deletions .github/scripts/tests/apply-pr-quality-ruleset.bats
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
#!/usr/bin/env bats
# Tests for apply-pr-quality-ruleset.sh — static content assertions, no live API calls.
# Tests for apply-pr-quality-ruleset.sh
#
# The pull_request rule parameters asserted below are the codified standard
# (petry-projects/.github/standards/rulesets/pr-quality.json), the source of
# truth referenced by issues #323 and #324. require_code_owner_review (#323)
# and dismiss_stale_reviews_on_push (#324) are the parameters that drifted to
# false and must be codified as true.
# Static checks verify the script's safety settings and target repo.
# The payload test mocks the gh CLI to capture the actual JSON sent to the
# GitHub API and uses jq to assert structure and values — avoids fragile
# grep-on-source-file assertions.

SCRIPT="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)/apply-pr-quality-ruleset.sh"

setup() {
export BATS_TMPDIR="$(mktemp -d)"
export GH_TOKEN="mock-token"
}

teardown() {
rm -rf "$BATS_TMPDIR"
}

@test "script exists and is executable" {
[ -f "$SCRIPT" ]
[ -x "$SCRIPT" ]
Expand All @@ -19,41 +27,46 @@ SCRIPT="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)/apply-pr-quality-rule
}

@test "script targets petry-projects/markets repo" {
grep -qE '^REPO="petry-projects/markets"$' "$SCRIPT"
}

@test "script declares the pr-quality ruleset" {
grep -qE 'RULESET_NAME\s*=\s*"pr-quality"' "$SCRIPT"
}

@test "script requires GH_TOKEN" {
grep -q 'GH_TOKEN' "$SCRIPT"
grep -q 'petry-projects/markets' "$SCRIPT"
}

@test "script sets dismiss_stale_reviews_on_push to true (issue #324)" {
grep -qE '^[[:space:]]+dismiss_stale_reviews_on_push[[:space:]]*:[[:space:]]*true[[:space:]]*,?[[:space:]]*$' "$SCRIPT"
}

@test "script requires one approving review" {
grep -qE '^[[:space:]]+required_approving_review_count[[:space:]]*:[[:space:]]*1[[:space:]]*,?[[:space:]]*$' "$SCRIPT"
}

@test "script requires code owner review (issue #323)" {
grep -qE '^[[:space:]]+require_code_owner_review[[:space:]]*:[[:space:]]*true[[:space:]]*,?[[:space:]]*$' "$SCRIPT"
}
@test "script generates correct ruleset payload" {
gh() {
if [ "$1" = "api" ]; then
if [ "$2" = "repos/petry-projects/markets/rulesets" ]; then
echo ""
return 0
elif [ "$2" = "-X" ] && [ "$3" = "POST" ]; then
cat > "$BATS_TMPDIR/payload.json"
echo '{"id": 12345}'
return 0
fi
fi
command gh "$@"
}
export -f gh

@test "script requires review thread resolution" {
grep -qE '^[[:space:]]+required_review_thread_resolution[[:space:]]*:[[:space:]]*true[[:space:]]*,?[[:space:]]*$' "$SCRIPT"
}
run bash "$SCRIPT"
[ "$status" -eq 0 ]

@test "script requires last push approval" {
grep -qE '^[[:space:]]+require_last_push_approval[[:space:]]*:[[:space:]]*true[[:space:]]*,?[[:space:]]*$' "$SCRIPT"
}
[ "$(jq -r '.name' "$BATS_TMPDIR/payload.json")" = "pr-quality" ]
[ "$(jq -r '.target' "$BATS_TMPDIR/payload.json")" = "branch" ]
[ "$(jq -r '.enforcement' "$BATS_TMPDIR/payload.json")" = "active" ]
[ "$(jq -r '.conditions.ref_name.include[0]' "$BATS_TMPDIR/payload.json")" = "~DEFAULT_BRANCH" ]
[ "$(jq -r '.rules[0].type' "$BATS_TMPDIR/payload.json")" = "pull_request" ]

@test "script restricts allowed_merge_methods to squash" {
grep -qE 'allowed_merge_methods:\s*\[\s*"squash"\s*\]' "$SCRIPT"
}
local params=".rules[0].parameters"
[ "$(jq -r "$params.required_approving_review_count" "$BATS_TMPDIR/payload.json")" -eq 1 ]
[ "$(jq -r "$params.require_code_owner_review" "$BATS_TMPDIR/payload.json")" = "true" ]
[ "$(jq -r "$params.required_review_thread_resolution" "$BATS_TMPDIR/payload.json")" = "true" ]
[ "$(jq -r "$params.dismiss_stale_reviews_on_push" "$BATS_TMPDIR/payload.json")" = "true" ]
[ "$(jq -r "$params.require_last_push_approval" "$BATS_TMPDIR/payload.json")" = "true" ]
[ "$(jq -r "$params.allowed_merge_methods[0]" "$BATS_TMPDIR/payload.json")" = "squash" ]

@test "script declares a pull_request rule type" {
grep -qE 'type:\s*"pull_request"' "$SCRIPT"
[ "$(jq '.bypass_actors | length' "$BATS_TMPDIR/payload.json")" -eq 2 ]
[ "$(jq -r '.bypass_actors[0].actor_type' "$BATS_TMPDIR/payload.json")" = "OrganizationAdmin" ]
[ "$(jq -r '.bypass_actors[0].bypass_mode' "$BATS_TMPDIR/payload.json")" = "always" ]
[ "$(jq -r '.bypass_actors[1].actor_type' "$BATS_TMPDIR/payload.json")" = "Integration" ]
[ "$(jq -r '.bypass_actors[1].bypass_mode' "$BATS_TMPDIR/payload.json")" = "always" ]
[ "$(jq '.bypass_actors[1].actor_id' "$BATS_TMPDIR/payload.json")" -eq 3167543 ]
}
Comment thread
don-petry marked this conversation as resolved.
2 changes: 1 addition & 1 deletion .github/scripts/tests/apply-repo-settings.bats
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ SCRIPT="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)/apply-repo-settings.s
grep -q 'apply-code-quality-ruleset.sh' "$SCRIPT"
}

@test "script wires in pr-quality ruleset application (issues #323, #324)" {
@test "script wires in pr-quality ruleset application (issue #325)" {
grep -q 'apply-pr-quality-ruleset.sh' "$SCRIPT"
}
2 changes: 1 addition & 1 deletion .github/workflows/add-to-project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ jobs:
# `secrets: inherit` handing the reusable every org secret).
secrets:
INITIATIVES_APP_ID: ${{ secrets.INITIATIVES_APP_ID }}
INITIATIVES_APP_PRIVATE_KEY: ${{ secrets.INITIATIVES_APP_PRIVATE_KEY }}
INITIATIVES_APP_PRIVATE_KEY: ${{ secrets.INITIATIVES_APP_PRIVATE_KEY }}
8 changes: 4 additions & 4 deletions .github/workflows/dev-lead.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ permissions: {}

jobs:
dev-lead:
# Pinned to the moving dev-lead/stable channel tag, not @main, so a broken
# 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/stable tag centrally; this
# 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/stable # NOSONAR(githubactions:S7637) first-party channel ref
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/stable
agent_ref: dev-lead/v1-stable
secrets: inherit # NOSONAR(githubactions:S7635) first-party trusted reusable
permissions:
contents: write
Expand Down
Loading