Skip to content

Commit b56a891

Browse files
Merge pull request #84 from paritytech/ci/e2e-phase-3-fixture-tool
tools(e2e): register-e2e-fixtures — Phase 3 of E2E redesign
2 parents a596196 + 36dab45 commit b56a891

3 files changed

Lines changed: 191 additions & 118 deletions

File tree

e2e/cli/fixtures/accounts.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,13 @@ export const E2E_DOMAINS = {
9393
redeploy: "e2e-cli-redeploy",
9494
/** Used by the cross-owner collision test (BOB tries to take SIGNER's). */
9595
collision: "e2e-cli-collision",
96+
/**
97+
* Phase 3 cell domains — registered by `tools/register-e2e-fixtures.ts`.
98+
* Owned by SIGNER; subsequent runs are same-owner re-publishes.
99+
* Not yet wired to any test — see Phase 4 of docs-internal/2026-05-02-e2e-test-suite-design.md.
100+
*/
101+
foundry: "e2e-cli-foundry",
102+
cdm: "e2e-cli-cdm",
103+
hardhat: "e2e-cli-hardhat",
104+
multi: "e2e-cli-multi",
96105
} as const;

tools/register-e2e-fixtures.ts

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#!/usr/bin/env bun
2+
/**
3+
* Register all permanent E2E fixture domains on the live playground-registry
4+
* contract, signed by the dedicated E2E deployer (SIGNER from
5+
* e2e/cli/fixtures/accounts.ts). Same-owner re-publish is permitted by the
6+
* registry contract, so re-running this tool simply updates the metadata in
7+
* place — idempotent.
8+
*
9+
* Generalises the old `register-mod-fixture.ts`. The mod fixture
10+
* (`dot-cli-mod-fixture.dot`) is now one entry in a unified FIXTURES table
11+
* alongside the new per-cell deploy domains added in Phase 3 (foundry, cdm,
12+
* hardhat, multi).
13+
*
14+
* Usage:
15+
* bun tools/register-e2e-fixtures.ts # register all 5
16+
* bun tools/register-e2e-fixtures.ts --domain e2e-cli-foundry # one only
17+
* bun tools/register-e2e-fixtures.ts --suri //Alice # custom signer
18+
*
19+
* Auto-tops-up SIGNER from the CLI's funder chain if balance is too low to
20+
* cover the publish extrinsic, matching the e2e setup behavior.
21+
*/
22+
23+
import { resolveSigner } from "../src/utils/signer.js";
24+
import { publishToPlayground } from "../src/utils/deploy/playground.js";
25+
import { getConnection, destroyConnection } from "../src/utils/connection.js";
26+
import { ensureFunded, checkBalance, MIN_BALANCE } from "../src/utils/account/funding.js";
27+
import { DEDICATED_E2E_DEPLOYER_MNEMONIC } from "../e2e/cli/fixtures/accounts.js";
28+
29+
interface Fixture {
30+
domain: string;
31+
repositoryUrl: string | null;
32+
purpose: string;
33+
}
34+
35+
/**
36+
* Permanent E2E fixture domains. Registering them is a one-shot bootstrap
37+
* step per registry-contract lifetime; see Phase 3 of the spec.
38+
*
39+
* `dot-cli-mod-fixture.dot` is the only one with a repository URL, because
40+
* `dot mod <domain>` only works when the registered metadata advertises a
41+
* source repo. The other domains are deploy targets — same-owner re-publish
42+
* cycles their metadata on every CI run.
43+
*/
44+
const FIXTURES: readonly Fixture[] = [
45+
{
46+
domain: "dot-cli-mod-fixture.dot",
47+
repositoryUrl: "https://github.com/paritytech/Rock-Paper-Scissors",
48+
purpose: "dot mod E2E fixture (clones into a fresh repo)",
49+
},
50+
{
51+
domain: "e2e-cli-foundry",
52+
repositoryUrl: null,
53+
purpose: "pr-deploy-foundry cell",
54+
},
55+
{
56+
domain: "e2e-cli-cdm",
57+
repositoryUrl: null,
58+
purpose: "pr-deploy-cdm cell",
59+
},
60+
{
61+
domain: "e2e-cli-hardhat",
62+
repositoryUrl: null,
63+
purpose: "nightly-deploy-hardhat cell",
64+
},
65+
{
66+
domain: "e2e-cli-multi",
67+
repositoryUrl: null,
68+
purpose: "nightly-deploy-multi cell",
69+
},
70+
];
71+
72+
const DEFAULT_SURI = `${DEDICATED_E2E_DEPLOYER_MNEMONIC}//e2e-deployer`;
73+
const DOT = 10_000_000_000n;
74+
const TOPUP_TARGET = 500n * DOT;
75+
const TOPUP_AMOUNT = 1000n * DOT;
76+
77+
interface Args {
78+
onlyDomain: string | null;
79+
suri: string;
80+
}
81+
82+
function parseArgs(argv: string[]): Args {
83+
const args: Args = { onlyDomain: null, suri: DEFAULT_SURI };
84+
for (let i = 0; i < argv.length; i++) {
85+
const arg = argv[i];
86+
const next = argv[i + 1];
87+
if (arg === "--domain" && next) {
88+
args.onlyDomain = next;
89+
i++;
90+
} else if (arg === "--suri" && next) {
91+
args.suri = next;
92+
i++;
93+
} else if (arg === "--help" || arg === "-h") {
94+
console.log("Usage: bun tools/register-e2e-fixtures.ts [--domain X] [--suri Z]");
95+
console.log();
96+
console.log("Default: registers all permanent E2E fixture domains:");
97+
for (const f of FIXTURES) {
98+
console.log(` ${f.domain.padEnd(28)}${f.purpose}`);
99+
}
100+
process.exit(0);
101+
} else {
102+
throw new Error(`Unknown arg: ${arg}`);
103+
}
104+
}
105+
return args;
106+
}
107+
108+
async function topUpIfLow(client: Awaited<ReturnType<typeof getConnection>>, address: string): Promise<void> {
109+
const balance = await checkBalance(client, address, TOPUP_TARGET);
110+
console.log(`signer balance: ${balance.free / DOT} DOT`);
111+
if (!balance.sufficient) {
112+
console.log(`balance below ${TOPUP_TARGET / DOT} DOT — topping up by ${TOPUP_AMOUNT / DOT} DOT…`);
113+
await ensureFunded(client, address, TOPUP_TARGET, TOPUP_AMOUNT);
114+
const after = await checkBalance(client, address, MIN_BALANCE);
115+
console.log(`topped up: ${after.free / DOT} DOT`);
116+
}
117+
console.log();
118+
}
119+
120+
async function registerOne(fixture: Fixture, signer: Awaited<ReturnType<typeof resolveSigner>>): Promise<void> {
121+
console.log(`▶ registering ${fixture.domain}`);
122+
console.log(` purpose: ${fixture.purpose}`);
123+
console.log(` repository: ${fixture.repositoryUrl ?? "(none)"}`);
124+
const result = await publishToPlayground({
125+
domain: fixture.domain,
126+
publishSigner: signer,
127+
repositoryUrl: fixture.repositoryUrl,
128+
onLogEvent: (event) => {
129+
if (event.kind === "info") console.log(` • ${event.message}`);
130+
},
131+
});
132+
console.log(` ✓ published ${result.fullDomain}`);
133+
console.log(` metadataCid ${result.metadataCid}`);
134+
console.log();
135+
}
136+
137+
async function main(): Promise<number> {
138+
const args = parseArgs(process.argv.slice(2));
139+
140+
const normalize = (s: string): string => s.replace(/\.dot$/i, "");
141+
const targets = args.onlyDomain
142+
? FIXTURES.filter((f) => normalize(f.domain) === normalize(args.onlyDomain ?? ""))
143+
: FIXTURES;
144+
145+
if (targets.length === 0) {
146+
console.error(`No fixture matches --domain ${args.onlyDomain}`);
147+
console.error(`Known fixtures: ${FIXTURES.map((f) => f.domain).join(", ")}`);
148+
return 2;
149+
}
150+
151+
console.log(`registering ${targets.length} fixture(s):`);
152+
for (const f of targets) console.log(` - ${f.domain}`);
153+
console.log();
154+
155+
const signer = await resolveSigner({ suri: args.suri });
156+
console.log(`signer ${signer.address} (${signer.source})`);
157+
console.log();
158+
159+
try {
160+
const client = await getConnection();
161+
// Balance checked once; TOPUP_TARGET (500 DOT) gives ~1000× headroom
162+
// for the ~0.1 DOT/publish cost across all 5 fixtures.
163+
await topUpIfLow(client, signer.address);
164+
for (const fixture of targets) {
165+
await registerOne(fixture, signer);
166+
}
167+
console.log(`✓ all ${targets.length} fixture(s) registered`);
168+
console.log();
169+
console.log(`verify with: bun tools/probe-registry-resolution.ts <domain>`);
170+
return 0;
171+
} finally {
172+
signer.destroy();
173+
destroyConnection();
174+
}
175+
}
176+
177+
main()
178+
.then((code) => process.exit(code))
179+
.catch((err) => {
180+
console.error(err instanceof Error ? (err.stack ?? err.message) : String(err));
181+
process.exit(2);
182+
});

tools/register-mod-fixture.ts

Lines changed: 0 additions & 118 deletions
This file was deleted.

0 commit comments

Comments
 (0)