Document repo split, desktop API URL, and env template #17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 + ')', | |
| }); |