Skip to content

feat: add privacy-first Codex to OKF migration #1929

feat: add privacy-first Codex to OKF migration

feat: add privacy-first Codex to OKF migration #1929

Workflow file for this run

name: Auto-label Bounties and PRs
# Automatically assigns incremental "Bounty #N" labels to bounty issues.
# Also labels any pull request that references a bounty issue with the
# specific "Bounty #N" label from the issue.
on:
issues:
types: [opened, edited]
pull_request_target:
types: [opened, edited, synchronize, reopened]
concurrency:
group: bounty-labeling
cancel-in-progress: false
permissions:
pull-requests: write
issues: write
jobs:
label:
runs-on: ubuntu-latest
steps:
- name: Apply bounty labels
uses: actions/github-script@v7
with:
script: |
function extractSpecificBountyLabel(labels) {
for (const label of labels) {
const name = typeof label === "string" ? label : label.name;
if (/^bounty\s*#?\d+/i.test(name)) {
return name;
}
}
return null;
}
async function ensureLabelExists(name) {
try {
await github.rest.issues.getLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name,
});
} catch (error) {
if (error.status === 404) {
// A palette of visually distinct colors
const palette = [
"b60205", // red
"0e8a16", // green
"fbca04", // yellow
"1d76db", // blue
"5319e7", // purple
"d93f0b", // orange
"006b75", // teal
"c5def5", // light blue
"f9d0c4", // light pink
"d4c5f9", // light purple
];
// Extract bounty number to deterministically pick a color
const match = name.match(/\d+/);
const num = match ? parseInt(match[0], 10) : 0;
const color = palette[num % palette.length];
core.info(`Creating missing label "${name}" with color ${color}.`);
try {
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name,
color,
});
} catch (createError) {
// Another concurrent run may create the same label first.
if (createError.status !== 422) {
throw createError;
}
}
} else {
throw new Error(`Failed to check label "${name}": ${error.message}`);
}
}
}
async function findOpenPrsReferencingIssue(issueNumber) {
const prs = await github.paginate(github.rest.pulls.list, {
owner: context.repo.owner,
repo: context.repo.repo,
state: "open",
per_page: 100,
});
const refPattern = new RegExp(`#${issueNumber}(?!\\d)`);
return prs.filter((pr) => {
const text = `${pr.title}\n${pr.body ?? ""}`;
return refPattern.test(text);
});
}
async function applyLabelsToPr(prNumber, labels) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels,
});
}
async function labelIssue(issue) {
const isMaintainer = ["OWNER", "MEMBER", "COLLABORATOR"].includes(issue.author_association);
const hasBountyInTitle = /bounty/i.test(issue.title);
if (!isMaintainer || !hasBountyInTitle) {
return null;
}
const existingSpecificBounty = extractSpecificBountyLabel(issue.labels);
if (existingSpecificBounty) {
return existingSpecificBounty;
}
const allLabels = await github.paginate(github.rest.issues.listLabelsForRepo, {
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100
});
let maxBountyNum = 0;
for (const label of allLabels) {
const match = label.name.match(/^bounty\s*#?(\d+)/i);
if (match) {
const num = parseInt(match[1], 10);
if (num > maxBountyNum) {
maxBountyNum = num;
}
}
}
const nextBountyNumber = maxBountyNum + 1;
const newLabel = `Bounty #${nextBountyNumber}`;
await ensureLabelExists(newLabel);
core.info(`Issue #${issue.number}: applying label ${newLabel}`);
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: [newLabel],
});
return newLabel;
}
async function labelPr(pr) {
const text = `${pr.title}\n${pr.body ?? ""}`;
const issueNumbers = new Set(
[...text.matchAll(/#(\d+)/g)].map((m) => parseInt(m[1], 10))
);
if (issueNumbers.size === 0) {
core.info(`PR #${pr.number}: no issue references found.`);
return;
}
const bountyLabels = new Set();
for (const number of issueNumbers) {
try {
const { data: issue } = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: number,
});
// Skip if the referenced number is actually a PR, not an issue.
if (issue.pull_request) continue;
// Skip closed issues so only "active" bounties apply.
if (issue.state !== "open") continue;
const existingSpecificBounty = extractSpecificBountyLabel(issue.labels);
if (existingSpecificBounty) bountyLabels.add(existingSpecificBounty);
} catch (error) {
core.info(`PR #${pr.number}: could not read issue #${number}: ${error?.message ?? String(error)}`);
}
}
if (bountyLabels.size === 0) {
core.info(`PR #${pr.number}: no referenced issue(s) carry a bounty label.`);
return;
}
for (const name of bountyLabels) {
await ensureLabelExists(name);
}
core.info(`PR #${pr.number}: applying labels: ${[...bountyLabels].join(", ")}`);
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
labels: [...bountyLabels],
});
}
if (context.eventName === "issues") {
const bountyLabel = await labelIssue(context.payload.issue);
if (bountyLabel) {
const referencingPrs = await findOpenPrsReferencingIssue(context.payload.issue.number);
for (const pr of referencingPrs) {
core.info(`Issue #${context.payload.issue.number}: propagating ${bountyLabel} to PR #${pr.number}`);
await ensureLabelExists(bountyLabel);
await applyLabelsToPr(pr.number, [bountyLabel]);
}
}
} else {
await labelPr(context.payload.pull_request);
}