Skip to content

Commit 1dd618b

Browse files
authored
Merge pull request #250 from thand-io/pr-labels
Pr labels and PR template
2 parents 6966b69 + 0024625 commit 1dd618b

2 files changed

Lines changed: 244 additions & 0 deletions

File tree

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
## Summary
2+
3+
> Briefly describe what this PR does and why. Link to the relevant issue or context.
4+
5+
Closes #<!-- issue number -->
6+
7+
---
8+
9+
## Type of Change
10+
11+
<!-- Check all that apply -->
12+
13+
- [ ] `feat` – New feature (minor version bump)
14+
- [ ] `fix` – Bug fix (patch version bump)
15+
- [ ] `refactor` – Code refactoring, no functional change
16+
- [ ] `docs` – Documentation only
17+
- [ ] `test` – Adding or updating tests
18+
- [ ] `chore` – Build, CI, dependency updates
19+
- [ ] `major` / `BREAKING CHANGE` – Breaking change (major version bump)
20+
21+
---
22+
23+
## What Changed
24+
25+
> A concise list of the changes made. Focus on the **what** and **why**, not the how.
26+
27+
-
28+
-
29+
-
30+
31+
---
32+
33+
## Provider / Workflow / Role Changes
34+
35+
> Complete this section if you've added or modified providers, workflows, or roles. Delete if not applicable.
36+
37+
| Area | Change | Notes |
38+
|------|--------|-------|
39+
| Provider | | |
40+
| Workflow | | |
41+
| Role | | |
42+
43+
- [ ] Provider config files updated (`config/providers/`)
44+
- [ ] Role config files updated (`config/roles/`)
45+
- [ ] Workflow definitions updated (`config/workflows/`)
46+
- [ ] Example configs updated (`examples/`)
47+
48+
---
49+
50+
## Security Considerations
51+
52+
> This project handles privileged access. Describe any security implications of this change.
53+
54+
- [ ] No security impact
55+
- [ ] Reviewed for least-privilege impact
56+
- [ ] Access grant / revocation logic reviewed
57+
- [ ] Audit trail is preserved for any new access paths
58+
- [ ] No credentials, tokens, or secrets introduced in code or config
59+
60+
**Security notes** *(if applicable)*:
61+
62+
---
63+
64+
## Testing
65+
66+
> Describe how this was tested. Include commands if helpful.
67+
68+
- [ ] Unit tests pass (`go test ./...`)
69+
- [ ] Functional tests pass
70+
- [ ] Integration tests pass
71+
- [ ] Manually tested locally — describe scenario below
72+
73+
**Manual test scenario** *(if applicable)*:
74+
75+
```
76+
# Describe the steps taken to verify the change works end-to-end
77+
```
78+
79+
---
80+
81+
## Breaking Changes
82+
83+
> If this is a breaking change, describe the impact and any migration steps required.
84+
85+
- [ ] This PR does **not** introduce breaking changes
86+
- [ ] This PR **does** introduce breaking changes (describe below)
87+
88+
**Migration steps** *(if applicable)*:
89+
90+
---
91+
92+
## Documentation
93+
94+
- [ ] No documentation changes needed
95+
- [ ] In-code comments updated
96+
- [ ] `docs/` updated
97+
- [ ] `README.md` updated
98+
- [ ] Config examples updated
99+
100+
---
101+
102+
## Checklist
103+
104+
- [ ] My branch is up to date with `main`
105+
- [ ] Commit messages follow the [conventional commit format](RELEASE.md) (`feat:`, `fix:`, `major:`, etc.)
106+
- [ ] No debug code, hardcoded values, or temporary workarounds left in
107+
- [ ] All new code has appropriate test coverage
108+
- [ ] I have reviewed my own diff before requesting review

