Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 57 additions & 36 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,39 +48,60 @@ jobs:
working-directory: cleanup

validate-pr-template:
if: github.event_name == 'pull_request'

runs-on: ubuntu-latest

steps:
- name: Validate PR template
uses: actions/github-script@v7
with:
script: |
const body = context.payload.pull_request.body || "";

// 1. Check both checkboxes
const checkbox1 = /\[x\].*?There is reasonable content/i.test(body);
const checkbox2 = /\[x\].*?I have read and accepted/i.test(body);

// 2. URL must be on the exact "The site content can be seen at ..." line
// https://regex101.com/r/N36fsT
const urlLineRegex = /^[ \t]*-[ \t]*The site content can be seen at[ \t]+(?:<)?(?:\[.*?\]\()?https?:\/\/[^\s>()]+(?:\))?(?:>)?/m;
const urlMatch = urlLineRegex.exec(body);
const urlValid = urlMatch !== null;

// 3. Explanation must follow the blockquote marker
const explanationMatch = />\s*The site content is(?:\s*|\s*\n)(.+)/i.exec(body);
const explanation = explanationMatch && explanationMatch[1].trim().length > 10;

if (!checkbox1 || !checkbox2 || !urlValid || !explanation) {
core.setFailed(
"❌ PR template is not properly filled:\n" +
`Checkbox1: ${checkbox1 ? '✅' : '❌'}\n` +
`Checkbox2: ${checkbox2 ? '✅' : '❌'}\n` +
`URL on correct line: ${urlValid ? '✅' : '❌'}\n` +
`Explanation: ${explanation ? '✅' : '❌'}`
);
} else {
console.log("✅ PR template format is valid.");
}
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest

steps:
- name: Validate PR template and comment
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const body = pr.body || "";

const checkbox1 = /\[x\].*?There is reasonable content/i.test(body);
const checkbox2 = /\[x\].*?I have read and accepted/i.test(body);
const urlLineRegex = /^[ \t]*-[ \t]*The site content can be seen at[ \t]+(?:<)?(?:\[.*?\]\()?https?:\/\/[^\s>()]+(?:\))?(?:>)?/m;
const urlValid = urlLineRegex.exec(body) !== null;
const explanationMatch = />\s*The site content is(?:\s*|\s*\n)(.+)/i.exec(body);
const explanation = explanationMatch && explanationMatch[1].trim().length > 10;

const failed = !checkbox1 || !checkbox2 || !urlValid || !explanation;

if (!failed) {
console.log("✅ PR template is valid.");
return;
}

const commentBody = `❌ **PR template is not properly filled:**\n\n- Checkbox1 (reasonable content): ${checkbox1 ? "✅" : "❌"}\n- Checkbox2 (read and accepted): ${checkbox2 ? "✅" : "❌"}\n- URL on correct line: ${urlValid ? "✅" : "❌"}\n- Explanation (> The site content is...): ${explanation ? "✅" : "❌"}\n\nPlease update your PR description accordingly.`;

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
});

const existingComment = comments.find(c =>
c.user.login === 'github-actions[bot]' &&
c.body.includes("**PR template is not properly filled:**")
);

if (existingComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: commentBody
});
console.log("🔁 Updated existing PR comment.");
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: commentBody
});
console.log("💬 Posted new PR comment.");
}

core.setFailed("PR template validation failed.");
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ As above with adding a subdomain to a GitHub Pages site, the final step is to ma
---

Thanks to **[Cloudflare](https://www.cloudflare.com)** for their awesome DNS service that makes this service possible. While JS.ORG is using their free plan - to a shameless extent - they helped us more than once with some flexible solutions and extended quotas. Many thanks!
// dummy test