igneum/packaging/README-ship.md
igneum-labs 3551069c51 Public testnet launch, the public side: dl/public downloads path, site download buttons, HiveOS package, faucet
Downloads: packaging/ota/publish-public.sh publishes the current installers, the HiveOS package and the two signed
manifests into dl/public/ with no token in any URL, writes the four /public/ aliases as vercel.json rewrites and an
unsigned index for the site; publish-manifest.sh --public and ship-app.mjs --public run it on every release (dry run
and self-test cover it). Nothing removed from the token folders.

Site: the miner and wallet buttons link the public aliases and show the version and size from the index, read at
build time (site/downloads.json is the offline snapshot); TESTNET_OPEN in build.mjs drops the "Public testnet: not yet
open" line on the go; the HiveOS Flight Sheet install line on the miner page; /faucet page.

HiveOS: igneum-hive-0.3.8.tar.gz from the 0.3.8 node (2b6d23ef, PC build job) and the zig-built Linux workers.

Faucet: site/api/faucet.mjs (10 IGN per address and per IP per day, Neon table faucet_grants, EIP-1559 transfer signed
by site/lib/eth.mjs with no dependencies: keccak, RLP, secp256k1 with RFC 6979), FAUCET_KEY and FAUCET_RPC from the
Vercel env only; 15 unit tests with a fake database and node, run in CI.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-05 15:59:31 +00:00

108 lines
8.5 KiB
Markdown

