跳到主要内容

Deploy from GitHub Actions

Publish your site or dapp to DIG automatically — a new capsule of your existing store, exactly the git-push-to-deploy flow you'd expect from a managed host, but decentralized. Add one workflow file; the Action does the right thing for the event:

  • Pull request → a free preview. Your build is compiled and verified through the real chia:// read path and you get a shareable, content-addressed preview. No chain, no wallet, no spend.
  • Push to your default branch → a real deploy. The Action advances your store's on-chain root and publishes the new capsule, then posts the live URL + cost back on the commit.

The dedicated dig-network/deploy-action does the work: it installs the digstore CLI on the runner, runs digstore deploy, and reports the result as step outputs, a PR comment, a GitHub Deployment, and a commit status.

You create the store once; CI only updates it

Your store already exists (you ran digstore init once, which mints it and spends $DIG). The Action only advances that store — it never mints. Each real deploy is a new capsule and costs the uniform capsule price in $DIG + a small XCH fee, paid from your deploy wallet. PR previews are free.

What you need

  • An existing DIG store (created with digstore init).
  • The store bound to your repo in DIGHUb (the one-time keyless binding, below) — so CI needs no long-lived hub secret.
  • A dedicated deploy wallet funded with enough DIG for your expected deploys (it pays only on a real deploy; see Security).
  • A GitHub repo whose build produces a directory of static files (e.g. dist/).
Requires digstore ≥ v0.6.0

Keyless CI auth (--writer-key) and the free deploy --preview path require digstore ≥ v0.6.0 — which is the Action's default digstore-version. Keep digstore-version pinned to an explicit tag for reproducible CI.

Add the workflow

One workflow handles both modes — a free preview on every PR and a real deploy on push to your default branch. The Action picks the mode from the event; you don't configure it.

name: Deploy to DIG
on:
push:
branches: [main] # real deploy
pull_request: # free preview

permissions:
contents: read
id-token: write # KEYLESS auth — exchange the OIDC token (no hub secret)
pull-requests: write # comment the preview / live URL on the PR
deployments: write # the GitHub Deployment + commit status

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: "20" }
- run: npm ci && npm run build # produces ./dist

- name: Deploy to DIG
id: dig
uses: DIG-Network/deploy-action@v1 # pin to @v1 once released (a commit SHA until then)
with:
directory: dist
digstore-version: v0.6.0 # PIN for reproducible CI
# KEYLESS: no hub secret. The on-chain spend still needs a funding wallet:
writer-key: ${{ secrets.DIG_WRITER_KEY }} # advances the root (revocable, root-only)
passphrase: ${{ secrets.DIGSTORE_PASSPHRASE }} # funds the capsule price ($DIG) + XCH fee
mnemonic: ${{ secrets.DIG_MNEMONIC }}
# store-id comes from the OIDC binding (or dig.toml). Pass store-id: to override.

- run: echo "Deployed ${{ steps.dig.outputs.capsule }} -> ${{ steps.dig.outputs.hub-url }}"

That's it. Open a PR to get a free preview commented on it; merge to main to advance your store's on-chain root and publish the new capsule to DIGHUb.

  • PRs run digstore deploy --preview: a free, content-addressed build verified through the real chia:// read path. The preview address is the content-address output and is commented on the PR.
  • Pushes to the default branch run digstore deploy --if-changed: a push whose build is byte-identical to the live version is a no-op (no spend, nothing published), so it is safe to run on every push.
  • A push to a non-default branch previews (never a surprise spend). Set preview: true to force a preview on any event.

Keyless auth — one-time binding

Keyless auth removes the long-lived hub secret from your repo. CI presents the workflow's short-lived GitHub OIDC token; the hub verifies it (fail-closed against GitHub's JWKS) and, if your repo + ref is bound to your store, mints a short-lived store-scoped session for the push. Requires permissions: id-token: write (in the workflow above).

Register the binding once (owner-only) — no secret is generated, the binding itself is what authorizes the exchange:

  • In DIGHUb: Project → Settings → CI deploy → add a repo binding for owner/repo + the git ref (defaults to refs/heads/main).

If the repo isn't bound, the Action fails with a clear 403 pointing you here.

What it reports on a PR

