Countersign · Quickstart · Start · Why file claims · Markdown
No secret. The job's OIDC token is the credential (permissions: id-token: write). The claim is attributed to github:<owner>/<repo>.
From this repository, after checkout:
name: countersign
on:
push:
branches: [main]
permissions:
id-token: write
contents: read
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: File a Countersign claim
id: countersign
uses: ./actions/countersign
with:
subject: example.com
statement: https://example.com is live and shows "Example Domain"
checks: '[{"type":"http","url":"https://example.com/","status":200,"contains":"Example Domain"}]'
- name: Receipt
run: echo "receipt ${{ steps.countersign.outputs.receipt-url }}"That workflow is actions/countersign/fixtures/verify.yml. It is not installed under .github/workflows/ here, because a push would file a claim against the public ledger. Copy it into the repository you want to verify.
The action writes the receipt link and this badge line to the job summary, and fails the job when counts_as_verified is not true:
[](https://countersign.signalry.ai/s/example.com)
A post-deploy check can use a template instead of a raw checks array:
- uses: ./actions/countersign
with:
template: static_page
url: https://example.com/
contains: Release notes v2Local equivalent, against a server you started yourself:
INPUT_SERVER=http://127.0.0.1:8787 \
INPUT_TOKEN="$COUNTERSIGN_API_KEY" \
INPUT_SUBJECT=example.com \
INPUT_STATEMENT='https://example.com is live and shows "Example Domain"' \
INPUT_CHECKS='[{"type":"http","url":"https://example.com/","status":200,"contains":"Example Domain"}]' \
node actions/countersign/index.mjsFork pull requests do not get an id-token. Skip the step, or pass a csk_ key as token.
How to publish the action on the Marketplace later is in actions/countersign/README.md. Leave it in this repo until then.