chore(repo): rework github pipelines #9
Workflow file for this run
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 Validator | |
| on: | |
| pull_request: | |
| types: [opened, edited, reopened, synchronize] | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| issues: write | |
| jobs: | |
| validate-pr: | |
| name: validate-pr | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Validate pull request | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const pr = context.payload.pull_request; | |
| const title = pr.title || ""; | |
| const body = pr.body || ""; | |
| const headRef = pr.head.ref || ""; | |
| const baseRef = pr.base.ref || ""; | |
| const prNumber = pr.number; | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const failures = []; | |
| const titleRegex = /^(feat|fix|docs|chore|refactor|test|style|perf)\((app|backend|ml-worker|repo|shared)\):\s+.{10,}$/i; | |
| const branchRegex = /^(codex\/[a-z0-9-]+|(feat|fix|docs|chore|refactor|test|style|perf)\/(app|backend|ml-worker|repo|shared)\/[a-z0-9-]+)$/; | |
| if (!titleRegex.test(title)) { | |
| failures.push("Use a title like `fix(app): handle empty room names`."); | |
| } | |
| if (baseRef !== "main") { | |
| failures.push(`Target branch must be \`main\`, not \`${baseRef}\`.`); | |
| } | |
| if (!branchRegex.test(headRef)) { | |
| failures.push("Use a branch like `codex/short-description` or `fix/app/short-description`."); | |
| } | |
| const bodyHasSummary = /##\s*(summary|what changed)/i.test(body); | |
| const bodyHasTesting = /##\s*(verification|how to test|testing)/i.test(body); | |
| if (!body.trim() || !bodyHasSummary || !bodyHasTesting) { | |
| failures.push("PR body must include summary and verification sections."); | |
| } | |
| async function addLabel(name) { | |
| try { | |
| await github.rest.issues.addLabels({ | |
| owner, | |
| repo, | |
| issue_number: prNumber, | |
| labels: [name], | |
| }); | |
| } catch (error) { | |
| core.warning(`Could not add label "${name}": ${error.message}`); | |
| } | |
| } | |
| async function removeLabel(name) { | |
| try { | |
| await github.rest.issues.removeLabel({ | |
| owner, | |
| repo, | |
| issue_number: prNumber, | |
| name, | |
| }); | |
| } catch (error) { | |
| if (error.status !== 404) { | |
| core.warning(`Could not remove label "${name}": ${error.message}`); | |
| } | |
| } | |
| } | |
| if (failures.length === 0) { | |
| await addLabel("ready-for-review"); | |
| await removeLabel("invalid-pr"); | |
| console.log("PR validation passed."); | |
| return; | |
| } | |
| await addLabel("invalid-pr"); | |
| await removeLabel("ready-for-review"); | |
| const message = [ | |
| "## PR Validation Failed", | |
| "", | |
| "Please update this pull request before merge:", | |
| "", | |
| ...failures.map((failure) => `- ${failure}`), | |
| ].join("\n"); | |
| await github.rest.issues.createComment({ | |
| owner, | |
| repo, | |
| issue_number: prNumber, | |
| body: message, | |
| }); | |
| core.setFailed(`PR validation failed with ${failures.length} issue(s).`); |