.github/workflows/pr-label.yml

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
name: PR Type Label
2+
3+
# Runs on every PR event that could change the title, commits, or labels.
4+
# 1. If a recognised type label is already present → pass (nothing to do).
5+
# 2. Otherwise scan the PR title and all commit messages for a conventional
6+
# commit prefix and auto-apply the matching label.
7+
# 3. If neither is found → fail with a helpful message so the contributor knows
8+
# what to do.
9+
10+
on:
11+
pull_request:
12+
types: [opened, edited, synchronize, reopened, labeled, unlabeled]
13+
branches: [main]
14+
15+
permissions:
16+
contents: read
17+
pull-requests: write # needed to add/create labels
18+
19+
jobs:
20+
check-and-label:
21+
name: Check PR type label
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
- name: Ensure type labels exist in the repo
26+
env:
27+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28+
REPO: ${{ github.repository }}
29+
run: |
30+
# Create labels if they don't already exist.
31+
# `gh label create` exits non-zero when the label already exists,
32+
# so we suppress that with --force (update colour/description if changed).
33+
gh label create "feat" --color "0075ca" --description "New feature (minor version bump)" --force --repo "$REPO"
34+
gh label create "fix" --color "e4e669" --description "Bug fix (patch version bump)" --force --repo "$REPO"
35+
gh label create "refactor" --color "cfd3d7" --description "Code refactoring, no functional change" --force --repo "$REPO"
36+
gh label create "docs" --color "0052cc" --description "Documentation only" --force --repo "$REPO"
37+
gh label create "test" --color "bfd4f2" --description "Adding or updating tests" --force --repo "$REPO"
38+
gh label create "chore" --color "d4c5f9" --description "Build, CI, dependency updates" --force --repo "$REPO"
39+
gh label create "major" --color "d93f0b" --description "Breaking change (major version bump)" --force --repo "$REPO"
40+
41+
- name: Check labels and apply from title / commits if missing
42+
id: label-check
43+
env:
44+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45+
REPO: ${{ github.repository }}
46+
PR_NUMBER: ${{ github.event.pull_request.number }}
47+
PR_TITLE: ${{ github.event.pull_request.title }}
48+
run: |
49+
set -euo pipefail
50+
51+
# ── 1. Collect existing labels on this PR ──────────────────────────
52+
CURRENT_LABELS=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json labels \
53+
--jq '[.labels[].name] | join(" ")')
54+
echo "Current labels: $CURRENT_LABELS"
55+
56+
# ── 2. Check whether any type label is already set ─────────────────
57+
TYPE_LABELS="feat fix refactor docs test chore major"
58+
FOUND_LABEL=""
59+
for lbl in $TYPE_LABELS; do
60+
if echo " $CURRENT_LABELS " | grep -qw "$lbl"; then
61+
FOUND_LABEL="$lbl"
62+
break
63+
fi
64+
done
65+
66+
if [ -n "$FOUND_LABEL" ]; then
67+
echo "✅ Type label already set: $FOUND_LABEL"
68+
echo "label=$FOUND_LABEL" >> "$GITHUB_OUTPUT"
69+
exit 0
70+
fi
71+
72+
# ── 3. No label yet – scan PR title first ──────────────────────────
73+
# Matches: feat: feat!: feat(scope): feat(scope)!:
74+
# Also matches standalone prefixes: major / BREAKING CHANGE
75+
detect_type() {
76+
local text="$1"
77+
local lower
78+
lower=$(echo "$text" | tr '[:upper:]' '[:lower:]')
79+
80+
if echo "$lower" | grep -qE '^major[^a-z]|breaking.?change'; then
81+
echo "major"; return
82+
elif echo "$lower" | grep -qE '^feat(\([^)]*\))?!?:'; then
83+
echo "feat"; return
84+
elif echo "$lower" | grep -qE '^fix(\([^)]*\))?!?:'; then
85+
echo "fix"; return
86+
elif echo "$lower" | grep -qE '^refactor(\([^)]*\))?!?:'; then
87+
echo "refactor"; return
88+
elif echo "$lower" | grep -qE '^docs?(\([^)]*\))?!?:'; then
89+
echo "docs"; return
90+
elif echo "$lower" | grep -qE '^tests?(\([^)]*\))?!?:'; then
91+
echo "test"; return
92+
elif echo "$lower" | grep -qE '^(chore|build|ci)(\([^)]*\))?!?:'; then
93+
echo "chore"; return
94+
fi
95+
echo ""
96+
}
97+
98+
DETECTED=$(detect_type "$PR_TITLE")
99+
100+
# ── 4. If not in title, scan commit messages ───────────────────────
101+
if [ -z "$DETECTED" ]; then
102+
echo "No prefix in PR title – scanning commit messages..."
103+
COMMITS=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json commits \
104+
--jq '[.commits[].messageHeadline] | join("\n")')
105+
106+
while IFS= read -r msg; do
107+
TYPE=$(detect_type "$msg")
108+
if [ -n "$TYPE" ]; then
109+
DETECTED="$TYPE"
110+
echo " Found prefix '$DETECTED' in commit: $msg"
111+
break
112+
fi
113+
done <<< "$COMMITS"
114+
fi
115+
116+
# ── 5. Apply label if detected; otherwise fail ─────────────────────
117+
if [ -n "$DETECTED" ]; then
118+
echo "Applying label: $DETECTED"
119+
gh pr edit "$PR_NUMBER" --repo "$REPO" --add-label "$DETECTED"
120+
echo "label=$DETECTED" >> "$GITHUB_OUTPUT"
121+
echo "✅ Label '$DETECTED' applied automatically."
122+
else
123+
echo ""
124+
echo "❌ No type label found and no conventional commit prefix detected."
125+
echo ""
126+
echo "Please either:"
127+
echo " • Add one of these labels to the PR: $TYPE_LABELS"
128+
echo " • OR prefix your PR title or a commit message with one of:"
129+
echo " feat: fix: refactor: docs: test: chore: major:"
130+
echo ""
131+
echo "Examples:"
132+
echo " feat: add OAuth2 provider support"
133+
echo " fix(sessions): correct token expiry calculation"
134+
echo " major: BREAKING CHANGE: redesign workflow DSL"
135+
exit 1
136+
fi

0 commit comments

Comments
 (0)