Skip to content

Add dot build + dot deploy with two signer modes and playground publish#19

Merged
UtkarshBhardwaj007 merged 1 commit intomainfrom
ch/deploy-and-build
Apr 17, 2026
Merged

Add dot build + dot deploy with two signer modes and playground publish#19
UtkarshBhardwaj007 merged 1 commit intomainfrom
ch/deploy-and-build

Conversation

@UtkarshBhardwaj007
Copy link
Copy Markdown
Member

@UtkarshBhardwaj007 UtkarshBhardwaj007 commented Apr 17, 2026

Summary

  • New dot build command — auto-detects pnpm/yarn/bun/npm from the lockfile and runs the build script (or falls back to vite/next/tsc when no script is defined).
  • Rewritten dot deploy command — interactive 4-prompt TUI (signer / buildDir / domain / publish) with two signer modes, or fully headless when all flags are passed.
  • Process-guard safety net (signal handlers, hard-exit timer, 4 GB RSS watchdog), telemetry forced off, Bun stdin warm-up, retry-friendly domain availability preflight.
  • 122 tests across 15 files. Ships with a complete rundown of non-obvious invariants + a dedicated changeset (minor bump).

How to try

dot build
dot deploy

# It would ask for signer - choose dev if you want to avoid signing 3 times for bulletin upload
# It would require 1 signing for publish to playground - sign in mobile app.

How it works at a glance

Mode Storage signer DotNS signer Playground publish signer Phone taps
--signer dev pool mnemonic pool mnemonic user's phone 0 (1 with --playground)
--signer phone pool mnemonic user's phone user's phone 3 (4 with --playground)

The playground publish is always signed by the user so the registry records env::caller() as the app owner — this is what drives the Playground "my apps" view.

Commands for reviewers to test

Setup (once)

# Clone, install deps, build the binary locally
pnpm install
pnpm cli:install       # installs the binary at ~/.polkadot/bin/dot

# Prerequisite — `dot init` installs ipfs CLI + sets up the mapped account
dot init

dot build

# From a project root (the working directory is the project by default)
dot build

# Explicit directory
dot build --dir /path/to/project

# --help
dot build --help

Expected: detects the package manager from the lockfile, runs <pm> run build, streams output to stdout, exits non-zero on failure.

dot deploy — interactive (TUI)

# From a project dir that has a build output (e.g. vite's dist/)
dot deploy

Walk through: pick a signer (Dev by default), accept dist as build dir, enter a domain, choose whether to publish to Playground. The TUI shows a summary card with exactly how many phone approvals will be requested. Press Enter to proceed.

Partial flags (each supplied flag skips its corresponding prompt):

dot deploy --signer dev                        # skip signer prompt
dot deploy --domain my-app                     # skip domain prompt
dot deploy --buildDir dist                     # skip buildDir prompt
dot deploy --playground                        # skip publish prompt (sets publish=yes)
dot deploy --signer dev --domain my-app        # mix & match

dot deploy — fully headless (all four prompts bypassed)

# Dev mode — fastest, zero phone taps unless --playground
dot deploy --signer dev --domain my-app --buildDir dist --playground=false

# Phone mode — DotNS signed with your phone session
dot deploy --signer phone --domain my-app --buildDir dist --playground=false

# With playground publish (adds 1 phone tap for the registry.publish call)
dot deploy --signer dev --domain my-app --buildDir dist --playground
dot deploy --signer phone --domain my-app --buildDir dist --playground

Re-deploy / update

# Deploy a domain once (e.g. my-app), then deploy it a second time.
# The availability check should now say:
#   "my-app.dot is available — Already owned by you — will update the existing deployment."
dot deploy --domain my-app --signer phone --buildDir dist --playground
dot deploy --domain my-app --signer phone --buildDir dist --playground   # second run = update

Reserved domain (should block)

# Names like "polkadot" trip the PopOracle Reserved classification
dot deploy --domain polkadot --signer dev --buildDir dist --playground=false
# expected: availability check aborts with "polkadot.dot is reserved — ..."

Dev signer with an explicit SURI

dot deploy --suri //Alice --signer dev --domain test-alice --buildDir dist --playground=false

Environment flag (mainnet guard)

dot deploy --env testnet                       # default, works
dot deploy --env mainnet                       # should cleanly error — not yet supported

Cancellation behaviour

  • Inside the interactive TUI: press Esc at the summary card to cancel.
  • Anywhere in the flow: Ctrl+C. The process-guard runs cleanup (destroys signer adapter + connection) and exits within 3 s. Running ps aux | grep dot afterward should show no lingering dot process.

Memory diagnostics

DOT_MEMORY_TRACE=1 dot deploy 2>mem.log
# tail mem.log — per-sample RSS / heap / external stats

If RSS ever exceeds 4 GB the watchdog aborts with a clear error rather than letting the OS swap. A typical healthy deploy sits at 1–1.5 GB peak.

dot deploy --help — flag reference

