Skip to content

chore(repo): rework github pipelines #9

chore(repo): rework github pipelines

chore(repo): rework github pipelines #9

Workflow file for this run

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).`);