Motivation
There are countless situations where you want to automatically post comments to PRs in CI/CD pipelines. It’s convenient when bots notify you via comments about test results, coverage reports, lint warnings, and more.
However, if you implement this without careful consideration, identical comments will multiply every time CI runs. On the other hand, writing logic to search for existing comments, retrieve their IDs, update if found, or create new ones if not—that’s tedious.
So I created a gh extension that manages comments by uniquely identifying them with “anchor strings.”
Overview
gh-xz is a GitHub CLI (gh) extension that manages PR and Issue comments using anchor strings.
An anchor string is an HTML comment in the format <!-- anchor_string --> appended to the end of a comment. This string identifies the comment—if a comment with the same anchor already exists, it gets updated; otherwise, a new comment is created.
Installation
gh extension install https://github.com/hakadoriya/gh-xz
This makes the gh xz command available.
Usage
Post or Update a Comment
# Specify text directly
gh xz put-anchored-comment owner/repo 123 "my-anchor" "Test results: All passed"
# Read from a file
gh xz put-anchored-comment owner/repo 123 "my-anchor" @./report.md
# Read from stdin
cat ./report.md | gh xz put-anchored-comment owner/repo 123 "my-anchor" @-
On the first run, a new comment is created. On subsequent runs, the comment with the same anchor is updated.
Retrieve a Comment
gh xz get-anchored-comment owner/repo 123 "my-anchor"
This retrieves the body of the comment with the specified anchor.
Using with GitHub Actions
You can easily set this up in GitHub Actions using hakadoriya-actions/setup-gh-xz.
name: post-comment
on:
pull_request:
jobs:
comment:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: hakadoriya-actions/setup-gh-xz@v0.0.1
- name: Post coverage report
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh xz put-anchored-comment \
${{ github.repository }} \
${{ github.event.number }} \
"coverage-report" \
"Coverage: 87.5%"
Comments won’t multiply every time CI runs—they’ll always be updated with the latest results.
How It Works
Internally, it uses gh api to call the GitHub API and manipulate comments.
- Retrieve the list of comments for the target PR/Issue
- Search for a comment containing the anchor string
- If not found, POST to create a new comment; if found, PATCH to update it
The anchor string is automatically wrapped in <!-- -->, so users only need to specify a simple string.
The only dependency is the gh command, and it operates as a single Bash script.