Skip to content

Document repo split, desktop API URL, and env template #17

Document repo split, desktop API URL, and env template

Document repo split, desktop API URL, and env template #17

Workflow file for this run

name: PR rules
on:
pull_request_target:
types:
- opened
- reopened
- ready_for_review
- edited
- synchronize
permissions:
contents: read
pull-requests: write
jobs:
validate-and-approve:
runs-on: ubuntu-latest
steps:
- name: Validate PR title and description
uses: actions/github-script@v7
with:
script: |
// Fetch current PR data to avoid stale payload on re-runs
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
});
const title = (pr.title || '').trim();
const body = (pr.body || '').trim();
const titlePattern = /^(feat|fix|docs|refactor|test|chore|ci|build|perf|revert)(\([^)]+\))?:\s.+$/i;
const requiredSections = [
'## Summary',
'## Related issue',
'## Changes',
'## Testing',
];
const errors = [];
if (!titlePattern.test(title)) {
errors.push(
'PR title must use conventional format: `type(scope): summary` (for example: `fix: handle room join errors`).'
);
}
for (const section of requiredSections) {
if (!body.includes(section)) {
errors.push(`Missing required section: ${section}`);
}
}
const sectionOrder = requiredSections.map((section) => body.indexOf(section));
if (sectionOrder.some((position) => position === -1)) {
// Missing section errors are already captured above.
} else {
for (let index = 1; index < sectionOrder.length; index += 1) {
if (sectionOrder[index] < sectionOrder[index - 1]) {
errors.push('PR sections must appear in the order: Summary, Related issue, Changes, Testing.');
break;
}
}
}
const relatedIssueSection = body.match(/## Related issue[\s\S]*?(Fixes|Closes|Resolves)\s+#(\d+)/i);
if (!relatedIssueSection) {
errors.push('The `## Related issue` section must include a linked issue line such as `Fixes #123`.');
}
if (errors.length > 0) {
core.setFailed(errors.join('\n'));
return;
}
const issueNumber = relatedIssueSection?.[2];
core.notice(`✅ PR validation passed! Title and body are correctly formatted. Linked issue #${issueNumber}.`);
// Add a success comment to the PR
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: '✅ **PR Validation Passed**\n\nYour PR title and description meet all requirements:\n- Title follows conventional format\n- All required sections are present\n- Issue is properly linked (#' + issueNumber + ')',
});