docs: add team usage guide for scope and language conventions #102
Workflow file for this run
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
| name: PR Validation | |
| on: | |
| pull_request: | |
| types: [opened, edited, labeled, unlabeled, synchronize] | |
| jobs: | |
| check-issue-reference: | |
| name: Check Issue Reference | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Verify PR links an issue | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const body = context.payload.pull_request.body || ''; | |
| const issuePattern = /(?:closes|fixes|resolves)\s+#(\d+)/gi; | |
| const matches = [...body.matchAll(issuePattern)]; | |
| if (matches.length === 0) { | |
| core.setFailed( | |
| '❌ PR must reference an approved issue.\n' + | |
| 'Add "Closes #N", "Fixes #N", or "Resolves #N" to the PR body.\n' + | |
| 'See CONTRIBUTING.md for the full contribution workflow.' | |
| ); | |
| } else { | |
| const issueNumbers = matches.map(m => m[1]).join(', '); | |
| core.info(`✅ Found issue reference(s): #${issueNumbers}`); | |
| } | |
| check-issue-approved: | |
| name: Check Issue Has status:approved | |
| runs-on: ubuntu-latest | |
| needs: check-issue-reference | |
| steps: | |
| - name: Verify linked issue is approved | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const body = context.payload.pull_request.body || ''; | |
| const issuePattern = /(?:closes|fixes|resolves)\s+#(\d+)/gi; | |
| const matches = [...body.matchAll(issuePattern)]; | |
| if (matches.length === 0) { | |
| core.setFailed('❌ No issue reference found in PR body.'); | |
| return; | |
| } | |
| const failures = []; | |
| for (const match of matches) { | |
| const issueNumber = parseInt(match[1], 10); | |
| core.info(`Checking issue #${issueNumber} for status:approved label...`); | |
| let issue; | |
| try { | |
| const response = await github.rest.issues.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| }); | |
| issue = response.data; | |
| } catch (err) { | |
| failures.push(`Issue #${issueNumber}: could not be fetched (${err.message})`); | |
| continue; | |
| } | |
| const labels = issue.labels.map(l => l.name); | |
| core.info(`Issue #${issueNumber} labels: ${labels.join(', ') || '(none)'}`); | |
| if (!labels.includes('status:approved')) { | |
| failures.push( | |
| `Issue #${issueNumber} ("${issue.title}") does not have the \`status:approved\` label. ` + | |
| `A maintainer must approve the issue before a PR can be merged.` | |
| ); | |
| } else { | |
| core.info(`✅ Issue #${issueNumber} has status:approved`); | |
| } | |
| } | |
| if (failures.length > 0) { | |
| core.setFailed('❌ Linked issue(s) not approved:\n' + failures.join('\n')); | |
| } | |
| check-type-label: | |
| name: Check PR Has type:* Label | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Verify PR has a type label | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const prNumber = context.payload.pull_request.number; | |
| const { data: pullRequest } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: prNumber, | |
| }); | |
| const labels = pullRequest.labels.map(l => l.name); | |
| core.info(`PR #${prNumber} labels: ${labels.join(', ') || '(none)'}`); | |
| const typeLabels = labels.filter(l => l.startsWith('type:')); | |
| if (typeLabels.length === 0) { | |
| core.setFailed( | |
| '❌ PR must have exactly one type:* label.\n' + | |
| 'Valid types: type:bug, type:feature, type:docs, type:refactor, type:chore, type:breaking-change\n' + | |
| 'Add the label to the PR after opening it.' | |
| ); | |
| } else if (typeLabels.length > 1) { | |
| core.setFailed( | |
| `❌ PR has multiple type:* labels: ${typeLabels.join(', ')}.\n` + | |
| 'Please keep exactly one type label.' | |
| ); | |
| } else { | |
| core.info(`✅ PR has type label: ${typeLabels[0]}`); | |
| } |