dot deploy --help
Flag Purpose
--signer <dev|phone> Signer mode. Skips the signer prompt when present.
--domain <name> DotNS label (with or without .dot). Skips the domain prompt.
--buildDir <path> Directory holding build artifacts (default dist). Skips the buildDir prompt.
--playground Publish to the playground registry. Skips the publish prompt (presence ⇒ yes).
--suri <suri> Dev secret URI (e.g. //Alice) — useful for CI.
--env <testnet|mainnet> Target environment. Only testnet is supported today.
--dir <path> Project directory. Defaults to cwd.

Passing all four of --signer, --domain, --buildDir, --playground runs non-interactively.

Test plan

  • dot build in a Vite project — produces dist/, streams output
  • dot build --dir ... with an absolute path
  • dot deploy interactive — full TUI walkthrough in dev mode without playground (0 phone taps)
  • dot deploy --playground interactive — dev mode, 1 phone tap for registry.publish
  • dot deploy --signer phone --playground — 4 phone taps, correct labels on phone ("Reserve domain", "Finalize domain", "Link content", "Publish to Playground registry")
  • Re-deploy the same domain → availability shows "Already owned by you — will update the existing deployment."
  • Try a reserved name (e.g. polkadot) → availability aborts with a clear reason
  • Ctrl+C during deploy → clean exit, no zombie process (verify with ps aux)
  • dot deploy --env mainnet → errors cleanly ("not yet supported")
  • DOT_MEMORY_TRACE=1 dot deploy 2>mem.log → log shows bounded growth
  • Deployed site loads in Polkadot Desktop (fetch ojasvi-aloo.dot or whatever you deployed)
  • Deployed app appears in the Playground registry's "my apps" view (when --playground used)

Non-obvious invariants (documented in CLAUDE.md)

  • bulletin-deploy pinned to 0.6.9-rc.6. The latest npm tag points at 0.6.8 which has a WS heartbeat bug. Do NOT revert.
  • jsMerkle: true is deliberately NOT set — bulletin-deploy's pure-JS merkleizer produces CARs with DAG-PB structural blocks missing (verified empirically; Polkadot Desktop would serve 404). We rely on the Kubo binary path; dot init installs ipfs.
  • Process-guard has only the absolute 4 GB cap — the earlier growth-rate detector was removed because it false-positived on legit one-time metadata-loading spikes.
  • DeployLogParser emits events ONLY for phase banners and [N/M] chunk progress. Everything else returns null.
  • src/utils/deploy/* + src/utils/build/* are React/Ink-free so RevX can consume them from a WebContainer.

Introduces `dot build` and a fully-rewritten `dot deploy` plus the supporting
infrastructure (config module, process-guard, signer-mode matrix, signing
proxy, availability preflight, CAR-upload wrapper, playground registry
publisher, Ink TUI).

Key behaviours
--------------
* `dot build` auto-detects the package manager (pnpm/yarn/bun/npm from the
  lockfile) and runs the `build` script, falling back to vite/next/tsc when
  no script is defined.
* `dot deploy` prompts for signer (dev/phone), build dir, domain, and
  publish-to-playground, or runs fully headless when all four flags are
  passed. After inputs resolve, the TUI announces exactly how many phone
  approvals will be needed and what each is for.
* Dev mode uploads + DotNS use bulletin-deploy's default pool mnemonic
  (0 phone taps for the heavy work). Phone mode signs DotNS with the user's
  session signer (3 taps). Playground publish is always signed by the user
  so `registry.publish`'s `env::caller()` records them as the app owner.
* Domain availability is checked before build: `classifyName` catches
  Reserved names; `checkOwnership(label, ss58ToH160(user))` correctly
  identifies "owned by you → update" vs "owned by someone else → taken".

Defense in depth
----------------
* SIGINT/SIGTERM/SIGHUP + unhandledRejection handlers run cleanup and
  force-exit within 3 s.
* `unref`'d hard-exit timer fires if a stray WebSocket keeps the event
  loop alive after the main flow returns.
* 4 GB RSS watchdog aborts on runaway growth. `DOT_MEMORY_TRACE=1` streams
  per-sample memory stats.
* `BULLETIN_DEPLOY_TELEMETRY=0` forced at CLI entry (Sentry off by default).
* Bun compiled-binary stdin warm-up listener (required for Ink `useInput`).

Non-obvious choices
-------------------
* `bulletin-deploy` pinned to `0.6.9-rc.6`; the `latest` dist-tag still
  points at 0.6.8 which has a WS heartbeat bug. Don't revert to `latest`.
* `jsMerkle: true` intentionally NOT passed to `bulletin-deploy` — the
  pure-JS merkleizer produces CARs missing their DAG-PB structural blocks
  (verified against a real deployed CAR). Kubo binary path is used instead;
  `dot init` installs `ipfs`.
* Playground metadata upload uses a dedicated Bulletin client with a 300 s
  WS heartbeat, not the shared `getConnection()` (which uses polkadot-api's
  40 s default and tears down mid-tx).
* `DeployLogParser` deliberately emits events ONLY for phase banners and
  `[N/M]` chunk progress — catch-all `info` events were a measurable
  contributor to 20+ GB heap pressure during long deploys.

Ships with 122 tests across 15 files covering the orchestrator event flow,
build detection, availability, playground publish, signing proxy, progress
parser, and the summary view. All gated by `tsc --noEmit` + `biome format`.
@github-actions
Copy link
Copy Markdown
Contributor

Dev build ready — try this branch:

curl -fsSL https://raw.githubusercontent.com/paritytech/playground-cli/main/install.sh | VERSION=dev/ch/deploy-and-build bash

@socket-security
Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedbulletin-deploy@​0.6.7 ⏵ 0.6.9-rc.677 +1100100 +196 +1100

View full report

@UtkarshBhardwaj007 UtkarshBhardwaj007 merged commit 75ba759 into main Apr 17, 2026
5 checks passed
@UtkarshBhardwaj007 UtkarshBhardwaj007 deleted the ch/deploy-and-build branch April 17, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant