ci: Improve error message in title checker #35
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 Title Checker | |
| on: | |
| pull_request_target: | |
| types: [opened, edited, reopened] | |
| jobs: | |
| check-title: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: write | |
| steps: | |
| - name: Validate PR Title and Apply Labels | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const title = context.payload.pull_request.title; | |
| const { owner, repo } = context.repo; | |
| const pr_number = context.payload.pull_request.number; | |
| const regex = /^([a-z-]+)(?:\(([^)]+)\))?(!?): ([A-Z].+)$/; | |
| const match = title.match(regex); | |
| if (!match) { | |
| core.setFailed("PR title does not follow any of the accepted formats:\n 'type(scope)!: Description'\n 'type(scope): Description'\n 'type!: Description'\n 'type: Description'\n See https://www.conventionalcommits.org/ for more details"); | |
| return; | |
| } | |
| const [_, type, scope, breaking, __] = match; | |
| const displayTitle = `${title} (#${pr_number})`; | |
| const maxLength = 72; | |
| if (displayTitle.length > maxLength) { | |
| core.setFailed( | |
| `PR title is too long by ${displayTitle.length-maxLength} characters.` | |
| ); | |
| return; | |
| } | |
| const repoLabels = await github.rest.issues.listLabelsForRepo({ | |
| owner, | |
| repo, | |
| per_page: 100, | |
| }); | |
| const labelNames = repoLabels.data.map(l => l.name); | |
| const labelsToAdd = []; | |
| const typeLabel = `cc: ${type}`; | |
| if (!labelNames.includes(typeLabel)) { | |
| core.setFailed(`Invalid type: "${type}". No label "${typeLabel}" found in repo.`); | |
| return; | |
| } | |
| labelsToAdd.push(typeLabel); | |
| if (scope) { | |
| const scopeLabel = `package: ${scope}`; | |
| if (!labelNames.includes(scopeLabel)) { | |
| core.setFailed(`Invalid scope: "${scope}". No label "${scopeLabel}" found in repo.`); | |
| return; | |
| } | |
| labelsToAdd.push(scopeLabel); | |
| } | |
| if (breaking === '!') { | |
| if (!labelNames.includes('breaking-change')) { | |
| core.setFailed('No "breaking-change" label found in repo.'); | |
| return; | |
| } | |
| labelsToAdd.push('breaking-change'); | |
| } | |
| const prLabels = await github.rest.issues.listLabelsOnIssue({ | |
| owner, | |
| repo, | |
| issue_number: pr_number, | |
| per_page: 100, | |
| }); | |
| const managedPrefixes = ['cc: ', 'package: ']; | |
| const labelsToRemove = prLabels.data | |
| .map(l => l.name) | |
| .filter(n => managedPrefixes.some(p => n.startsWith(p)) || n === 'breaking-change'); | |
| for (const label of labelsToRemove) { | |
| await github.rest.issues.removeLabel({ | |
| owner, | |
| repo, | |
| issue_number: pr_number, | |
| name: label | |
| }); | |
| } | |
| await github.rest.issues.addLabels({ | |
| owner, | |
| repo, | |
| issue_number: pr_number, | |
| labels: labelsToAdd | |
| }); | |
| console.log(`Successfully added labels: ${labelsToAdd.join(', ')}`); |