| name: PR Validation | |
| on: | |
| pull_request: | |
| types: [opened, edited, synchronize, labeled, unlabeled, milestoned, demilestoned] | |
| permissions: | |
| contents: read | |
| jobs: | |
| validate: | |
| name: Validate PR | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Validate Description | |
| uses: actions/github-script@v6 | |
| with: | |
| script: | | |
| const body = context.payload.pull_request.body; | |
| const requiredRegex = new RegExp('^RELEASE NOTES:\\s*([Nn][Oo][Nn][Ee]|[Nn]/[Aa]|\\n(\\*|-)\\s*.+)$', 'm'); | |
| if (!requiredRegex.test(body)) { | |
| core.setFailed(` | |
| The PR description must include a RELEASE NOTES section. | |
| It should be in one of the following formats: | |
| - "RELEASE NOTES: none" (case-insensitive) | |
| - "RELEASE NOTES: N/A" (case-insensitive) | |
| - A bulleted list under "RELEASE NOTES:", for example: | |
| RELEASE NOTES: | |
| * my_package: Fix bug causing crash... | |
| `); | |
| } | |
| - name: Validate Label | |
| uses: actions/github-script@v6 | |
| with: | |
| script: | | |
| const labels = context.payload.pull_request.labels.map(label => label.name); | |
| const requiredRegex = new RegExp('^Type:'); | |
| const hasRequiredLabel = labels.some(label => requiredRegex.test(label)); | |
| if (!hasRequiredLabel) { | |
| core.setFailed("This PR must have a label starting with 'Type:'."); | |
| } | |
| - name: Validate Milestone | |
| uses: actions/github-script@v6 | |
| with: | |
| script: | | |
| const milestone = context.payload.pull_request.milestone; | |
| if (!milestone) { | |
| core.setFailed("This PR must be associated with a milestone."); | |
| } else { | |
| const requiredRegex = new RegExp('Release$'); | |
| if (!requiredRegex.test(milestone.title)) { | |
| core.setFailed("The milestone for this PR must end with 'Release'."); | |
| } | |
| } |