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
171 changes: 71 additions & 100 deletions .github/workflows/design-done-label.yml
Original file line number Diff line number Diff line change
@@ -1,146 +1,117 @@
name: Add "Design Done" Label
name: Sync Checklist Labels

# Trigger whenever an issue body is edited so we can detect checklist changes.
# Trigger whenever an issue body is edited so checklist changes are reflected
# as issue labels.
on:
issues:
types: [edited]
types: [opened, edited, reopened]

jobs:
add-design-done-label:
# Only run for issues in this repository (not forks or other events).
sync-checklist-labels:
if: github.event.issue != null
runs-on: ubuntu-latest
permissions:
issues: write # Required to add/remove labels.
issues: write

steps:
- name: Check checklist item and apply label
- name: Sync checklist items to labels
uses: actions/github-script@v7
with:
script: |
// The exact checklist item text we watch for.
const CHECKLIST_ITEM =
'Design Document \u2014 A detailed design document has been created and reviewed, covering architecture, data flow, and edge cases.';
const LABEL_NAME = 'Design Done';

const body = context.payload.issue.body || '';

// A checked GFM checkbox looks like: "- [x] <text>" or "* [x] <text>"
// We escape the checklist item for use in a regular expression.
const escapedItem = CHECKLIST_ITEM.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const checkedPattern = /^[\s]*[-*]\s+\[x\]\s+.*\*{0,2}Design Document\*{0,2}.*$/im;

if (checkedPattern.test(body)) {
console.log('Checklist item is checked. Ensuring label exists...');

// Ensure the "Design Done" label exists in this repository.
// If it already exists this call will throw a 422; we catch and ignore that.
const issueNumber = context.payload.issue.number;

const checklistLabels = [
{
label: 'Design Done',
color: '0075ca',
description: 'Design document has been created and reviewed.',
pattern: /^[\s]*[-*]\s+\[x\]\s+.*\*{0,2}Design Document\*{0,2}.*$/im,
},
{
label: 'Mail Sent',
color: 'e4e669',
description: 'Design mail has been sent.',
pattern: /^[\s]*[-*]\s+\[x\]\s+.*Design Mail.*$/im,
},
{
label: 'Code Review Done',
color: '0e8a16',
description: "All code changes have been peer-reviewed and approved according to the project's review standards.",
pattern: /^[\s]*[-*]\s+\[x\]\s+.*\*{0,2}Code Review\*{0,2}.*$/im,
},
{
label: 'Testing Done',
color: '5319e7',
description: 'Adequate unit, integration, and/or end-to-end tests have been written and are passing.',
pattern: /^[\s]*[-*]\s+\[x\]\s+.*\*{0,2}Testing Complete\*{0,2}.*$/im,
},
{
label: 'Doc Review Done',
color: '1d76db',
description: 'User-facing and/or developer documentation has been updated to reflect the new feature and reviewed.',
pattern: /^[\s]*[-*]\s+\[x\]\s+.*\*{0,2}Documentation Review\*{0,2}.*$/im,
},
{
label: 'Feature Complete',
color: '0052cc',
description: 'The feature is fully implemented, all checklist items above are done, and it is ready for release.',
pattern: /^[\s]*[-*]\s+\[x\]\s+.*\*{0,2}Feature Complete\*{0,2}.*$/im,
},
];

async function ensureLabel({ label, color, description }) {
try {
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: LABEL_NAME,
color: '0075ca', // Blue — feel free to change.
description: 'Design document has been created and reviewed.',
name: label,
color,
description,
});
console.log(`Label "${LABEL_NAME}" created.`);
console.log(`Label "${label}" created.`);
} catch (err) {
if (err.status === 422) {
// Label already exists — that is fine.
console.log(`Label "${LABEL_NAME}" already exists.`);
console.log(`Label "${label}" already exists.`);
} else {
throw err;
}
}
}

// Add the label to the issue. GitHub ignores duplicates, so this is
// idempotent — applying it again will not cause an error.
async function addLabel(label) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
labels: [LABEL_NAME],
issue_number: issueNumber,
labels: [label],
});
console.log(`Label "${label}" added to issue #${issueNumber}.`);
}

console.log(`Label "${LABEL_NAME}" added to issue #${context.payload.issue.number}.`);
} else {
console.log('Checklist item is not checked. Removing label if present...');

// Remove the label from the issue if it exists.
// GitHub returns 404 if the label is not on the issue; we catch and ignore that.
async function removeLabel(label) {
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
name: LABEL_NAME,
issue_number: issueNumber,
name: label,
});
console.log(`Label "${LABEL_NAME}" removed from issue #${context.payload.issue.number}.`);
console.log(`Label "${label}" removed from issue #${issueNumber}.`);
} catch (err) {
if (err.status === 404) {
// Label was not on the issue — nothing to remove.
console.log(`Label "${LABEL_NAME}" was not present on issue #${context.payload.issue.number}.`);
console.log(`Label "${label}" was not present on issue #${issueNumber}.`);
} else {
throw err;
}
}
}
- name: Check "Design Mail" checklist item and apply "Mail Sent" label
uses: actions/github-script@v7
with:
script: |
const LABEL_NAME = 'Mail Sent';

const body = context.payload.issue.body || '';

// Matches a checked GFM checkbox line containing "Design Mail"
const checkedPattern = /^[\s]*[-*]\s+\[x\]\s+.*Design Mail.*$/im;

if (checkedPattern.test(body)) {
console.log('"Design Mail" checklist item is checked. Ensuring label exists...');

// Ensure the "Mail Sent" label exists in this repository.
try {
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: LABEL_NAME,
color: 'e4e669', // Yellow — feel free to change.
description: 'Design mail has been sent.',
});
console.log(`Label "${LABEL_NAME}" created.`);
} catch (err) {
if (err.status === 422) {
console.log(`Label "${LABEL_NAME}" already exists.`);
} else {
throw err;
}
}

await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
labels: [LABEL_NAME],
});

console.log(`Label "${LABEL_NAME}" added to issue #${context.payload.issue.number}.`);
} else {
console.log('"Design Mail" checklist item is not checked. Removing label if present...');

try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
name: LABEL_NAME,
});
console.log(`Label "${LABEL_NAME}" removed from issue #${context.payload.issue.number}.`);
} catch (err) {
if (err.status === 404) {
console.log(`Label "${LABEL_NAME}" was not present on issue #${context.payload.issue.number}.`);
} else {
throw err;
}
for (const config of checklistLabels) {
if (config.pattern.test(body)) {
await ensureLabel(config);
await addLabel(config.label);
} else {
await removeLabel(config.label);
}
}
Loading
Loading