chore(ci): update PR template and add workflow to validate template is filled out

This commit is contained in:
Gabe Kangas
2026-02-02 18:47:10 -08:00
parent 3aee02f7a8
commit 551d2f668a
2 changed files with 97 additions and 5 deletions
+9 -5
View File
@@ -1,12 +1,16 @@
<!-- REQUIRED-CHECKLIST:START - Do not remove this section -->
## Double check ## Required checklist
- [ ] I included a screenshot, logs, or example payload to demonstrate the change. **Do not remove this section.** These checkboxes are required and validated.
- [ ] I have personally tested these changes and verified they work as intended.
- [ ] I understand the code I'm submitting and can explain how it works if asked.
- [ ] I included a screenshot, logs, example payload to demonstrate the change, or it really doesn't need it.
- [ ] This is a frontend change and it supports [translations](https://docs.owncast.dev/web-translations), or it's not a frontend change. - [ ] This is a frontend change and it supports [translations](https://docs.owncast.dev/web-translations), or it's not a frontend change.
- [ ] This change has actually been tested.
- [ ] The code has been run through the proper linters and/or formatters for the language. - [ ] The code has been run through the proper linters and/or formatters for the language.
- [ ] There is an issue discussing this change and it's assigned to me. - [ ] There is an issue discussing this change and it's assigned to me.
- [ ] I read the "Read first" details about filing this PR. <!-- REQUIRED-CHECKLIST:END -->
--- ---
@@ -47,5 +51,5 @@ Some things you might want to mention:
3. If you're fixing something, what was wrong? How should we stop from having this issue happen again? 3. If you're fixing something, what was wrong? How should we stop from having this issue happen again?
4. If this is a new feature or addition to functionality, why should it be added? What are the use cases? Who was asking for this functionality? 4. If this is a new feature or addition to functionality, why should it be added? What are the use cases? Who was asking for this functionality?
5. If this is a frontend change, does the text support [translation](https://owncast.notion.site/web-translations)? 5. If this is a frontend change, does the text support [translation](https://owncast.notion.site/web-translations)?
Thank you so much for contributing to Owncast! 🎉 Thank you so much for contributing to Owncast! 🎉
+88
View File
@@ -0,0 +1,88 @@
# This workflow validates that required PR checklist items are checked
# Triggers:
# - PR opened, edited, or reopened
# Skips:
# - Organization members
# - Dependabot PRs
# Note: Looks for content between REQUIRED-CHECKLIST:START and REQUIRED-CHECKLIST:END
# markers and fails if any unchecked boxes exist in that section.
name: PR Checklist
on:
pull_request:
types: [opened, edited, reopened]
permissions:
contents: read
jobs:
validate-checklist:
name: Validate PR checklist
runs-on: ubuntu-latest
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- name: Check organization membership
id: membership
uses: actions/github-script@v7
with:
script: |
try {
await github.rest.orgs.checkMembershipForUser({
org: 'owncast',
username: context.payload.pull_request.user.login
});
console.log('User is an organization member, skipping checklist validation');
return true;
} catch (error) {
if (error.status === 404 || error.status === 302) {
console.log('User is not an organization member, will validate checklist');
return false;
}
throw error;
}
- name: Validate required checkboxes
if: ${{ steps.membership.outputs.result == 'false' }}
uses: actions/github-script@v7
with:
script: |
const prBody = context.payload.pull_request.body || '';
// Extract content between the markers
const markerPattern = /<!-- REQUIRED-CHECKLIST:START[\s\S]*?-->([\s\S]*?)<!-- REQUIRED-CHECKLIST:END -->/;
const match = prBody.match(markerPattern);
if (!match) {
core.setFailed(
'## PR Checklist Validation Failed\n\n' +
'The required checklist section is missing from your PR description.\n\n' +
'Please do not remove the "Required checklist" section from the PR template.'
'If you need to restore this section, please edit your PR description to include it from [the original template](https://raw.githubusercontent.com/owncast/owncast/refs/heads/develop/.github/PULL_REQUEST_TEMPLATE.MD).'
);
return;
}
const checklistSection = match[1];
// Find all unchecked boxes in the section
const uncheckedPattern = /-\s*\[\s*\]\s*(.+)/g;
const uncheckedItems = [];
let uncheckedMatch;
while ((uncheckedMatch = uncheckedPattern.exec(checklistSection)) !== null) {
uncheckedItems.push(uncheckedMatch[1].trim());
}
if (uncheckedItems.length > 0) {
let message = '## PR Checklist Validation Failed\n\n';
message += 'The following required checklist items are not checked:\n\n';
for (const item of uncheckedItems) {
message += `- [ ] ${item}\n`;
}
message += '\nPlease check all items in the required checklist section to confirm you have completed them.';
core.setFailed(message);
} else {
console.log('All required checklist items are checked');
}