Repository navigation
feat: implement issue #398 — Compliance: secret_scanning_ai_detection #482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
f62da64
feat: implement issue #398 — Compliance: secret_scanning_ai_detection
donpetry-bot f20e318
chore: apply manual instructions [skip ci-relay]
donpetry-bot 402b0af
fix(reviews): address review comments [skip ci-relay]
donpetry-bot 42ac25b
Merge branch 'main' into dev-lead/issue-398-20260608-0049
don-petry aa30ccd
Merge branch 'main' into dev-lead/issue-398-20260608-0049
don-petry c15ace2
Merge branch 'main' into dev-lead/issue-398-20260608-0049
don-petry d5e4bc7
Merge branch 'main' into dev-lead/issue-398-20260608-0049
don-petry a4322d1
chore: apply manual instructions [skip ci-relay]
donpetry-bot 0a85a0e
Merge branch 'main' into dev-lead/issue-398-20260608-0049
don-petry 9ac9e7b
Merge branch 'main' into dev-lead/issue-398-20260608-0049
don-petry c23208d
fix: address review comments — safety flags, readonly array, dependab…
donpetry-bot 6ef9088
Merge branch 'main' into dev-lead/issue-398-20260608-0049
don-petry File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| #!/usr/bin/env bash | ||
|
don-petry marked this conversation as resolved.
|
||
| # push-protection.sh — required security_and_analysis settings and apply helper. | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| # | ||
| # Sourced by scripts that need to enforce or audit the push-protection standard: | ||
| # https://github.com/petry-projects/.github/blob/main/standards/push-protection.md | ||
| # | ||
| # PP_REQUIRED_SA_SETTINGS lists the security_and_analysis keys that must be | ||
| # "enabled" on every petry-projects repository. Adding a key here | ||
| # automatically extends both apply and audit logic that sources this file. | ||
| # | ||
| # Usage: | ||
| # source scripts/lib/push-protection.sh | ||
| # REPO=owner/repo pp_apply_security_and_analysis | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| readonly -a PP_REQUIRED_SA_SETTINGS=( | ||
| secret_scanning | ||
| secret_scanning_push_protection | ||
| secret_scanning_ai_detection | ||
| secret_scanning_non_provider_patterns | ||
| dependabot_security_updates | ||
|
don-petry marked this conversation as resolved.
don-petry marked this conversation as resolved.
don-petry marked this conversation as resolved.
|
||
| ) | ||
|
|
||
| # pp_apply_security_and_analysis | ||
| # Patches all PP_REQUIRED_SA_SETTINGS to "enabled" on $REPO. | ||
| # Honours DEV_LEAD_DRY_RUN=true (prints intent, makes no API call). | ||
| pp_apply_security_and_analysis() { | ||
| : "${REPO:?pp_apply_security_and_analysis: REPO must be set}" | ||
|
|
||
| if [ "${DEV_LEAD_DRY_RUN:-false}" = "true" ]; then | ||
| echo "[dry-run] would patch security_and_analysis on ${REPO}: ${PP_REQUIRED_SA_SETTINGS[*]}" | ||
| return 0 | ||
| fi | ||
|
|
||
| # Enable Dependabot alerts — prerequisite for dependabot_security_updates. | ||
| gh api -X PUT "repos/${REPO}/vulnerability-alerts" --silent 2>/dev/null || \ | ||
| echo "[warn] ${REPO} — could not enable vulnerability alerts (prerequisite for dependabot_security_updates)" >&2 | ||
|
|
||
| local failures=0 | ||
| for key in "${PP_REQUIRED_SA_SETTINGS[@]}"; do | ||
| local payload | ||
| payload=$(jq -n --arg k "$key" '{"security_and_analysis": {($k): {"status": "enabled"}}}') | ||
| if ! gh api -X PATCH "repos/${REPO}" --input - <<<"$payload"; then | ||
| echo "[warn] ${REPO} — could not enable ${key} (may require Advanced Security)" >&2 | ||
| failures=$((failures + 1)) | ||
| fi | ||
|
don-petry marked this conversation as resolved.
|
||
| done | ||
| return 0 | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| #!/usr/bin/env bats | ||
| # Unit tests for scripts/lib/push-protection.sh | ||
| # | ||
| # Run with: bats tests/test_push_protection.bats | ||
| # Install bats: https://github.com/bats-core/bats-core | ||
|
|
||
| setup() { | ||
| source "$(dirname "$BATS_TEST_FILENAME")/../scripts/lib/push-protection.sh" | ||
| # Capture API calls via a temp file so cross-subshell checks work. | ||
| GH_LOG="$(mktemp)" | ||
| gh() { echo "$*" >> "$GH_LOG"; } | ||
| export -f gh | ||
| export GH_LOG | ||
| unset REPO | ||
| unset DEV_LEAD_DRY_RUN | ||
| } | ||
|
|
||
| teardown() { | ||
| rm -f "${GH_LOG:-}" | ||
| } | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # PP_REQUIRED_SA_SETTINGS — the array must include every required key | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| @test "PP_REQUIRED_SA_SETTINGS includes secret_scanning" { | ||
| [[ " ${PP_REQUIRED_SA_SETTINGS[*]} " == *" secret_scanning "* ]] | ||
| } | ||
|
|
||
| @test "PP_REQUIRED_SA_SETTINGS includes secret_scanning_push_protection" { | ||
| [[ " ${PP_REQUIRED_SA_SETTINGS[*]} " == *" secret_scanning_push_protection "* ]] | ||
| } | ||
|
|
||
| @test "PP_REQUIRED_SA_SETTINGS includes secret_scanning_ai_detection" { | ||
| [[ " ${PP_REQUIRED_SA_SETTINGS[*]} " == *" secret_scanning_ai_detection "* ]] | ||
| } | ||
|
|
||
| @test "PP_REQUIRED_SA_SETTINGS includes secret_scanning_non_provider_patterns" { | ||
| [[ " ${PP_REQUIRED_SA_SETTINGS[*]} " == *" secret_scanning_non_provider_patterns "* ]] | ||
| } | ||
|
|
||
| @test "PP_REQUIRED_SA_SETTINGS includes dependabot_security_updates" { | ||
| [[ " ${PP_REQUIRED_SA_SETTINGS[*]} " == *" dependabot_security_updates "* ]] | ||
| } | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # pp_apply_security_and_analysis — dry-run mode | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| @test "dry-run skips gh api call" { | ||
| export DEV_LEAD_DRY_RUN=true | ||
| export REPO="owner/repo" | ||
| run pp_apply_security_and_analysis | ||
| [ "$status" -eq 0 ] | ||
| [ ! -s "$GH_LOG" ] | ||
| } | ||
|
|
||
| @test "dry-run prints what it would do" { | ||
| export DEV_LEAD_DRY_RUN=true | ||
| export REPO="owner/repo" | ||
| run pp_apply_security_and_analysis | ||
| [[ "$output" == *"dry-run"* ]] | ||
| } | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # pp_apply_security_and_analysis — live mode | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| @test "live mode calls gh api PATCH for the repo" { | ||
| export DEV_LEAD_DRY_RUN=false | ||
| export REPO="owner/repo" | ||
| run pp_apply_security_and_analysis | ||
| [ "$status" -eq 0 ] | ||
| [ -s "$GH_LOG" ] | ||
| grep -q "api" "$GH_LOG" | ||
| grep -q "PATCH" "$GH_LOG" | ||
| grep -q "owner/repo" "$GH_LOG" | ||
| } | ||
|
|
||
| @test "live mode PUTs vulnerability-alerts as prerequisite before PATCH loop" { | ||
| export DEV_LEAD_DRY_RUN=false | ||
| export REPO="owner/repo" | ||
| run pp_apply_security_and_analysis | ||
| [ "$status" -eq 0 ] | ||
| grep -q "vulnerability-alerts" "$GH_LOG" | ||
| } | ||
|
|
||
| @test "live mode errors when REPO is unset" { | ||
| export DEV_LEAD_DRY_RUN=false | ||
| unset REPO | ||
| run pp_apply_security_and_analysis | ||
| [ "$status" -ne 0 ] | ||
| } | ||
|
|
||
| @test "live mode makes one PATCH call per required setting" { | ||
| export DEV_LEAD_DRY_RUN=false | ||
| export REPO="owner/repo" | ||
| gh() { | ||
| local stdin_body="" | ||
| [ ! -t 0 ] && stdin_body=$(cat) | ||
| printf '%s BODY=%s\n' "$*" "$stdin_body" >> "$GH_LOG" | ||
| } | ||
| export -f gh | ||
| run pp_apply_security_and_analysis | ||
| [ "$status" -eq 0 ] | ||
| local patch_count | ||
| patch_count=$(grep -c "PATCH" "$GH_LOG") | ||
| [ "$patch_count" -eq "${#PP_REQUIRED_SA_SETTINGS[@]}" ] | ||
| } | ||
|
|
||
| @test "live mode continues applying remaining settings after one PATCH failure" { | ||
| export DEV_LEAD_DRY_RUN=false | ||
| export REPO="owner/repo" | ||
| export FAIL_KEY="${PP_REQUIRED_SA_SETTINGS[0]}" | ||
| gh() { | ||
| local stdin_body="" | ||
| [ ! -t 0 ] && stdin_body=$(cat) | ||
| printf '%s BODY=%s\n' "$*" "$stdin_body" >> "$GH_LOG" | ||
| echo "$stdin_body" | grep -q "\"${FAIL_KEY}\"" && return 1 | ||
| return 0 | ||
| } | ||
| export -f gh | ||
| run pp_apply_security_and_analysis | ||
| # All settings should be attempted even though the first one fails | ||
| local patch_count | ||
| patch_count=$(grep -c "PATCH" "$GH_LOG") | ||
| [ "$patch_count" -eq "${#PP_REQUIRED_SA_SETTINGS[@]}" ] | ||
| } | ||
|
|
||
| @test "live mode returns 0 when some PATCH calls fail (partial failure is non-fatal)" { | ||
| export DEV_LEAD_DRY_RUN=false | ||
| export REPO="owner/repo" | ||
| export FAIL_KEY="${PP_REQUIRED_SA_SETTINGS[0]}" | ||
| gh() { | ||
| local stdin_body="" | ||
| [ ! -t 0 ] && stdin_body=$(cat) | ||
| printf '%s BODY=%s\n' "$*" "$stdin_body" >> "$GH_LOG" | ||
| echo "$stdin_body" | grep -q "\"${FAIL_KEY}\"" && return 1 | ||
| return 0 | ||
| } | ||
| export -f gh | ||
| run pp_apply_security_and_analysis | ||
| # A 422 for one unavailable setting (e.g. secret_scanning_ai_detection without GHAS) | ||
| # must not abort callers running under set -euo pipefail; exit code must be 0. | ||
| [ "$status" -eq 0 ] | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.