# Shipping an Igneum Miner version (packaging/README-ship.md)
One command cuts a version for both platforms. 4 October 2026: 0.3.1, 0.3.2 and 0.3.3 each took eight hand steps and
an hour; `tools/ship-app.mjs` is those steps in order, each one checked and resumable.
node tools/ship-app.mjs 0.3.4 --node vendor/igneum-node-v4 --notes "one line for the changelog"
Add `--dry-run` first: it reads everything, prints the plan and writes nothing.
## What it does
| Step | What happens | Skips itself when |
|---|---|---|
| preflight | this tree clean and on master, the fork worktree clean (`--node-commit <sha>` pins it), tools, binaries, secrets present, gh account, what is live | never (reads only) |
| bump | the six version files, written by one function and read back | the files already say the version |
| inputs | `packaging/windows/push-inputs.sh` with the fork's Windows exes (`IGNEUM_WIN_RELEASE`, `IGNEUM_NODE_SRC`) | the live `payload-inputs.json` carries these exact files from this fork commit |
| commit | `Igneum Miner <v>: <notes>`, push master (the push starts the Windows build) | committed and on origin/master |
| ci | the `windows.yml` run for that commit (dispatched when the push started none), polled every 30 s | a green run for the commit exists |
| fetch | `packaging/windows/fetch-ci-artifacts.sh <run>`: installer and payload zip into the downloads folder | the installer from that run is there |
| dmg | `packaging/mac/build-dmg.sh` under `tools/lock/with-lock.sh build` | the DMG is newer than the bump (`--rebuild` forces) |
| copy | the DMG into the downloads folder | same sha256 already there |
| manifest | `packaging/ota/publish-manifest.sh --no-deploy`: signed, signature verified locally | never (cheap) |
| deploy | the downloads folder, one Vercel deploy for the files and the manifest together | never |
| verify | HEAD and GET of the DMG, the installer and the zip (size and sha256 against the local copies); the live manifest through `igneum-ota-sign verify` | never |
| console | one `build` item on the console (version, sizes, hashes, run, commit), then `sync-dl` | never (upsert on `ship:<v>`) |
The six version files: `app/igneum-app/Cargo.toml`, `app/igneum-app/Cargo.lock`, `app/windows/version.h`,
`app/igneum-app/resources/igneum-app.rc`, `packaging/windows/Igneum-Miner.iss`, `packaging/mac/app/Info.plist`.
`node tools/ship-app.mjs --check` says whether they agree; `--self-test` runs the bump on a scratch copy.
## Flags
| Flag | Meaning |
|---|---|
| `--node <dir>` | the igneum-node worktree the node and miner were built from (required); binaries from its `target-integration/`, else `target/` |
| `--notes "..."` | the manifest's changelog line and the commit message |
| `--dry-run` | reads only, prints the plan (exit 1 when preflight would stop the real run) |
| `--from <step>` | resume at that step (preflight runs again first); the failure message prints this command |
| `--skip-windows`, `--skip-mac` | one platform only (the other entry is carried over when the live manifest is the same version) |
| `--node-commit <sha>` | the fork must be on this commit |
| `--win-release <dir>`, `--mac-release <dir>` | other binary folders |
| `--min-supported`, `--activation-height`, `--deadline-note`, `--channel` | passed to `publish-manifest.sh` |
| `--rebuild` | build the DMG again even when a fresh one exists |
| `--branch <name>` | accept another branch than master (a dry run from a worktree; the Windows build still runs on pushes to master) |
| `--public` | the manifest step also publishes the version into `dl/public/` (no token in any URL; its own signed manifest; the `/public/` aliases rewritten), the same deploy carries it, verify checks every public file and alias. The token folders are untouched |
## The public downloads path (5 October 2026, testnet launch)
`dl/public/` in the downloads folder holds only the current installers, the HiveOS package and the two signed manifests
(app and wallet) with URLs under `https://dl.igneum.network/dl/public/`, plus an unsigned index `igneum-downloads.json`
that the site build reads. Four stable aliases are rewrites in the downloads folder's `vercel.json`, written from what the
folder holds, so they follow every release by themselves:
| Alias | Rewrites to |
|---|---|
| `https://dl.igneum.network/public/igneum-miner-windows.exe` | `dl/public/Igneum-Miner-Setup-<v>.exe` |
| `https://dl.igneum.network/public/igneum-miner-mac.dmg` | `dl/public/Igneum-Miner-<v>.dmg` |
| `https://dl.igneum.network/public/igneum-miner-hive.tar.gz` | `dl/public/igneum-hive-<v>.tar.gz` |
| `https://dl.igneum.network/public/igneum-wallet-mac.dmg` | `dl/public/Igneum-Wallet-<v>.dmg` |
`packaging/ota/publish-public.sh --app | --wallet | --hive <tar.gz> [--deploy] [--verify] [--dry-run]` does the work;
`publish-manifest.sh --public` and `ship-app.mjs --public` call it, so every future release lands there too. The
HiveOS package comes from `packaging/hive/make-hive-package.sh` (Linux node and miner from a PC `build` job, the two GPU
workers from `infra/cross/build-workers-linux.sh`) and is published with `--hive`. The site (`site/build.mjs`) reads the
index at build time and stamps every download button with the version and size; `TESTNET_OPEN` there removes the
"Public testnet: not yet open" line on the go.
## When a step fails
The tool stops, prints why and the `--from` command to retry. Nothing is skipped silently. State that is not a secret
(commit, run id, bump time, the hashes) is in `~/.cache/igneum/ship/<version>.json`.
Secrets come from `~/.config/igneum` (dl-token, dlsite-dir, ota-signing-key, relay token and key, the Vercel login) and are
never printed; every output line is scrubbed. `gh auth switch --user igneum-labs` runs before every gh call and before the
push.
## What a cut needs before it starts
- The node fork built for both targets in `--node`: `target-integration/release/{igneumd,igneum-miner}` and
`target-integration/x86_64-pc-windows-gnu/release/{igneumd,igneum-miner}.exe` (`proto-cuda/windows-node/cross-build.sh`).
- The prebuilt workers (`proto-cuda/nvrtc/igneum-worker-cuda.exe`, `proto-opencl/igneum-worker-opencl.exe`) and the prover
(`proving/igneum-prove/target/release/igneum-prove-{host,export}`); missing ones are noted, not fatal.
- The Mac on mains, nothing else building (the DMG step waits for the build lock).
## The site project on Vercel (4 October 2026, checked by hand)
Two Vercel projects are called `igneum`, in two teams, and the link file under `site/.vercel` points at the wrong one:
| Team | Login (global config) | Project | Holds | Deploys |
|---|---|---|---|---|
| `igneum` | `igneum-labs` (`~/.config/igneum/vercel`) | `igneum` (`prj_HcNO2NLY4jkhikmLMugpJ8nLcWNW`, root directory `site`, build `node build.mjs`) | `igneum.network`, `igneum.com`; env `DATABASE_URL`, `LOG_INTAKE_KEY` | GitHub integration: every push to master is a production deploy, every branch push a preview (`igneum-git-<branch>-igneum.vercel.app`) |
| `[other-business]` | `[user]-4826` (the default `~/.vercel`) | `igneum` (`prj_y5lQg3C87fXAgoj3vug6iwWU3KwV`, same settings) | the 13 redirect domains (`igneum.app`, `.art`, `.co.uk`, `.email`, `.info`, `.io`, `.net`, `.online`, `.org`, `.pro`, `.shop`, `.store`, `.vip`, `.xyz`) | nothing live |
So `vercel env add` from `site/` fails with "Could not retrieve Project Settings" under the igneum login (the link file names
the [other-business] project, which that login cannot read), and would silently add the value to the wrong project under the default
login. The working commands, from `site/` in the shared checkout (the link step rewrites `site/.vercel/project.json`, which
is ignored by git):
cd site
npx --yes vercel@latest --global-config ~/.config/igneum/vercel link --scope igneum --project igneum --yes
npx --yes vercel@latest --global-config ~/.config/igneum/vercel env ls --scope igneum # names only
npx --yes vercel@latest --global-config ~/.config/igneum/vercel env add LOG_INTAKE_KEY_NEXT production --scope igneum
A production deploy by hand is `npx --yes vercel@latest --global-config ~/.config/igneum/vercel deploy --prod --yes --scope igneum`
from the repository root (the project's root directory is `site`), but the normal path is a push to master. The relay
(`igneum-relay`) and the downloads folder (`igneum-dl`) are the other two projects in the `igneum` team; both deploy by CLI
from their own folders (`relay/README.md`, `packaging/ota/README.md`). CLAUDE.md still says the site sits in the [other-business]
team and deploys with `--scope [other-business]` from `site/`: that was true on 3 October and is not now.