Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
blank_issues_enabled: true
blank_issues_enabled: false
59 changes: 0 additions & 59 deletions .github/workflows/label-policy.yml

This file was deleted.

18 changes: 0 additions & 18 deletions .github/workflows/labeler.yml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: pr-priority-triage
name: pr-triage

on:
pull_request_target:
types: [opened, synchronize, reopened]
branches: [dev]

concurrency:
group: pr-priority-triage-${{ github.event.pull_request.number }}
group: pr-triage-${{ github.event.pull_request.number }}
cancel-in-progress: true

permissions:
Expand All @@ -15,10 +15,14 @@ permissions:
pull-requests: write

jobs:
pr-priority-triage:
pr-triage:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # actions/labeler@v6.1.0
with:
sync-labels: true

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # actions/checkout@v6
with:
persist-credentials: false
Expand All @@ -34,6 +38,9 @@ jobs:
const triage = await import(
pathToFileURL(path.join(process.env.GITHUB_WORKSPACE, ".github/scripts/pr-priority-triage.js")).href,
)
const policy = await import(
pathToFileURL(path.join(process.env.GITHUB_WORKSPACE, ".github/scripts/label-policy-check.js")).href,
)
const { buildPriorityReview, planPriorityLabels, TRIAGE_MARKER } = triage
const pull_number = Number(process.env.PR_NUMBER)
const owner = context.repo.owner
Expand Down Expand Up @@ -85,18 +92,34 @@ jobs:
per_page: 100,
})

