Skip to content

Commit 799544f

Browse files
feat: auto-label PRs touching aidlc-rules/ with codebuild label (#158)
* feat: auto-label PRs using actions/labeler Adds an auto-label job to the Pull Request Validation workflow using actions/labeler v6.0.1. Labels are applied based on changed file paths and removed when those files are no longer changed (sync-labels: true). Works for fork PRs via pull_request_target — no checkout of fork code, the action only reads file paths from the API. Initial label rules: - codebuild: aidlc-rules/** - documentation: **/*.md, docs/** - workflows: .github/** * refactor: rename label to 'rules', refine labeler config - Rename 'codebuild' label to 'rules' in codebuild.yml (conditions, reminder text, and marker) - Rename 'workflows' label to 'github' matching .github/** - Scope 'documentation' label to *.md files NOT under aidlc-rules/ using all-globs-to-any-file with negation * fix: add issues:write permission for auto-label job Allows actions/labeler to create labels that don't yet exist in the repository, preventing failures on first use of a new label rule. * docs: update administrative guide for auto-labeling and rules label - Rename all 'codebuild' label references to 'rules' (preserving CodeBuild service/environment references) - Add auto-label job to Pipeline 3 diagram and workflow reference - Document label rules table (rules, documentation, github) - Add actions/labeler to external actions table - Add auto-label job to permissions table - Add labeler.yml to repository tree diagram --------- Co-authored-by: Scott Schreckengaust <345885+scottschreckengaust@users.noreply.github.com>
1 parent accaa5a commit 799544f

4 files changed

Lines changed: 64 additions & 19 deletions

File tree

.github/labeler.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Auto-label configuration for actions/labeler
2+
# See https://github.com/actions/labeler#match-object for syntax
3+
4+
rules:
5+
- changed-files:
6+
- any-glob-to-any-file: 'aidlc-rules/**'
7+
8+
documentation:
9+
- changed-files:
10+
- all-globs-to-any-file:
11+
- '**/*.md'
12+
- '!aidlc-rules/**'
13+
14+
github:
15+
- changed-files:
16+
- any-glob-to-any-file: '.github/**'

.github/workflows/codebuild.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ concurrency:
2525

2626
env:
2727
CODEBUILD_PROJECT_NAME: ${{ vars.CODEBUILD_PROJECT_NAME || 'codebuild-project' }}
28-
LABEL_REMINDER_MARKER: codebuild-label-reminder
28+
LABEL_REMINDER_MARKER: rules-label-reminder
2929

3030
permissions:
3131
actions: none
@@ -48,17 +48,17 @@ jobs:
4848
label-reminder:
4949
if: >-
5050
github.event_name == 'pull_request'
51-
&& !contains(github.event.pull_request.labels.*.name, 'codebuild')
51+
&& !contains(github.event.pull_request.labels.*.name, 'rules')
5252
5353
permissions:
5454
pull-requests: write
5555

5656
runs-on: ubuntu-latest
5757

5858
steps:
59-
- name: Warn about missing codebuild label
59+
- name: Warn about missing rules label
6060
run: |
61-
echo "::warning::This PR changes aidlc-rules/ but does not have the 'codebuild' label. Add the label to trigger the CodeBuild evaluation pipeline."
61+
echo "::warning::This PR changes aidlc-rules/ but does not have the 'rules' label. Add the label to trigger the CodeBuild evaluation pipeline."
6262
6363
- name: Comment on PR
6464
if: github.event.pull_request.head.repo.full_name == github.repository
@@ -76,9 +76,9 @@ jobs:
7676
exit 0
7777
fi
7878
BODY="<!-- $MARKER -->
79-
> **Note:** This PR changes \`aidlc-rules/\` but the \`codebuild\` label has not been applied.
79+
> **Note:** This PR changes \`aidlc-rules/\` but the \`rules\` label has not been applied.
8080
>
81-
> A maintainer must add the **codebuild** label to trigger the CodeBuild evaluation pipeline.
81+
> A maintainer must add the **rules** label to trigger the CodeBuild evaluation pipeline.
8282
> Once labeled, subsequent pushes will re-trigger the build automatically."
8383
gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$BODY"
8484
@@ -90,7 +90,7 @@ jobs:
9090
label-cleanup:
9191
if: >-
9292
github.event_name == 'pull_request'
93-
&& contains(github.event.pull_request.labels.*.name, 'codebuild')
93+
&& contains(github.event.pull_request.labels.*.name, 'rules')
9494
&& github.event.pull_request.head.repo.full_name == github.repository
9595
9696
permissions:
@@ -123,7 +123,7 @@ jobs:
123123
build:
124124
if: >-
125125
github.event_name != 'pull_request'
126-
|| contains(github.event.pull_request.labels.*.name, 'codebuild')
126+
|| contains(github.event.pull_request.labels.*.name, 'rules')
127127
environment: codebuild
128128

129129
permissions:

.github/workflows/pull-request-lint.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,19 @@ jobs:
165165
test
166166
requireScope: false
167167

168+
auto-label:
169+
name: Auto-label
170+
runs-on: ubuntu-latest
171+
permissions:
172+
contents: read
173+
issues: write
174+
pull-requests: write
175+
if: github.event_name == 'pull_request_target'
176+
steps:
177+
- uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
178+
with:
179+
sync-labels: true
180+
168181
contributorStatement:
169182
name: Require Contributor Statement
170183
runs-on: ubuntu-latest

docs/ADMINISTRATIVE_GUIDE.md

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ awslabs/aidlc-workflows/
4444
├── .github/
4545
│ ├── CODEOWNERS
4646
│ ├── ISSUE_TEMPLATE/ # Bug, feature, RFC, docs templates
47+
│ ├── labeler.yml # Auto-label rules (path → label mapping)
4748
│ ├── pull_request_template.md # PR template with contributor statement
4849
│ └── workflows/
4950
│ ├── codebuild.yml # CI via AWS CodeBuild
@@ -116,7 +117,7 @@ The release flow is **changelog-first**: the CHANGELOG is updated *before* the t
116117
flowchart LR
117118
A["git push main"] --> B{{"Manual approval\n(codebuild environment)"}}
118119
C["workflow_dispatch\n(no tag input)"] --> B
119-
D["pull_request\n(aidlc-rules/** changed)"] --> E{"codebuild\nlabel?"}
120+
D["pull_request\n(aidlc-rules/** changed)"] --> E{"rules\nlabel?"}
120121
E -->|yes| F["label-cleanup\n(remove reminder comment)"]
121122
F --> B
122123
E -->|no| I["label-reminder\n(warning + PR comment)"]
@@ -135,9 +136,10 @@ flowchart TD
135136
B --> E["fail-by-label\n(do-not-merge label)"]
136137
A --> F["validate\n(conventional commit title)"]
137138
A --> G["contributorStatement\n(acknowledgment in PR body)"]
139+
A --> H["auto-label\n(actions/labeler)"]
138140
```
139141

140-
`pull-request-lint.yml` runs on every PR targeting `main` and on merge queue checks. It enforces four gates: conventional commit PR titles, the contributor statement from the PR template, a configurable merge-halt mechanism, and a do-not-merge label check. The workflow uses `pull_request_target` (not `pull_request`) so it runs in the context of the base branch — this is safe because it never checks out PR code.
142+
`pull-request-lint.yml` runs on every PR targeting `main` and on merge queue checks. It enforces four gates (conventional commit PR titles, the contributor statement from the PR template, a configurable merge-halt mechanism, and a do-not-merge label check) and automatically applies labels based on changed file paths. The workflow uses `pull_request_target` (not `pull_request`) so it runs in the context of the base branch — this is safe because it never checks out PR code and the `auto-label` job uses `actions/labeler` which only reads file paths from the API.
141143

142144
---
143145

@@ -216,24 +218,24 @@ flowchart TD
216218

217219
**Purpose:** Runs an AWS CodeBuild project, downloads primary and secondary artifacts from S3, caches them in GitHub Actions cache, uploads them as workflow artifacts, and (when triggered from a `v*` tag) attaches them to the GitHub Release.
218220

219-
**PR label gate:** For `pull_request` events, the workflow only fires when files under `aidlc-rules/**` are changed (via `paths` filter) and the `build` job only runs when the `codebuild` label is present on the PR (via `contains(github.event.pull_request.labels.*.name, 'codebuild')`). The trigger includes `types: [opened, synchronize, reopened, labeled]` so that subsequent pushes to a labeled PR re-trigger the build automatically. `push`, `workflow_dispatch`, and tag events bypass the label check entirely.
221+
**PR label gate:** For `pull_request` events, the workflow only fires when files under `aidlc-rules/**` are changed (via `paths` filter) and the `build` job only runs when the `rules` label is present on the PR (via `contains(github.event.pull_request.labels.*.name, 'rules')`). The `rules` label is applied automatically by the `auto-label` job in `pull-request-lint.yml` (see [Pull Request Validation Workflow](#pull-request-validation-workflow-pull-request-lintyml)). The trigger includes `types: [opened, synchronize, reopened, labeled]` so that subsequent pushes to a labeled PR re-trigger the build automatically. `push`, `workflow_dispatch`, and tag events bypass the label check entirely.
220222

221-
**Job: `label-reminder`** (PR only, no `codebuild` label)
223+
**Job: `label-reminder`** (PR only, no `rules` label)
222224

223225
| Step | Name | Action |
224226
| ---- | -------------------------------- | ------------------------------------------------------------------------------------------ |
225-
| 1 | Warn about missing codebuild label | Emits a `::warning::` annotation visible in the Actions summary |
227+
| 1 | Warn about missing rules label | Emits a `::warning::` annotation visible in the Actions summary |
226228
| 2 | Comment on PR | Posts a one-time PR comment (idempotent — skips if the reminder comment already exists) |
227229

228-
This job runs only for `pull_request` events where `aidlc-rules/**` changed but the `codebuild` label is absent. It alerts maintainers and reviewers that the evaluation pipeline was not triggered. The comment is posted once per PR using an HTML comment marker (`<!-- codebuild-label-reminder -->`) to avoid duplicates.
230+
This job runs only for `pull_request` events where `aidlc-rules/**` changed but the `rules` label is absent. It alerts maintainers and reviewers that the evaluation pipeline was not triggered. The comment is posted once per PR using an HTML comment marker (`<!-- rules-label-reminder -->`) to avoid duplicates. In normal operation, the `auto-label` job in `pull-request-lint.yml` applies the `rules` label automatically, so this job serves as a fallback safety net.
229231

230-
**Job: `label-cleanup`** (PR only, `codebuild` label present)
232+
**Job: `label-cleanup`** (PR only, `rules` label present)
231233

232234
| Step | Name | Action |
233235
| ---- | ----------------------------- | ---------------------------------------------------------------------------------------- |
234236
| 1 | Remove label reminder comment | Finds and deletes the `label-reminder` PR comment (no-op if it doesn't exist) |
235237

236-
This job runs when the `codebuild` label is applied, immediately removing the reminder comment without waiting for the `codebuild` environment approval gate.
238+
This job runs when the `rules` label is applied, immediately removing the reminder comment without waiting for the `codebuild` environment approval gate.
237239

238240
**Job: `build`**
239241

@@ -351,6 +353,18 @@ Only runs for `pull_request` and `pull_request_target` events (not `merge_group`
351353

352354
Allowed types: `fix`, `feat`, `build`, `chore`, `ci`, `docs`, `style`, `refactor`, `perf`, `test`. Scopes are optional (`requireScope: false`).
353355

356+
**Job: `auto-label` ("Auto-label")**
357+
358+
Only runs for `pull_request_target` events. Uses [`actions/labeler`](https://github.com/actions/labeler) v6.0.1 to automatically apply and remove labels based on changed file paths. Label rules are defined in `.github/labeler.yml`:
359+
360+
| Label | Path Pattern | Description |
361+
| --------------- | ----------------------------------------------- | ------------------------------------------------ |
362+
| `rules` | `aidlc-rules/**` | Triggers CodeBuild evaluation pipeline |
363+
| `documentation` | `**/*.md` (excluding `aidlc-rules/**`) | Non-rules markdown file changes |
364+
| `github` | `.github/**` | Workflow, template, or config changes |
365+
366+
With `sync-labels: true`, labels are automatically removed when the matching files are no longer in the PR diff (e.g., after a rebase drops those changes). New label rules can be added by editing `.github/labeler.yml` — no workflow changes required.
367+
354368
**Job: `contributorStatement` ("Require Contributor Statement")**
355369

356370
Only runs for `pull_request` and `pull_request_target` events. Skipped for bot accounts (`dependabot[bot]`, `github-actions[bot]`, `github-actions`, `aidlc-workflows`). Verifies the PR body contains the contributor acknowledgment text from `.github/pull_request_template.md`:
@@ -361,6 +375,7 @@ Only runs for `pull_request` and `pull_request_target` events. Skipped for bot a
361375

362376
| Action | Version | SHA |
363377
| --------------------------------------- | ------- | ------------------------------------------ |
378+
| `actions/labeler` | v6.0.1 | `634933edcd8ababfe52f92936142cc22ac488b1b` |
364379
| `amannn/action-semantic-pull-request` | v6.1.1 | `48f256284bd46cdaab1048c3721360e808335d50` |
365380
| `actions/github-script` | v8.0.0 | `ed597411d8f924073f98dfc5c65a23a2325f34cd` |
366381

@@ -421,9 +436,10 @@ All variables have sensible defaults via `${{ vars.VAR || 'default' }}` syntax,
421436

422437
| Workflow | Job | Permissions | Rationale |
423438
| ----------------------- | ---------------------- | ------------------------------------------------------ | -------------------------------------------------------------- |
424-
| `codebuild.yml` | `label-reminder` | `pull-requests: write` | Post reminder comment when `codebuild` label is missing |
425-
| `codebuild.yml` | `label-cleanup` | `pull-requests: write` | Delete reminder comment when `codebuild` label is applied |
439+
| `codebuild.yml` | `label-reminder` | `pull-requests: write` | Post reminder comment when `rules` label is missing |
440+
| `codebuild.yml` | `label-cleanup` | `pull-requests: write` | Delete reminder comment when `rules` label is applied |
426441
| `codebuild.yml` | `build` | `actions: write`, `contents: write`, `id-token: write` | Cache management, release asset upload, OIDC token for AWS STS |
442+
| `pull-request-lint.yml` | `auto-label` | `contents: read`, `issues: write`, `pull-requests: write` | Apply/remove labels based on changed file paths; `issues: write` allows creating labels that don't yet exist |
427443
| `pull-request-lint.yml` | `get-pr-info` | `contents: read`, `pull-requests: read` | Read PR metadata and labels via API |
428444
| `pull-request-lint.yml` | `check-merge-status` | `pull-requests: read` | Read PR state for merge gate checks |
429445
| `pull-request-lint.yml` | `validate` | `pull-requests: read` | Read PR title for conventional commit validation |
@@ -441,7 +457,7 @@ Both `codebuild.yml` and `pull-request-lint.yml` follow a **deny-all-then-grant*
441457
| **AWS authentication** | OIDC-based role assumption via `id-token: write` — no static credentials stored |
442458
| **Least-privilege tokens** | `codebuild.yml` and `pull-request-lint.yml` explicitly deny all 16 permission scopes at workflow level, grant only required scopes at job level |
443459
| **Environment protection** | `codebuild` environment gates AWS credential access with potential reviewer/branch rules |
444-
| **Label-gated CI** | `codebuild.yml` requires the `codebuild` label on PRs and only triggers for `aidlc-rules/**` changes, preventing unnecessary builds and environment approval prompts |
460+
| **Label-gated CI** | `codebuild.yml` requires the `rules` label on PRs and only triggers for `aidlc-rules/**` changes, preventing unnecessary builds and environment approval prompts. The label is applied automatically by the `auto-label` job in `pull-request-lint.yml` |
445461
| **Concurrency control** | `codebuild.yml` and `pull-request-lint.yml` cancel in-progress runs for the same branch |
446462
| **Safe PR trigger** | `pull-request-lint.yml` uses `pull_request_target` but never checks out PR code — only inspects metadata (title, labels, body) |
447463
| **Injection-safe inputs** | Zero `${{ }}` expression interpolation in `run:` blocks — all dynamic values (`github.ref_name`, `github.repository`, `env.*`, event inputs) passed via step-level `env:` or auto-exported workflow `env:` variables |

0 commit comments

Comments
 (0)