GitHub Actions PR comments — stop flooding, start updating
Every terraform workflow that comments plan output on PRs has the same problem: push 5 commits, get 5 duplicate comments. Add a matrix strategy across 8 workspaces and your PR is unreadable by lunch. The fix is idempotent comments — find-and-update instead of create-create-create.
The pattern
Embed an HTML comment as a marker in the comment body:
const marker = '<!-- tf-plan: workspace-name -->';
const body = `${marker}\n### Terraform Plan: workspace-name\n\`\`\`hcl\n${plan}\n\`\`\``;
Before creating a comment, search for the marker:
const { data: comments } = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});
const existing = comments.find(c => c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
comment_id: existing.id,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
} else {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
}
HTML comments are invisible in rendered markdown. Each workspace gets its own marker. First push creates the comment. Every subsequent push updates it in place.
Pair it with commit statuses
Comments alone don’t tell you if the plan is still running. Add commit status indicators:
# Pending (yellow dot)
gh api repos/$REPO/statuses/$SHA \
-f state=pending \
-f context="terraform-plan/workspace-name" \
-f description="Plan running..."
# Complete (green/red dot)
gh api repos/$REPO/statuses/$SHA \
-f state=success \
-f context="terraform-plan/workspace-name" \
-f description="Plan posted"
Reviewers see yellow dots while plans are running, green when they’re ready to read. No more guessing whether the comment is current or stale.
Requires statuses: write in your workflow permissions. Found that out the hard way — 403s on three workflows before I noticed.
The cleanup
We had 14 comment steps across 6 workflows all using createComment. Changed them all to find-and-update. Deleted 32 stale comments from a single PR.