Skip to content

release: version → 0.12.25 (release-commit convention) #1682

release: version → 0.12.25 (release-commit convention)

release: version → 0.12.25 (release-commit convention) #1682

# merge-card-comment — the friendly surface of the merge card. The GATE (merge-card.yml) produces
# the required status check; THIS posts the same card as ONE sticky PR comment (create-or-update by
# marker, never a thread of new comments) so a contributor sees "value ✅/❌ · diff ✅/❌ — here's
# what's left" inline, without digging into check logs. It matches the constitution's "one card,
# plain language" intent. It gates nothing — comment-only.
#
# pull_request_target (not pull_request) so it can comment on FORK PRs too; it checks out `main`
# (trusted gate code, never the PR's tree) and reads PR state via the API — no untrusted code runs.
name: merge-card-comment
on:
pull_request_target:
# `edited` keeps the sticky comment honest across the `Closes` → `Part of` re-link (#712)
types: [opened, edited, synchronize, reopened, labeled, unlabeled, ready_for_review]
pull_request_review:
types: [submitted, dismissed]
permissions:
pull-requests: write # upsert the one sticky card comment
issues: read # the acceptance row reads Closes-target issue bodies
concurrency:
group: merge-card-comment-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
comment:
if: ${{ !github.event.pull_request.draft }}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with: { ref: main } # trusted gate script, never the PR head
- uses: actions/setup-node@v4
with: { node-version: 22 }
- name: Render the card
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
PR_NUMBERS: ${{ github.event.pull_request.number }}
run: node scripts/merge-card-gate.mjs > card.md || true # exit 1 when not accepted; the card body is what we want
- uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const body = fs.readFileSync('card.md', 'utf8').trim();
if (!body.includes('<!-- merge-card -->')) { core.info('no card body — skipping'); return; }
const { owner, repo } = context.repo;
const issue_number = context.payload.pull_request.number;
const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number, per_page: 100 });
const mine = comments.find(c => (c.user?.type === 'Bot') && c.body.includes('<!-- merge-card -->'));
if (mine) await github.rest.issues.updateComment({ owner, repo, comment_id: mine.id, body });
else await github.rest.issues.createComment({ owner, repo, issue_number, body });