name: Approve Command
on:
issue_comment:
types: [created]
jobs:
handle-approve:
runs-on: ubuntu-latest
# Only run on issues (not PRs) and when comment is /approve
if: github.event.issue.pull_request == null && contains(github.event.comment.body, '/approve')
permissions:
issues: write
steps:
- name: Handle approve command
uses: actions/github-script@v7
with:
script: |
const comment = context.payload.comment.body.trim();
// Only process if comment is exactly /approve
if (comment !== '/approve') {
return;
}
const issue = context.payload.issue;
const labels = issue.labels.map(l => l.name);
// Define the promotion paths: [current_status, next_status]
const promotions = {
'status-01:created': 'status-02:awaiting-planning',
'status-04:plan-review': 'status-05:plan-ready',
'status-07:code-review': 'status-08:ready-pr'
};
let promoted = false;
let oldStatus = null;
let newStatus = null;
// Check which status the issue currently has and promote it
for (const [currentStatus, nextStatus] of Object.entries(promotions)) {
if (labels.includes(currentStatus)) {
// Remove old status
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
name: currentStatus
}).catch(() => {}); // Ignore errors if label doesn't exist
// Add new status
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: [nextStatus]
});
oldStatus = currentStatus;
newStatus = nextStatus;
promoted = true;
break;
}
}
// Post confirmation comment
if (promoted) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: `✅ Status promoted: \`${oldStatus}\` → \`${newStatus}\`\n\nThe bot can now pick up this issue for the next step.`
});
} else {
// No matching status found
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: `⚠️ Cannot promote issue. The issue must have one of these statuses:\n- \`status-01:created\`\n- \`status-04:plan-review\`\n- \`status-07:code-review\`\n\nCurrent labels: ${labels.filter(l => l.startsWith('status-')).join(', ') || 'none'}`
});
}