if (reviews.some((review) => typeof review.body === "string" && review.body.includes(TRIAGE_MARKER))) {
if (!reviews.some((review) => typeof review.body === "string" && review.body.includes(TRIAGE_MARKER))) {
const review = buildPriorityReview(paths)
await github.rest.pulls.createReview({
owner,
repo,
pull_number,
event: "COMMENT",
body: review.body,
})
core.info(`Posted priority recommendation: ${review.priority}`)
} else {
core.info("Priority recommendation comment already exists; skipping.")
return
}

const review = buildPriorityReview(paths)
await github.rest.pulls.createReview({
const finalLabels = await github.paginate(github.rest.issues.listLabelsOnIssue, {
owner,
repo,
pull_number,
event: "COMMENT",
body: review.body,
issue_number: pull_number,
per_page: 100,
})
const labels = finalLabels.map((label) => label.name)
const result = policy.validateLabelPolicy({ itemType: "pull_request", labels })

if (!result.ok) {
const labelText = labels.length > 0 ? labels.join(", ") : "(none)"
const errorText = result.errors.map((error) => `- ${error.message}`).join("\n")
core.setFailed(`Label policy failed for pull_request #${pull_number}.\n\nLabels: ${labelText}\n\n${errorText}`)
return
}

core.info(`Posted priority recommendation: ${review.priority}`)
core.info(`Label policy passed for pull_request #${pull_number}: ${labels.join(", ")}`)
28 changes: 0 additions & 28 deletions packages/opencode/test/github/label-policy-workflow.test.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import { parseWorkflow, readWorkflow } from "./workflow-parser"

const repoRoot = path.join(import.meta.dir, "../../../..")
const labelerConfigPath = path.join(repoRoot, ".github", "labeler.yml")
const labelerWorkflowPath = path.join(repoRoot, ".github", "workflows", "labeler.yml")
const triageWorkflowPath = path.join(repoRoot, ".github", "workflows", "pr-priority-triage.yml")
const triageWorkflowPath = path.join(repoRoot, ".github", "workflows", "pr-triage.yml")

type LabelerRule = {
"changed-files"?: Array<{
Expand All @@ -35,7 +34,7 @@ function labelerLabelsForGlob(glob: string) {
.map(([label]) => label)
}

describe("pr routing workflows", () => {
describe("pr triage workflow", () => {
test("defines labeler routing for repo areas and workflow policy labels", () => {
const config = readWorkflow(labelerConfigPath)
expect(config).toContain("ci:")
Expand All @@ -61,32 +60,15 @@ describe("pr routing workflows", () => {
expect(validateLabelPolicy({ itemType: "pull_request", labels: [...labels, "P3"] }).ok).toBe(true)
})

test("pins labeler and triage workflow contracts", () => {
const labelerWorkflow = readWorkflow(labelerWorkflowPath)
const labelerParsed = parseWorkflow(labelerWorkflowPath)
const labelerSteps = labelerParsed.jobs?.labeler?.steps ?? []
const labelerStep = labelerSteps[0]

expect(labelerParsed.name).toBe("labeler")
expect(labelerParsed.on?.pull_request_target).toEqual({
types: ["opened", "synchronize", "reopened"],
branches: ["dev"],
})
expect(labelerParsed.permissions).toEqual({
contents: "read",
"pull-requests": "write",
})
expect(labelerStep?.uses).toBe("actions/labeler@f27b608878404679385c85cfa523b85ccb86e213")
expect(labelerStep?.with).toEqual({ "sync-labels": true })
expect(labelerWorkflow).not.toContain("persist-credentials: true")

test("pins pr-triage workflow contract: labeler, priority, and policy run serially", () => {
const triageWorkflow = readWorkflow(triageWorkflowPath)
const triageParsed = parseWorkflow(triageWorkflowPath)
const triageSteps = triageParsed.jobs?.["pr-priority-triage"]?.steps ?? []
const triageSteps = triageParsed.jobs?.["pr-triage"]?.steps ?? []
const labelerStep = triageSteps.find((step) => step.uses?.startsWith("actions/labeler@"))
const checkout = triageSteps.find((step) => step.uses?.startsWith("actions/checkout@"))
const script = triageSteps.find((step) => step.uses?.startsWith("actions/github-script@"))

expect(triageParsed.name).toBe("pr-priority-triage")
expect(triageParsed.name).toBe("pr-triage")
expect(triageParsed.on?.pull_request_target).toEqual({
types: ["opened", "synchronize", "reopened"],
branches: ["dev"],
Expand All @@ -96,14 +78,19 @@ describe("pr routing workflows", () => {
issues: "write",
"pull-requests": "write",
})
expect(triageParsed.concurrency?.group).toBe("pr-priority-triage-${{ github.event.pull_request.number }}")
expect(triageParsed.concurrency?.group).toBe("pr-triage-${{ github.event.pull_request.number }}")
expect(triageParsed.concurrency?.["cancel-in-progress"]).toBe(true)
expect(checkout?.uses).toBe("actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd")

const stepUses = triageSteps.map((step) => step.uses).filter((value): value is string => Boolean(value))
expect(stepUses[0]).toBe("actions/labeler@f27b608878404679385c85cfa523b85ccb86e213")
expect(stepUses[1]).toBe("actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd")
expect(stepUses[2]).toBe("actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3")

expect(labelerStep?.with).toEqual({ "sync-labels": true })
expect(checkout?.with).toEqual({
"persist-credentials": false,
ref: "${{ github.event.pull_request.base.sha }}",
})
expect(script?.uses).toBe("actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3")
expect(script?.env).toEqual({ PR_NUMBER: "${{ github.event.pull_request.number }}" })
expect(script?.run).toBeUndefined()
expect(triageWorkflow).toContain('event: "COMMENT"')
Expand All @@ -114,11 +101,13 @@ describe("pr routing workflows", () => {
expect(triageWorkflow).toContain("github.rest.issues.removeLabel")
expect(triageWorkflow).not.toContain("github.rest.issues.setLabels")
expect(triageWorkflow).toContain("planPriorityLabels")
expect(triageWorkflow).toContain("validateLabelPolicy")
expect(triageWorkflow).toContain("github.rest.pulls.listReviews")
expect(triageWorkflow).toContain("pathToFileURL")
expect(triageWorkflow).toContain("process.env.GITHUB_WORKSPACE")
expect(triageWorkflow).toContain("await import(")
expect(triageWorkflow).not.toContain('require("./.github/scripts/pr-priority-triage.js")')
expect(triageWorkflow).not.toContain("persist-credentials: true")
})
})

Expand Down