With comment-on-pr at its default true, the Action:

  • Upserts a PR comment with the published capsule (or preview address), its URLs (dig:// + the DIGHUb URL), and the cost.
  • Creates a GitHub Deployment for the commit (marked transient for a preview).
  • Sets a commit status — a red X if the on-chain anchor or hub push failed or timed out, so a broken deploy can block merge.

Security

There are three distinct credentials. Two are keyless / spend-limited; only the funding wallet can spend, and that is needed solely on a real deploy (never for a preview):

CredentialWhat it can doHow it's provided
Keyless OIDC sessionAuthorize the DIGHUb head push for the bound storeMinted per-run from the GitHub OIDC token — no secret in the repo
Writer deploy-key (writer-key)Advance the store's on-chain root only — never change the owner, never melt; revocableRepo secret
Funding wallet (passphrase + mnemonic)Pay the capsule price ($DIG) + XCH fee for a real deployRepo secret
The funding wallet's seed can spend its DIG and XCH — use a dedicated wallet

The funding seed only signs the payment for the on-chain root update (the writer-key authorizes the change itself), but protect it anyway:

  • Use a dedicated deploy wallet, never your main wallet.
  • Fund it with only enough $DIG for your expected deploys (each real deploy = the uniform capsule price + a small fee).
  • Store the passphrase and mnemonic as GitHub encrypted secrets — never in dig.toml or any committed file.
  • PR previews are free and need none of these — no OIDC, no writer-key, no wallet.

The publisher deploy-key (deploy-key) is a separate §21 head-push credential with no spend authority. In keyless mode the OIDC session covers the push, so you usually don't need it; it remains available for self-hosted remotes or when not using keyless auth.

One-time setup

On the machine where you created the store:

digstore log --json          # copy the "store_id" field (or set it in dig.toml)
  1. Bind the repo to your store (keyless): in DIGHUb, Project → Settings → CI deploy → add a repo binding for owner/repo + ref. No secret is generated — the binding authorizes the OIDC exchange.
  2. Authorize a writer deploy-key for CI (DIGHUb Teams → add a "Deployer") and store it as a secret.
  3. Add the funding wallet as secrets.

Repository secrets (Settings → Secrets and variables → Actions):

SecretValue
DIG_WRITER_KEYThe 64-hex writer deploy-key that advances the store's root (revocable, root-only)
DIGSTORE_PASSPHRASEThe passphrase that unlocks the funding wallet's seed in CI
DIG_MNEMONICThe dedicated funding wallet's BIP-39 mnemonic

And commit a dig.toml to your repo root (so output-dir etc. don't have to be passed; store-id is resolved from the OIDC binding but may also be pinned here):

store-id   = "<your 64-hex store id>"
output-dir = "dist"
# build-command = "npm ci && npm run build" # optional

Action inputs

InputDefaultDescription
directorydistThe built-output directory to publish.
store-idOIDC binding / dig.tomlThe 64-hex store id to advance. Resolved from the keyless OIDC binding when available.
if-changedtrueSkip the deploy (and the spend) when the build is byte-identical to the live version.
previewfalseForce a free preview (--preview) even on a default-branch push. PRs preview automatically.
digstore-versionv0.6.0The digstore CLI version: a release tag, git ref/branch, or latest. Pin this. Needs ≥ v0.6.0.
keylesstrueKeyless CI auth: exchange the GitHub OIDC token (audience=dighub) for a store-scoped session — no hub secret. Needs id-token: write.
api-basehttps://hub.dig.net/v1The DIGHUb control-plane API base for the OIDC exchange.
writer-keyThe on-chain writer deploy-key (64-hex): advances the root only, revocable. (DIGSTORE_WRITER_KEY.)
passphraseThe funding wallet's DIGSTORE_PASSPHRASE — pays the on-chain fee on a real deploy. Use a dedicated wallet.
deploy-keyThe store's 64-hex §21 publisher deploy key (no spend authority). Usually unneeded with keyless.
mnemonicThe funding wallet's BIP-39 mnemonic, imported under passphrase.
saltSecret salt (64-hex) for a private store. Omit for public stores.
remotepublic DIGHUbThe remote to publish to (e.g. dig://<store-id> or a node URL).
messagethe commitCommit message for the new capsule.
build-commandOptional shell build command to run before deploying.
wait-timeout600Seconds to wait for on-chain confirmation (0 = don't block).
comment-on-prtrueOn a PR, upsert the comment and set the deployment + commit status.
github-token${{ github.token }}Token for the PR comment / deployment / commit status.
working-directory.Directory to run digstore from (where dig.toml lives).

All credentials should be passed from repo secrets, never inline.

Action outputs

OutputDescription
capsuleThe published capsule: storeId:rootHash.
rootThe new on-chain root hash.
store-idThe store id that was advanced.
dig-urlThe dig:// URL of the deployment (rootless = latest tip).
urnThe root-pinned URN permalink (urn:dig:chia:<store>:<root>).
hub-urlThe DIGHUb URL for the store (https://hub.dig.net/stores/<id>).
coin-idThe on-chain coin id of the anchored root.
content-addressOn a --preview build: the shareable root-pinned dig:// address. Empty on a real deploy.
previewtrue when this run produced a free preview (a PR), not a real on-chain deploy.
skippedtrue when --if-changed skipped a no-op deploy.
spenttrue when the deploy spent DIG (a real publish).
pushedtrue when the capsule was published to the hub.
Your *.on.dig.net address isn't a deploy output

A *.on.dig.net address is an optional, paid handle you register for a store — it isn't derivable from a deploy (and a store has none until you register one), so the Action surfaces the always-available dig-url (dig://), urn, and hub-url instead. The capsule is readable over the dig RPC by those the moment it confirms; if you've registered a handle, your site is also served at <your-name>.on.dig.net.

Using the CLI directly

The Action wraps digstore deploy, which is built for CI. You can run the same flow yourself (e.g. from another CI system):

digstore seed import --mnemonic "$DIG_MNEMONIC"            # DIGSTORE_PASSPHRASE set (funds the fee)
DIGSTORE_WRITER_KEY=<64-hex> digstore deploy --output-dir dist --json --if-changed # advance root + push
digstore deploy --preview --output-dir dist --json # a free preview — no chain, no spend

On a fresh checkout digstore deploy reconstructs the store locally from the deploy key + the current on-chain root, stages your output directory, advances the root (signed by the writer deploy-key), and pushes the new capsule — all non-interactively. See digstore deploy --help.

Versioning

Reference the Action as DIG-Network/deploy-action@v1 for the latest compatible v1.x release; pin to an exact tag (@v1.2.3) or a commit SHA for byte-for-byte reproducibility. Always pin digstore-version to a release tag (≥ v0.6.0) so the CLI doesn't move under you.

Pre-release

The Action is built and tested but not yet tagged @v1 — a human gates the first release. Until then, pin to a commit SHA.

Next: Command reference →