Skip to content

Show project status dots when collapsed in the sidebar #2085

Show project status dots when collapsed in the sidebar

Show project status dots when collapsed in the sidebar #2085

Workflow file for this run

name: PR Vouch
on:
pull_request_target:
types: [opened, reopened, synchronize, ready_for_review, converted_to_draft]
issue_comment:
types: [created]
push:
branches:
- main
paths:
- .github/VOUCHED.td
- .github/workflows/pr-vouch.yml
permissions:
contents: read
issues: write
pull-requests: write
jobs:
collect-targets:
name: Collect PR targets
runs-on: ubuntu-24.04
outputs:
targets: ${{ steps.collect.outputs.targets }}
steps:
- id: collect
uses: actions/github-script@v8
with:
script: |
if (context.eventName === "pull_request_target") {
const pr = context.payload.pull_request;
core.setOutput("targets", JSON.stringify([{ number: pr.number, user: pr.user.login }]));
return;
}
if (context.eventName === "issue_comment") {
const issue = context.payload.issue;
const body = context.payload.comment?.body ?? "";
if (!issue?.pull_request || !body.includes("/recheck-vouch")) {
core.setOutput("targets", "[]");
return;
}
core.setOutput(
"targets",
JSON.stringify([{ number: issue.number, user: issue.user.login }]),
);
return;
}
const pulls = await github.paginate(github.rest.pulls.list, {
owner: context.repo.owner,
repo: context.repo.repo,
state: "open",
per_page: 100,
});
const targets = pulls.map((pull) => ({
number: pull.number,
user: pull.user.login,
}));
core.setOutput("targets", JSON.stringify(targets));
label:
name: Label PR ${{ matrix.target.number }}
needs: collect-targets
if: ${{ needs.collect-targets.outputs.targets != '[]' }}
runs-on: ubuntu-24.04
concurrency:
group: pr-vouch-${{ matrix.target.number }}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
target: ${{ fromJson(needs.collect-targets.outputs.targets) }}
steps:
- id: vouch
name: Check PR author trust
uses: mitchellh/vouch/action/check-user@v1
with:
user: ${{ matrix.target.user }}
allow-fail: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Sync PR labels
uses: actions/github-script@v8
env:
PR_NUMBER: ${{ matrix.target.number }}
VOUCH_STATUS: ${{ steps.vouch.outputs.status }}
with:
script: |
const issueNumber = Number(process.env.PR_NUMBER);
const status = process.env.VOUCH_STATUS;
const managedLabels = [
{
name: "vouch:trusted",
color: "1f883d",
description: "PR author is trusted by repo permissions or the VOUCHED list.",
},
{
name: "vouch:unvouched",
color: "fbca04",
description: "PR author is not yet trusted in the VOUCHED list.",
},
{
name: "vouch:denounced",
color: "d1242f",
description: "PR author is explicitly blocked by the VOUCHED list.",
},
];
const managedLabelNames = new Set(managedLabels.map((label) => label.name));
for (const label of managedLabels) {
try {
const { data: existing } = await github.rest.issues.getLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label.name,
});
if (
existing.color !== label.color ||
(existing.description ?? "") !== label.description
) {
await github.rest.issues.updateLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label.name,
color: label.color,
description: label.description,
});
}
} catch (error) {
if (error.status !== 404) {
throw error;
}
try {
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label.name,
color: label.color,
description: label.description,
});
} catch (createError) {
if (createError.status !== 422) {
throw createError;
}
}
}
}
const nextLabelName =
status === "denounced"
? "vouch:denounced"
: ["bot", "collaborator", "vouched"].includes(status)
? "vouch:trusted"
: "vouch:unvouched";
const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
per_page: 100,
});
for (const label of currentLabels) {
if (!managedLabelNames.has(label.name) || label.name === nextLabelName) {
continue;
}
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
name: label.name,
});
} catch (removeError) {
if (removeError.status !== 404) {
throw removeError;
}
}
}
if (!currentLabels.some((label) => label.name === nextLabelName)) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
labels: [nextLabelName],
});
}
core.info(`PR #${issueNumber}: ${status} -> ${nextLabelName}`);