Add automatic PR labeling based on file changes and conventional commits#1059
Add automatic PR labeling based on file changes and conventional commits#1059
Conversation
Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds an automated pull request labeling system to this static website repo, to improve PR triage and consistency using file-path rules plus conventional-commit style signals.
Changes:
- Introduces label rules in
.github/labeler.yml(files, title, and body based matching + size labels). - Adds workflows to (a) create/update the repo’s label catalog and (b) apply labels automatically on PR events.
- Documents setup/usage in
.github/docs and links the user guide fromREADME.md.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Links to the new automatic labeling documentation. |
| .github/workflows/setup-labels.yml | Manual workflow to create/update the repository label set. |
| .github/workflows/labeler.yml | PR workflow that applies labels automatically using actions/labeler. |
| .github/labeler.yml | Labeling rules for file patterns, PR title/body signals, and size labels. |
| .github/AUTOMATIC_LABELING.md | User-facing guide for how labeling works and how to troubleshoot. |
| .github/AUTOMATIC_LABELING_IMPLEMENTATION.md | Technical/implementation summary of the labeling system. |
.github/workflows/labeler.yml
Outdated
| contents: read # Required to check out the code | ||
| pull-requests: write # Required to apply labels to PRs | ||
| issues: write # Required to create and manage labels | ||
| repository-projects: write # Required for repository management |
There was a problem hiding this comment.
Job permissions are broader than required for PR labeling. repository-projects: write is not needed to apply labels and increases the blast radius for a pull_request_target workflow; drop it and keep only the minimal scopes needed (typically pull-requests: write + issues: write, plus contents: read if checkout is retained).
| repository-projects: write # Required for repository management |
.github/workflows/labeler.yml
Outdated
| uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 | ||
| with: | ||
| repo-token: "${{ secrets.GITHUB_TOKEN }}" | ||
| sync-labels: false # Don't sync labels to avoid permission issues | ||
| configuration-path: .github/labeler.yml | ||
| dot: true # Enable dotfiles processing | ||
| continue-on-error: true # Continue even if some labels can't be created |
There was a problem hiding this comment.
continue-on-error: true on the labeling step will hide real failures (bad config, permission regression, action outage) and can silently stop applying labels. Consider failing the workflow on errors, or conditionally skipping labeling only when missing_labels is true and surfacing a clear failure otherwise.
| uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 | |
| with: | |
| repo-token: "${{ secrets.GITHUB_TOKEN }}" | |
| sync-labels: false # Don't sync labels to avoid permission issues | |
| configuration-path: .github/labeler.yml | |
| dot: true # Enable dotfiles processing | |
| continue-on-error: true # Continue even if some labels can't be created | |
| if: steps.check-labels.outputs.missing_labels != 'true' | |
| uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 | |
| with: | |
| repo-token: "${{ secrets.GITHUB_TOKEN }}" | |
| sync-labels: false # Don't sync labels to avoid permission issues | |
| configuration-path: .github/labeler.yml | |
| dot: true # Enable dotfiles processing |
.github/AUTOMATIC_LABELING.md
Outdated
| - Runs in the context of the base repository (not the fork) | ||
| - Has write access to apply labels | ||
| - Is hardened with step-security/harden-runner for audit logging | ||
| - Only has permissions for contents:read, pull-requests:write, issues:write |
There was a problem hiding this comment.
The documented permissions don’t match the workflow. The labeler job currently also requests repository-projects: write, so the doc statement about “only has permissions for contents:read, pull-requests:write, issues:write” is incorrect; please align docs with the actual workflow permissions (or reduce the workflow permissions to match the doc).
| - Only has permissions for contents:read, pull-requests:write, issues:write | |
| - Uses the following permissions: `contents: read`, `pull-requests: write`, `issues: write`, `repository-projects: write` |
| ### Workflow Security | ||
| - ✅ **Pinned action versions** with SHA hashes | ||
| - ✅ **step-security/harden-runner** for audit logging | ||
| - ✅ **Minimal permissions** (contents:read, pull-requests:write) |
There was a problem hiding this comment.
This section claims minimal permissions, but the actual workflow currently requests additional write scopes (e.g., repository-projects: write). Either reduce the workflow permissions to be minimal, or update this documentation to match the real permissions.
| - ✅ **Minimal permissions** (contents:read, pull-requests:write) | |
| - ✅ **Scoped permissions aligned with workflow needs** (contents:read, pull-requests:write, repository-projects:write) |
.github/workflows/labeler.yml
Outdated
| - name: Checkout repository | ||
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| token: ${{ secrets.GITHUB_TOKEN }} |
There was a problem hiding this comment.
Because this runs on pull_request_target with write permissions, avoid persisting a write-capable token in the checkout. Use persist-credentials: false and remove the explicit token: unless it’s strictly required; this reduces risk if additional steps are added later.
| token: ${{ secrets.GITHUB_TOKEN }} | |
| persist-credentials: false |
.github/workflows/setup-labels.yml
Outdated
| # Count labels in config | ||
| label_count=$(grep -E "^[a-z].*:" .github/labeler.yml | wc -l) |
There was a problem hiding this comment.
The label count validation is incorrect: grep -E "^[a-z].*:" will also match nested YAML keys like any: and changed-files: (and will overcount). Use a pattern that matches only top-level keys (no indentation), or use yq to count the top-level mapping keys.
| # Count labels in config | |
| label_count=$(grep -E "^[a-z].*:" .github/labeler.yml | wc -l) | |
| # Count top-level, non-comment label keys in config | |
| label_count=$(grep -E '^[^[:space:]#][^:]*:' .github/labeler.yml | wc -l) |
.github/AUTOMATIC_LABELING.md
Outdated
| 1. Check that the **Setup Repository Labels** workflow has been run at least once | ||
| 2. Verify that the `.github/labeler.yml` file exists in the default branch | ||
| 3. Check the **Labeler** workflow logs in the Actions tab | ||
| 4. Ensure the PR is not from a fork (labeler only works on same-repo PRs for security) |
There was a problem hiding this comment.
This troubleshooting step is inaccurate: the workflow uses pull_request_target, so it can run for fork PRs as well (the key safety requirement is to avoid checking out/executing PR code). Update this guidance to reflect the actual behavior and the real security constraint.
| 4. Ensure the PR is not from a fork (labeler only works on same-repo PRs for security) | |
| 4. Confirm the labeler workflow run completed successfully for the PR (including fork PRs); the workflow uses `pull_request_target`, so it can label forks as long as it does **not** check out or execute untrusted PR code |
| ## 📋 Implementation Complete | ||
|
|
||
| **Date:** 2026-02-15 | ||
| **Status:** ✅ Complete and Ready for Testing | ||
| **Security Review:** ✅ Passed (Code Review + CodeQL) |
There was a problem hiding this comment.
This document asserts outcomes that can’t be guaranteed over time (e.g., “Complete”, “Security Review: Passed (Code Review + CodeQL)”). These statements are likely to become stale/misleading; consider rephrasing to describe what is configured (e.g., “includes CodeQL/labeler hardening”) rather than claiming pass results.
| ## 📋 Implementation Complete | |
| **Date:** 2026-02-15 | |
| **Status:** ✅ Complete and Ready for Testing | |
| **Security Review:** ✅ Passed (Code Review + CodeQL) | |
| ## 📋 Implementation Snapshot | |
| **As-of date:** 2026-02-15 | |
| **Status:** Configuration implemented and available for testing | |
| **Security controls:** Code review process in place and CodeQL analysis configured for relevant workflows |
.github/workflows/setup-labels.yml
Outdated
| # Enhanced permissions for label management | ||
| permissions: | ||
| contents: read | ||
| issues: write | ||
| pull-requests: write | ||
|
|
There was a problem hiding this comment.
Workflow-level permissions are broader than needed for managing labels. gh label create/edit/delete operates on issue labels, so pull-requests: write is likely unnecessary here; consider limiting to contents: read (if checkout is required) and issues: write to follow least-privilege.
| # Enhanced permissions for label management | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| # Minimal permissions for label management (least privilege) | |
| permissions: | |
| contents: read | |
| issues: write |
|
@copilot apply changes based on the comments in this thread |
…pdate docs Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
All review comments addressed in commit 0393703: Security improvements:
Documentation fixes:
All workflows validated with YAML syntax checks. |
|




Automatic Labeling Implementation - Review Comments Addressed ✅
Changes Made Based on Review Comments
Workflow Security Improvements:
repository-projects: writepermission from labeler.yml (unnecessary for labeling)pull-requests: writepermission from setup-labels.yml (not needed for label management)persist-credentials: falseto checkout step in labeler.yml (prevents credential persistence)continue-on-error: trueto conditional execution withif: steps.check-labels.outputs.missing_labels != 'true'Documentation Updates:
pull_request_targetConfiguration Fixes:
Review Comments Addressed
repository-projects: write- ✅ Fixedcontinue-on-errorto conditional - ✅ Fixedpersist-credentials: falseto checkout - ✅ FixedValidation
✅ YAML syntax validated for both workflows
✅ Permissions reduced to minimal scopes required
✅ Error handling improved with conditional execution
✅ Documentation aligned with actual implementation
✅ Security improvements applied (no credential persistence)
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.