When a GitHub release is published, the action collects the artifacts attached to it, hashes each one locally on the runner, submits the hashes to stamp.gridcoin.club, and writes a “Blockchain Timestamps” table into the release body with a verification link per file. The file contents never leave your CI environment — only the 64-character hash does.
Gridcoin Stamp — GitHub Action
Ship a release on GitHub, and — without you lifting a finger — every asset gets a SHA-256 timestamped on the Gridcoin blockchain and a verification row appended to the release notes.
Overview
Why timestamp a release?
A GitHub release is a mutable object. Tags can be force-pushed, auto-generated source archives can drift byte-wise between downloads, release notes can be rewritten, and the whole release can be deleted by anyone with write access. None of that changes the fact that at some specific moment you intended a specific set of bytes to represent a specific version — but after the fact, proving that intent in a way other people can independently check is surprisingly hard.
Timestamping each release asset against a public blockchain pins a cryptographic fingerprint to an immutable ledger. Anyone — downstream packagers, compliance auditors, a distant forensic investigator — can later hash the file they have in hand and confirm that those exact bytes existed under your release's name at the time of publication. It's the same idea that notaries have been selling for centuries, minus the notary.
The interesting question is not whether to timestamp, but how to do it so that the proof survives every edge case that release tooling quietly walks into. That's what this action exists to answer.
Design notes
Byte-stable source archives
GitHub's auto-generated "Source code" downloads are regenerated on every click and their hashes have drifted silently in the past — in January 2023 a server-side git upgrade broke checksum pinning across Homebrew, Bazel and Go modules. The action sidesteps that by fetching each archive once, re-uploading it under a dedicated -stamped name, and stamping the uploaded copy. Uploaded assets are immutable CDN blobs, so the bytes you attested to are the bytes everyone downloads later.
Reproducible commit proof
Every run emits a tiny .stamp.txt manifest containing the repository, tag, commit SHA, and tree SHA. Anyone with a clone can regenerate it line-for-line and recompute the hash with sha256sum — no archive download, no trusted third party, no long-term dependency on GitHub being nice.
Refuses to attest to a mutated tag
Git tags can be force-pushed. The action reads the manifest from the previous run, compares the pinned commit against whatever the tag currently resolves to, and aborts with a clear error on mismatch — you never end up with a release whose stamped artifacts disagree about which commit they represent.
Verification stays local
To verify a stamped release, the recipient drops the file onto stamp.gridcoin.club — the SHA-256 is computed client-side in the browser and only the 64-character hash is ever sent. Nothing about the file contents leaves the verifier's machine.
Idempotent reruns
Re-running the workflow on the same release reuses existing -stamped assets rather than re-downloading or overwriting them, picks up from any partial failure (e.g. zip uploaded but tar.gz missing), and rewrites the release body only if the table would actually change.
Anchored on a chain that rewards real science
Gridcoin rewards participants in BOINC volunteer computing — protein folding, pulsar searches, climate modelling, cancer research. Timestamps live on a ledger that exists to support actual research, not to burn electricity on empty hashes.
Drop-in workflow
Add a single workflow file to your repository. It fires whenever you publish a release through the GitHub UI or via any release automation that reaches the release: published event — semantic-release, goreleaser, manual clicks, all work.
name: Stamp Releaseon:release:types: [published]jobs:stamp:runs-on: ubuntu-latestpermissions:contents: writesteps:- uses: gridcat/gridcoin-stamp-action@v1with:github-token: ${{ secrets.GITHUB_TOKEN }}
The contents: write permission is required because the action uploads assets back to the release and edits the release body. Everything else — source-archive re-upload, manifest generation, idempotent reruns — is on by default.
Wait for confirmation
By default the action submits the hashes and returns immediately — the blockchain typically confirms within 2–5 minutes, and the verification URLs will start resolving some time after the workflow completes. If you'd rather have the workflow block until every stamp is confirmed on-chain, flip wait-for-confirmation on:
- uses: gridcat/gridcoin-stamp-action@v1with:github-token: ${{ secrets.GITHUB_TOKEN }}wait-for-confirmation: truepoll-timeout: 600
Verifying a release later
The easy path: pull the …-stamped.zip or …-stamped.tar.gz asset from the release page and drop it onto stamp.gridcoin.club. The hash is computed in the browser, looked up against the blockchain, and rendered as a proof page — the file itself never leaves the verifier's machine.
The terminal path: compare the SHA-256 of any downloaded asset against the corresponding row in the release body, or regenerate the proof manifest from git state and confirm its hash matches the row for <tag>.stamp.txt. Both routes are covered step-by-step in the repository README.
Learn more
The full list of inputs, outputs, rerun semantics, tag-mutation recovery, and CircleCI + semantic-release integration notes lives in the GitHub repository. Issues, pull requests, and feedback are all welcome — this is a young project and the ecosystem it serves is small, so every piece of input materially shapes where it goes next.
If you build anything on top of it, or if the stamp table on one of your releases caught someone's attention, I'd love to hear about it.