58 lines
1.7 KiB
YAML
58 lines
1.7 KiB
YAML
name: PR Hygiene
|
|
|
|
on:
|
|
pull_request:
|
|
types:
|
|
- opened
|
|
- edited
|
|
- reopened
|
|
- synchronize
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
|
|
jobs:
|
|
validate:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Validate pull request body
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const body = context.payload.pull_request.body || "";
|
|
|
|
function getSection(title) {
|
|
const escaped = title.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
const regex = new RegExp(`##\\s+${escaped}\\s*\\n([\\s\\S]*?)(?=\\n##\\s+|$)`, "i");
|
|
const match = body.match(regex);
|
|
return match ? match[1].trim() : "";
|
|
}
|
|
|
|
const linkedIssue = getSection("Linked issue");
|
|
const howToTest = getSection("How to test");
|
|
|
|
const hasIssueReference =
|
|
/#\d+/.test(linkedIssue) ||
|
|
/https:\/\/github\.com\/[^/\s]+\/[^/\s]+\/issues\/\d+/i.test(linkedIssue);
|
|
|
|
const sanitizedHowToTest = howToTest
|
|
.replace(/Describe the verification steps\. If no runtime test applies, explain why\./i, "")
|
|
.trim();
|
|
|
|
const failures = [];
|
|
|
|
if (!hasIssueReference) {
|
|
failures.push("Add an issue reference under `## Linked issue` (for example `Closes #123`).");
|
|
}
|
|
|
|
if (!sanitizedHowToTest) {
|
|
failures.push("Fill in `## How to test` with verification steps or explain why no runtime test applies.");
|
|
}
|
|
|
|
if (failures.length > 0) {
|
|
core.setFailed(failures.join("\n"));
|
|
} else {
|
|
core.info("Pull request body passed hygiene checks.");
|
|
}
|