Skip to content

Bump to bulletin-deploy@0.15.0; per-env DotNS TLD (.paseo on paseo-next-v2) - #498

Merged
illegalcall merged 5 commits into
mainfrom
feat/bulletin-deploy-0.15-paseo-tld
Aug 20, 2026
Merged

illegalcall merged 5 commits into
mainfrom
feat/bulletin-deploy-0.15-paseo-tld

Conversation

@illegalcall

@illegalcall illegalcall commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

What / why

The paseo-next-v2 testnet was wiped and DotNS was redeployed at new canonical addresses, with the TLD now per-network (.paseo on paseo-next-v2, previewnet stays .dot). Our pinned deploy library carried the dead addresses and every domain-side code path hardcoded .dot.

  • Swap @parity/polkadot-app-deploy@0.13.1 for bulletin-deploy@0.15.0 (exact pin). The npm package was renamed at 0.14; 0.15 carries the post-wipe contract addresses and the per-env tld catalog field (upstream #1240/#1244).
  • Add ChainConfig.tld + getEnvTld() (src/config.ts) as the single TLD source; the config.test.ts divergence guard pins it to upstream's environments.json (tld ?? "dot" fallback), same as the endpoint guards.
  • normalizeDomain(domain, tld) accepts a bare label or the env TLD and rejects a wrong-TLD name with the same actionable message as upstream parseDomainName; all callers (deploy, decentralize, availability, mod lookup, registry publish, moddedFrom lineage) thread the env TLD. A .paseo name yields <label>.paseo.li.
  • PLAYGROUND_PRODUCT_ID = "playground.dot" is unchanged and now commented as TLD-independent by convention (product ids stay <label>.dot on every network).
  • UI copy, prompt help, and unit/e2e fixtures swept off hardcoded .dot.

Bump audit: 0.13.1 -> bulletin-deploy@0.15.0

The bump was validated on 0.15.0-rc.2; the pin moved to 0.15.0 stable the day upstream cut it, verified code-identical to the validated rc (git tag diff: version bump + an unshipped e2e script fix only; published dist byte-identical after normalizing tsup chunk hashes and the baked version string).

Item Finding
deploy() signature Unchanged: (content, domainName, options)
DeployOptions we pass (jsMerkle, signer, signerAddress, storageSigner, storageSignerAddress, mnemonic, rpc, attributes, env) All present; changes are additive only (transferTo, contracts, bulletinEndpoints/assetHubEndpoints, publish, dumpCar, onPhoneSignaturePlan, confirmPhoneReady, ...)
Console log strings vs progress.ts parser Banner titles (Preflight / Storage / DotNS / DEPLOYMENT COMPLETE!) and [N/M] chunk lines unchanged (verified against 0.15 source, clearing the 0.13.1 live-verify caveat). #1240 moved the Domain: echo to after the Preflight connect (TLD chain-resolved first) - prose the parser drops; a new parser test pins the ordering. No regex changes needed
storageSigner routing Precedence unchanged: storageSigner > signer > mnemonic > pool (exported resolveStorageRoute); storage never phone-signs
host-papp resolution No split tree: bulletin-deploy's subtree pins @parity/product-sdk-terminal@^0.5.1 (resolves 0.5.4) whose host-papp range dedupes onto our single @novasamatech/host-papp@0.8.11 (>= 0.8.6 floor). Only product-sdk-terminal is split (0.5.4 lib / 0.7.1 root). Patched statement-store@0.8.11 / sdk-statement@0.6.0 pins resolve unchanged; install is clean
environments.json / divergence guard paseo-next-v2 endpoints/network/gateway unchanged upstream; new tld: "paseo" field (guard extended to cover it); DotNS contract addresses changed (owned upstream, resolved by env id - out of guard scope by design). summit remains dropped
Exports loadEnvironments / resolveEndpoints (now carrying tld) still exported; parseDomainName(input, tld) exported; DEFAULT_TLD / KNOWN_TLDS are NOT exported from the package root, so the CLI keeps a guarded local copy
postinstall Still ships patch-package || true (bundling the same sdk-statement@0.6.0 patch we already carry); build-script denial renamed to bulletin-deploy: false
dotns-cli 0.15 dropped the @parity/dotns-cli subprocess path entirely; the old warning-suppression shim in src/index.ts is now a dormant no-op (our own playground dotns passthrough keeps the dep)

Notes

  • pnpm quirk hit while moving rc.2 -> stable: the min-age gate honors minimumReleaseAgeExclude at resolution time, but the lockfile-verification pass did not honor it for the prerelease entry (stable verifies fine). Remedy documented in CLAUDE.md: one-off pnpm install --config.minimumReleaseAge=0 to rewrite the lockfile, then a plain pnpm install to confirm.

Verified: pnpm format:check, pnpm lint:license, pnpm typecheck, pnpm test (1012 passed) - re-run on the stable pin.

… TLD per-env

- @parity/polkadot-app-deploy@0.13.1 -> bulletin-deploy@0.15.0-rc.2 (npm
  package rename at 0.14; carries the post-wipe paseo-next-v2 DotNS
  addresses and the per-network TLD catalog)
- Add ChainConfig.tld + getEnvTld(); paseo-next-v2 names now end in .paseo
- normalizeDomain is TLD-aware and rejects wrong-TLD input with the same
  actionable message as upstream parseDomainName
- Sweep deploy/decentralize/mod copy, prompts, and tests off hardcoded .dot;
  PLAYGROUND_PRODUCT_ID stays playground.dot (TLD-independent by convention)
Comment thread src/utils/deploy/playground.ts Fixed
@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/feat/bulletin-deploy-0.15-paseo-tld bash

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

E2E Test Pass · ❌ FAIL

Tag: e2e-ci-pr · Branch: feat/bulletin-deploy-0.15-paseo-tld · Commit: c32c080 · Run logs

Cell Result Time
pr-login-session ❌ FAIL 4m18s
pr-install ✅ PASS 0m53s
pr-deploy-cdm ✅ PASS 3m17s
pr-deploy-frontend ❌ FAIL 2m39s
pr-preflight ❌ FAIL 2m40s
pr-deploy-foundry ✅ PASS 0m45s
pr-mod ❌ FAIL 2m29s
${{ matrix.cell }} ⏭️ SKIP 0m00s
${{ matrix.cell }} ⏭️ SKIP 0m00s
❌ Failed tests (1)
  • e2e/cli/session.test.ts › session management &gt; corrupted session file does not produce a valid signer
    expected +0 not to be +0 // Object.is equality

Sentry traces: view spans for this run

Upstream cut 0.15.0 today; verified code-identical to the validated
rc.2 (tag diff is the version bump plus an unshipped e2e script fix;
published dist matches after normalizing chunk hashes and the baked
version string). Updates the pin, lockfile, min-age exclude, changeset,
and CLAUDE.md note.
@illegalcall illegalcall changed the title Bump to bulletin-deploy@0.15.0-rc.2; per-env DotNS TLD (.paseo on paseo-next-v2) Bump to bulletin-deploy@0.15.0; per-env DotNS TLD (.paseo on paseo-next-v2) Aug 12, 2026

@UtkarshBhardwaj007 UtkarshBhardwaj007 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. It is missing the sweep in a bunch of places - see comments. I am approving for you to address the comments and then be unblocked in merging.

Also all e2e tests are failing. I had a quick look - seems like we need a new funder account. Should be simple to fix. please make sure the e2e tests are all green before merging.

* Fixed `.dot` domain names for deploy tests. SIGNER owns all of these after
* DotNS TLD of the env the E2E run targets (per-env since the paseo-next-v2
* DotNS redeploy — "paseo" there, "dot" on previewnet). Tests build
* `<label>.${E2E_TLD}` registry keys / banner expectations from this so they

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sweep missed the fixture bootstrap side. tools/register-e2e-fixtures.ts still calls normalizeDomain() with one arg in five places (69, 76, 78, 83, 166), which now crashes with a TypeError at startup. tsc doesn't catch it because tools/ isn't in the tsconfig include. Separately, TEST_TEMPLATE_DOMAIN is still dot-cli-mod-fixture.dot in e2e.yml (4 places), tools/e2e-local.sh, and docs/e2e-running-tests.md, plus DEFAULT_TEMPLATE_DOMAIN in the tool itself. On paseo that means ensureTemplateRegistered throws the wrong-TLD error during bootstrap and mod looks up dot-cli-mod-fixture.dot.paseo, so the mod cell stays red even after the funder is topped up. Re-registering fixtures with this exact tool is step one of the post-wipe recovery, so I think this belongs in this PR: bare label for DEFAULT_TEMPLATE_DOMAIN, thread getEnvTld() through the tool, and bump the workflow/docs values to .paseo.

const view = buildSummaryView({
mode: inputs.mode,
domain: inputs.domain.replace(/\.dot$/, "") + ".dot",
domain: normalizeDomain(inputs.domain, getEnvTld()).fullDomain,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can throw now, and it runs during render. A --domain passed as a flag never goes through the validate-domain stage (pickNextStage only prompts when domain is null, and validate-domain is only reachable from the prompt's onSubmit), so playground deploy --domain my-app.dot in interactive mode gets all the way to the confirm screen and then dies with a React stack trace instead of the wrong-TLD message. The old replace-and-append version couldn't throw here. Easiest fix is probably normalizing flag-provided domains in deploy/index.ts before the screen mounts, same as runHeadless already does.

writeDotJson(targetDir, meta.name ?? domain.replace(/\.dot$/, ""), meta, domain);
writeDotJson(
targetDir,
meta.name ?? domain.replace(new RegExp(`\\.${getEnvTld()}$`), ""),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related spot the sweep missed: defaultRepoName in src/utils/git/repoName.ts:23 still strips only .dot, so modding cool-app.paseo creates cool-app-paseo- instead of cool-app-. repoName.test.ts is still all .dot cases too, which is why nothing failed.

* actionable message bulletin-deploy's `parseDomainName` produces. Callers
* resolve `tld` once via `getEnvTld(env)`.
*/
export function normalizeDomain(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more caller that didn't get the TLD treatment: the deploy-all duplicate guard in src/commands/deploy-all/manifest.ts:88 still strips only .dot, so "app" and "app.paseo" in one manifest now slip past the duplicate check and race on the same DotNS name, which is exactly what that check exists to prevent.

Comment thread src/commands/mod/index.ts Outdated
// publish wrote — per-env since the DotNS TLD split (`.paseo` on
// paseo-next-v2). Accept a bare label or a fully-qualified name.
const tld = getEnvTld();
domain = rawDomain.endsWith(`.${tld}`) ? rawDomain : `${rawDomain}.${tld}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mod foo.dot on paseo becomes a lookup for foo.dot.paseo and reports a plain "not found in registry". An old .dot name is the most likely wrong input after the switch, and deploy/decentralize both reject it with the "this environment uses .paseo names" message. Running the input through normalizeDomain here (and catching) would make mod match the rest.

Comment thread .changeset/tld-aware-bulletin-deploy.md Outdated
"playground-cli": minor
---

Support per-network DotNS TLDs (`.paseo` on paseo-next-v2) and move the deploy library to `bulletin-deploy@0.15.0` (the renamed `@parity/polkadot-app-deploy`), which carries the post-wipe DotNS contract addresses. Deploys, decentralize, mod lookups, and all UI copy now use the environment's TLD; a name typed with the wrong TLD (e.g. `my-app.dot` on paseo-next-v2) is rejected with an actionable message. The `playground.dot` product id is unchanged by convention.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README still documents .dot names for deploy/decentralize/mod (lines 78, 83, 147, 155, 181) and refers to polkadot-app-deploy throughout, including the "currently pinned 0.8.3" line at 313, which was already stale but is now the wrong package name entirely. The CLI help says my-app.paseo now, so the README contradicts the binary it documents.

Comment thread src/utils/deploy/playground.ts Fixed
"Choosing Yes lists your app in the public Polkadot Playground so others " +
"can find and open it. No still deploys it to your .dot address. It just " +
"won't be listed in the playground.",
`can find and open it. No still deploys it to your .${getEnvTld()} address. ` +

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few copy strings didn't make the sweep: the publish select hint in DeployScreen.tsx:471 ("deploy to my .dot address only"), the decentralize command and flag descriptions (index.ts:102 and 116), login/nextSteps.ts:31 and 39, and the deploy-all description (index.ts:78).

…dge paths

- tools/register-e2e-fixtures.ts: thread the env TLD into normalizeDomain
  (was a startup TypeError); typecheck now covers this script (the rest of
  tools/ carries pre-existing type errors in standalone operator scripts,
  so only the e2e-wired file joins the tsc baseline)
- TEST_TEMPLATE_DOMAIN -> dot-cli-mod-fixture.paseo in e2e.yml, e2e-local.sh,
  and both e2e docs
- DeployScreen: validate a flag-passed --domain up front and fall back to the
  domain prompt with the inline error instead of throwing during render
- defaultRepoName strips any known TLD; deploy-all duplicate guard normalizes
  with the env TLD; mod surfaces normalizeDomain's wrong-TLD message
- Copy sweep: publish hint, decentralize/deploy-all descriptions, login next
  steps; README examples, bulletin-deploy rename, real pin version
- Drop unused label destructure in publishToPlayground
@illegalcall

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough sweep review @UtkarshBhardwaj007. All comments addressed in 98d9577:

  • tools/register-e2e-fixtures.ts: the five one-arg normalizeDomain() calls now thread the env TLD (they were a startup TypeError). bun tools/register-e2e-fixtures.ts --help runs clean and lists the fixtures as .paseo. The script is now also in the tsc include so this class of miss fails typecheck; the rest of tools/ is NOT included because the standalone operator scripts (check-bulletin-funder, diagnose-mapping, drain-product-account) carry pre-existing type errors that would burn the zero-error baseline. Cleaning those up is a separate chore.
  • TEST_TEMPLATE_DOMAIN: flipped to dot-cli-mod-fixture.paseo in all 4 e2e.yml cells, tools/e2e-local.sh, docs/e2e-running-tests.md, and docs/e2e-bootstrap.md. The script default now derives from getEnvTld() so it can't drift again.
  • DeployScreen render throw: a flag-passed --domain is validated once up front; on failure the screen falls back to the domain prompt with the message in the usual inline-error slot (same surface as the availability-check failure path), prefilled with the rejected value.
  • defaultRepoName: strips any known TLD (case-insensitive), so mod cool-app.paseo yields cool-app-<hex>; tests extended with .paseo cases.
  • deploy-all duplicate guard: normalizes with the env TLD before comparing, so "app" and "app.paseo" are caught; tests added (including the non-conflation case for a foreign-TLD spelling).
  • mod wrong-TLD hint: mod foo.dot on paseo now surfaces normalizeDomain's actionable wrong-TLD message instead of "not found in registry".
  • Copy sweep: publish hint in DeployScreen, decentralize command + --dot flag descriptions, deploy-all description, login next-steps.
  • README: .dot examples updated, polkadot-app-deploy references renamed to bulletin-deploy, and the stale "currently pinned 0.8.3" line now states the real 0.15.0 pin and points at CLAUDE.md's bump protocol.
  • playground.ts: unused label destructure dropped.

All four checks green (format:check, lint:license, typecheck, test: 1014 passed).

On the e2e failures: confirmed, and it is exactly the funder. Every cell dies in globalSetup before any test runs:

[e2e setup] e2e-deployer balance: 0 PAS (5DtoCFYY2gqk65CkrJAc44LCPZDvrxQCkCvTc2AoX28bCu65)
Error: ... Underlying error: All funders exhausted (tried: dedicated, Alice)

The paseo-next-v2 wipe zeroed the whole chain: the e2e deployer (//e2e-deployer, 5DtoCFYY...) is at 0, the dedicated funder (bare root of the MASTER_FUNDER_SEED secret, 5GmicA2jcBxr588m6b2RLhXYWWMiGYXDhaJzHA4KgXc51Fhv) is at 0.00 PAS per today's scheduled probe (see #226, filed by the funder-balance-check workflow), and Alice is below the ~101 PAS a top-up transfer needs. No secret rotation is required: the seed still derives the same address, it just has no funds.

Remediation, in order:

  1. A human tops up the dedicated funder 5GmicA2jcBxr588m6b2RLhXYWWMiGYXDhaJzHA4KgXc51Fhv on Paseo Asset Hub (parachain 1500) via https://faucet.polkadot.io/?network=pah, to at least 5000 PAS (the balance-check threshold; e2e top-ups draw 1000 PAS per transfer). This also closes [URGENT] Dedicated funder balance low — top up required #226.
  2. Re-register the wiped fixture registry entries with the fixed script (funds the deployer and requests the Bulletin allowance itself):
    MASTER_FUNDER_SEED=<secret> bun tools/register-e2e-fixtures.ts
    
    This writes the nine .paseo fixture keys listed by --help, including dot-cli-mod-fixture.paseo pointing at Rock-Paper-Scissors.
  3. Re-run the E2E workflow on this branch.

I have deliberately not executed any chain writes or touched secrets; step 2 is ready to run as-is once the funder has balance.

A network=pah drip lands on the public Paseo Asset Hub (para 1000), not
Asset Hub Next v2 (para 1500) where playground lives; proven empirically
when a drip via that link left the funder's next-v2 balance at 0. The
parachain=1500 form matches bulletin-deploy's environments.json
popSelfServe.faucetUrl, and the divergence guard now pins the two.
faucetUrlFor is separator-aware, and the funder-balance-check issue
template uses the corrected link.
@illegalcall
illegalcall force-pushed the feat/bulletin-deploy-0.15-paseo-tld branch from 5fd3c59 to d4708eb Compare August 14, 2026 05:18
@illegalcall

Copy link
Copy Markdown
Contributor Author

One more fix in d4708eb, and a correction to the remediation link in my previous comment: the faucet links this repo carried pointed at the WRONG chain. https://faucet.polkadot.io/?network=pah drips to the public Paseo Asset Hub (para 1000), not Asset Hub Next v2 (para 1500) where playground lives; we proved this empirically when a drip to the funder via network=pah left its next-v2 balance at 0 (re-confirmed just now: the funder reads 0 PAS on paseo-asset-hub-next-rpc). The correct form is https://faucet.polkadot.io/?parachain=1500, which is exactly what bulletin-deploy 0.15.0's environments.json ships as paseo-next-v2's popSelfServe.faucetUrl.

Changed:

  • src/config.ts: PASEO_NEXT_V2.faucetUrl is now the ?parachain=1500 form, with a doc note on why the form is load-bearing.
  • config.test.ts: the divergence guard now pins faucetUrl to upstream's popSelfServe.faucetUrl, so the two catalogs can't disagree again.
  • faucetUrlFor is separator-aware when appending address (composed link: ...?parachain=1500&address=<ss58>), with a unit test.
  • funder-balance-check.yml: the low-balance issue template now emits the corrected link.

So for the funder top-up in my earlier comment, please use: https://faucet.polkadot.io/?parachain=1500&address=5GmicA2jcBxr588m6b2RLhXYWWMiGYXDhaJzHA4KgXc51Fhv

All four checks green (1016 tests).

@illegalcall

Copy link
Copy Markdown
Contributor Author

@UtkarshBhardwaj007 all review comments addressed. On e2e: the funder is at 0 post-wipe and the public faucet can't reach next v2 (drips land on para 1000). You mentioned a new funder account - rotate the secret to one you can fund, or transfer to the existing 5GmicA2jcBxr588m6b2RLhXYWWMiGYXDhaJzHA4KgXc51Fhv? Alternatively, since the red is purely the funder, fine to merge now and go green on main once funded - your call.

@UtkarshBhardwaj007

Copy link
Copy Markdown
Member

@UtkarshBhardwaj007 all review comments addressed. On e2e: the funder is at 0 post-wipe and the public faucet can't reach next v2 (drips land on para 1000). You mentioned a new funder account - rotate the secret to one you can fund, or transfer to the existing 5GmicA2jcBxr588m6b2RLhXYWWMiGYXDhaJzHA4KgXc51Fhv? Alternatively, since the red is purely the funder, fine to merge now and go green on main once funded - your call.

There is no urgency to merge this PR AFAIK. Let's fix this here then. If this is urgent - sure we can create a task for it but this has been red since quite a while - would be good to fix.

Alternatively, since the red is purely the funder, fine to merge now and go green on main once funded - your call.

We cannot know if it is purely the funder as the test doesn't proceed ahead as soon as it fails to fund.

The builder-identity gate runs first in deploy/decentralize/deploy-all and
soft-exits 0 for a sessionless run, which swallowed getChainConfig's
'--env <x> is not yet supported' error entirely: 'deploy --env mainnet'
printed the sign-in notice and exited 0. Validate the resolved env before
the gate in all three commands; the throw propagates through the normal
error path with the canonical message and a non-zero exit.
@illegalcall

Copy link
Copy Markdown
Contributor Author

Reran e2e after the funder top-up (thanks!). Results and classification:

So this branch's e2e now sits exactly at main's baseline plus one fix. Given the remaining red is structural on main, I'd merge and pursue #504/#505 separately - your call.

@illegalcall
illegalcall merged commit c66e22b into main Aug 20, 2026
17 of 21 checks passed
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.

2 participants