fix: auto-create missing required labels during compliance audit#79
fix: auto-create missing required labels during compliance audit#79
Conversation
Replace passive `missing-label-*` findings with active label creation. `check_labels()` now calls `gh label create --force` for any required label absent from a repo. A compliance finding is only filed if creation fails (insufficient permissions) or when running in DRY_RUN mode. Resolves the recurring `missing-label-scorecard` finding (#47) by creating the label on the next audit run rather than just reporting it. Co-authored-by: don-petry <don-petry@users.noreply.github.com>
|
@don-petry — no CODEOWNERS file exists in this repo. Please review and merge this PR when ready. |
|
📝 WalkthroughWalkthroughThe compliance audit script replaces a hardcoded label list with structured label specifications containing metadata (color and description). The label-checking function now automatically creates missing labels via GitHub CLI in non-dry-run mode, with fallback warning generation on creation failure. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR makes the compliance audit proactive by automatically creating missing required GitHub labels (instead of only reporting them), while still reporting findings in dry-run mode or when label creation fails.
Changes:
- Replace
REQUIRED_LABELSwith structuredREQUIRED_LABEL_SPECS(name/color/description). - Update
check_labels()to create missing labels viagh label create --forcewhen not inDRY_RUN. - Only file a compliance finding when
DRY_RUN=trueor label creation fails.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for label in "${REQUIRED_LABELS[@]}"; do | ||
| for spec in "${REQUIRED_LABEL_SPECS[@]}"; do | ||
| IFS=':' read -r label color description <<< "$spec" | ||
| if ! echo "$existing_labels" | grep -qx "$label"; then |
There was a problem hiding this comment.
grep -qx interprets $label as a regex pattern. Even though current required labels are simple, this becomes fragile if a future required label contains regex metacharacters (e.g., . or []). Use fixed-string matching (e.g., grep -F) to ensure label names are treated literally.
| @@ -301,11 +310,28 @@ check_labels() { | |||
| local existing_labels | |||
| existing_labels=$(gh_api "repos/$ORG/$repo/labels" --jq '.[].name' --paginate 2>/dev/null || echo "") | |||
There was a problem hiding this comment.
If gh_api fails (rate limit/transient error/permission), existing_labels becomes empty and the script will attempt to create (and --force update) all required labels. That can unintentionally overwrite existing label colors/descriptions based solely on a list failure. Consider treating “unable to list labels” as its own finding and skipping auto-create in that case, and/or only using --force when you’ve positively confirmed absence. Also, redirecting stderr to /dev/null removes useful diagnostics for audit logs; it would be more actionable to preserve or capture the error output when creation fails.
| if gh label create "$label" \ | ||
| --repo "$ORG/$repo" \ | ||
| --color "$color" \ | ||
| --description "$description" \ | ||
| --force 2>/dev/null; then |
There was a problem hiding this comment.
If gh_api fails (rate limit/transient error/permission), existing_labels becomes empty and the script will attempt to create (and --force update) all required labels. That can unintentionally overwrite existing label colors/descriptions based solely on a list failure. Consider treating “unable to list labels” as its own finding and skipping auto-create in that case, and/or only using --force when you’ve positively confirmed absence. Also, redirecting stderr to /dev/null removes useful diagnostics for audit logs; it would be more actionable to preserve or capture the error output when creation fails.
| for spec in "${REQUIRED_LABEL_SPECS[@]}"; do | ||
| IFS=':' read -r label color description <<< "$spec" |
There was a problem hiding this comment.
Using : as the field delimiter makes descriptions unable to contain colons (they’ll be split and truncated). Since label descriptions are freeform text, this is a brittle encoding. Consider switching to a delimiter that’s less likely to appear in descriptions (or storing specs in a more structured way, e.g., separate arrays / JSON and parsing with jq) to avoid subtle parsing bugs later.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/compliance-audit.sh`:
- Around line 38-47: The script defines REQUIRED_LABEL_SPECS but
ensure_required_labels() uses a separate hardcoded label list causing metadata
drift (e.g., scorecard description) and --force can overwrite the canonical
spec; update ensure_required_labels() to read and parse REQUIRED_LABEL_SPECS
(not a second array) when creating/updating labels, remove the
duplicated/hardcoded label definitions inside ensure_required_labels(), and
ensure creation/update logic for label names, colors and descriptions uses the
parsed REQUIRED_LABEL_SPECS values so the spec remains the single source of
truth.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 882ea44e-64eb-4fa2-b4b8-85a02d5c110f
📒 Files selected for processing (1)
scripts/compliance-audit.sh
| # name:hex-color:description (color without leading #) | ||
| REQUIRED_LABEL_SPECS=( | ||
| "security:d93f0b:Security-related PRs and issues" | ||
| "dependencies:0075ca:Dependency update PRs" | ||
| "scorecard:d93f0b:OpenSSF Scorecard findings (auto-created)" | ||
| "bug:d73a4a:Bug reports" | ||
| "enhancement:a2eeef:Feature requests" | ||
| "documentation:0075ca:Documentation changes" | ||
| "in-progress:fbca04:An agent is actively working this issue" | ||
| ) |
There was a problem hiding this comment.
Unify required-label metadata to a single source of truth.
REQUIRED_LABEL_SPECS is standards-aligned, but ensure_required_labels() still hardcodes a second label list with different metadata (notably scorecard description). Since ensure_required_labels() runs with --force, it can overwrite the new spec and cause drift.
Proposed refactor
# Create all required labels (idempotent — uses --force to update if present)
ensure_required_labels() {
local repo="$1"
- # Format: "name|color|description" (pipe-delimited to avoid colon conflicts)
- local label_configs=(
- "security|d93f0b|Security-related PRs and issues"
- "dependencies|0075ca|Dependency update PRs"
- "scorecard|d93f0b|OpenSSF Scorecard findings"
- "bug|d73a4a|Bug reports"
- "enhancement|a2eeef|Feature requests"
- "documentation|0075ca|Documentation changes"
- "in-progress|fbca04|An agent is actively working this issue"
- )
-
- for config in "${label_configs[@]}"; do
- IFS='|' read -r name color description <<< "$config"
+ for spec in "${REQUIRED_LABEL_SPECS[@]}"; do
+ IFS=':' read -r name color description <<< "$spec"
gh label create "$name" \
--repo "$ORG/$repo" \
--description "$description" \
--color "$color" \
--force 2>/dev/null || true
done
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/compliance-audit.sh` around lines 38 - 47, The script defines
REQUIRED_LABEL_SPECS but ensure_required_labels() uses a separate hardcoded
label list causing metadata drift (e.g., scorecard description) and --force can
overwrite the canonical spec; update ensure_required_labels() to read and parse
REQUIRED_LABEL_SPECS (not a second array) when creating/updating labels, remove
the duplicated/hardcoded label definitions inside ensure_required_labels(), and
ensure creation/update logic for label names, colors and descriptions uses the
parsed REQUIRED_LABEL_SPECS values so the spec remains the single source of
truth.



Summary
missing-label-*compliance finding with active label creationcheck_labels()now callsgh label create --forcefor any required label absent from a repoDRY_RUN=trueREQUIRED_LABEL_SPECSarray with name, hex color, and description per the standardREQUIRED_LABELSarrayCloses #47
Test plan
scorecardlabel (and any other missing labels) are created on repos that lack themDRY_RUN=truestill files findings without modifying reposGenerated with Claude Code
Summary by CodeRabbit
New Features
Improvements