frigate/.github/workflows/pr_template_check.yml
Nicolas Mowen 0cf9d7d5b1
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
Inverse mypy and more mypy fixes (#22645)
* organize

* Improve storage mypy

* Cleanup timeline mypy

* Cleanup recording mypy

* Improve review mypy

* Add review mypy

* Inverse mypy

* Fix ffmpeg presets

* fix template thing

* Cleanup camera
2026-03-25 19:30:59 -05:00

121 lines
4.4 KiB
YAML

name: PR template check
on:
pull_request_target:
types: [opened, edited]
permissions:
pull-requests: write
jobs:
check_template:
name: Validate PR description
runs-on: ubuntu-latest
steps:
- name: Check PR description against template
uses: actions/github-script@v7
with:
script: |
const maintainers = ['blakeblackshear', 'NickM-27', 'hawkeye217', 'dependabot[bot]'];
const author = context.payload.pull_request.user.login;
if (maintainers.includes(author)) {
console.log(`Skipping template check for maintainer: ${author}`);
return;
}
const body = context.payload.pull_request.body || '';
const errors = [];
// Check that key template sections exist
const requiredSections = [
'## Proposed change',
'## Type of change',
'## AI disclosure',
'## Checklist',
];
for (const section of requiredSections) {
if (!body.includes(section)) {
errors.push(`Missing section: **${section}**`);
}
}
// Check that "Proposed change" has content beyond the default HTML comment
const proposedChangeMatch = body.match(
/## Proposed change\s*(?:<!--[\s\S]*?-->\s*)?([\s\S]*?)(?=\n## )/
);
const proposedContent = proposedChangeMatch
? proposedChangeMatch[1].trim()
: '';
if (!proposedContent) {
errors.push(
'The **Proposed change** section is empty. Please describe what this PR does.'
);
}
// Check that at least one "Type of change" checkbox is checked
const typeSection = body.match(
/## Type of change\s*([\s\S]*?)(?=\n## )/
);
if (typeSection && !/- \[x\]/i.test(typeSection[1])) {
errors.push(
'No **Type of change** selected. Please check at least one option.'
);
}
// Check that at least one AI disclosure checkbox is checked
const aiSection = body.match(
/## AI disclosure\s*([\s\S]*?)(?=\n## )/
);
if (aiSection && !/- \[x\]/i.test(aiSection[1])) {
errors.push(
'No **AI disclosure** option selected. Please indicate whether AI tools were used.'
);
}
// Check that at least one checklist item is checked
const checklistSection = body.match(
/## Checklist\s*([\s\S]*?)$/
);
if (checklistSection && !/- \[x\]/i.test(checklistSection[1])) {
errors.push(
'No **Checklist** items checked. Please review and check the items that apply.'
);
}
if (errors.length === 0) {
console.log('PR description passes template validation.');
return;
}
const prNumber = context.payload.pull_request.number;
const message = [
'## PR template validation failed',
'',
'This PR was automatically closed because the description does not follow the [pull request template](https://github.com/blakeblackshear/frigate/blob/dev/.github/pull_request_template.md).',
'',
'**Issues found:**',
...errors.map((e) => `- ${e}`),
'',
'Please update your PR description to include all required sections from the template, then reopen this PR.',
'',
'> If you used an AI tool to generate this PR, please see our [contributing guidelines](https://github.com/blakeblackshear/frigate/blob/dev/CONTRIBUTING.md) for details.',
].join('\n');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: message,
});
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
state: 'closed',
});
core.setFailed('PR description does not follow the template.');