Skip to content

Commit 3fabd39

Browse files
feat(config): DOT_BULLETIN_RPC env override + nightly-chaos-rpc cell (Phase 6 S18)
1 parent c3fb994 commit 3fabd39

6 files changed

Lines changed: 95 additions & 16 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"playground-cli": patch
3+
---
4+
5+
Adds `DOT_BULLETIN_RPC` env-var override to `getChainConfig()`, allowing tests (or operators in an emergency) to prepend a custom Bulletin RPC endpoint while keeping the built-in URL as a fallback. The new `nightly-chaos-rpc` cell exercises this by setting an unroutable primary URL and asserting the deploy still completes via failover.

.github/workflows/e2e.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ jobs:
141141
- cell: nightly-deploy-multi
142142
# source: e2e/cli/deploy.test.ts → describe("dot deploy — multi …")
143143
pattern: "deploy — multi"
144+
- cell: nightly-chaos-rpc
145+
# source: e2e/cli/chaos.test.ts → describe("dot deploy — chaos RPC failover")
146+
pattern: "chaos RPC failover"
147+
testFile: e2e/cli/chaos.test.ts
144148
steps:
145149
- uses: actions/checkout@v4
146150

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ These are things that aren't self-evident from reading the code and have bitten
5656

5757
- **Local launcher:** `tools/e2e-local.sh [smoke|pr|nightly]` — also callable via `pnpm test:e2e:smoke`, `pnpm test:e2e:pr`, `pnpm test:e2e:nightly`.
5858
- **CI workflow:** `.github/workflows/e2e.yml` — runs on PR / push:main / cron 06:00 UTC / workflow_dispatch.
59-
- **CI matrix:** 12 cells across four matrices — `test-no-publish` (parallel: pr-install, pr-preflight, pr-mod, pr-init-session) + `test-publish` (max-parallel: 1: pr-deploy-frontend, pr-deploy-foundry) + `test-nightly-no-publish` (parallel, schedule/dispatch only: nightly-mod-miss, nightly-diagnostic, nightly-rejections, nightly-chaos-sigint) + `test-nightly-publish` (max-parallel: 1, schedule/dispatch only: nightly-deploy-hardhat, nightly-deploy-multi). Each cell runs a subset via `vitest -t "<pattern>"`.
59+
- **CI matrix:** 13 cells across four matrices — `test-no-publish` (parallel: pr-install, pr-preflight, pr-mod, pr-init-session) + `test-publish` (max-parallel: 1: pr-deploy-frontend, pr-deploy-foundry) + `test-nightly-no-publish` (parallel, schedule/dispatch only: nightly-mod-miss, nightly-diagnostic, nightly-rejections, nightly-chaos-sigint) + `test-nightly-publish` (max-parallel: 1, schedule/dispatch only: nightly-deploy-hardhat, nightly-deploy-multi, nightly-chaos-rpc). Each cell runs a subset via `vitest -t "<pattern>"`.
6060
- **Release smoke:** `.github/workflows/e2e-release.yml` fires on `release: prereleased`, downloads the `dot-linux-x64` SEA asset, and runs `e2e/cli/published.test.ts` against it. Validates the published binary before stable release.
6161
- **Test files:** `e2e/cli/*.test.ts` (vitest, spawned via `bun run src/index.ts`).
6262
- **Reports directory:** `e2e-reports/junit.xml` + `e2e-reports/dot-runs.log` (gitignored).

e2e/cli/chaos.test.ts

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,26 @@ import { fixturePath } from "./fixtures/templates.js";
2929
const REPO_ROOT = resolve(import.meta.dirname, "../..");
3030
const CLI_ENTRY = resolve(REPO_ROOT, "src/index.ts");
3131

32+
/** Common CLI args for a full playground deploy in chaos scenarios. */
33+
function chaosDeployArgs(domain: string, buildDir: string, dir: string): string[] {
34+
return [
35+
"run",
36+
CLI_ENTRY,
37+
"deploy",
38+
"--signer",
39+
"dev",
40+
"--domain",
41+
domain,
42+
"--buildDir",
43+
buildDir,
44+
"--playground",
45+
"--suri",
46+
SIGNER.suri,
47+
"--dir",
48+
dir,
49+
];
50+
}
51+
3252
/** How long to wait for the storage-phase sentinel before sending SIGINT anyway. */
3353
const SENTINEL_WAIT_MS = 60_000;
3454

@@ -41,22 +61,11 @@ describe("dot deploy — chaos", () => {
4161

4262
const child = execa(
4363
"bun",
44-
[
45-
"run",
46-
CLI_ENTRY,
47-
"deploy",
48-
"--signer",
49-
"dev",
50-
"--domain",
64+
chaosDeployArgs(
5165
E2E_DOMAINS.chaos,
52-
"--buildDir",
5366
resolve(frontendOnly, "dist"),
54-
"--playground",
55-
"--suri",
56-
SIGNER.suri,
57-
"--dir",
5867
frontendOnly,
59-
],
68+
),
6069
{
6170
cwd: REPO_ROOT,
6271
env: { ...process.env, DOT_TAG: "e2e-chaos-sigint", DOT_TELEMETRY: "1" },
@@ -121,3 +130,40 @@ describe("dot deploy — chaos", () => {
121130
).toBeLessThan(MAX_EXIT_MS);
122131
});
123132
});
133+
134+
describe("dot deploy — chaos RPC failover", () => {
135+
test("survives an unreachable primary bulletin RPC via failover", { timeout: 600_000 }, async () => {
136+
// Set DOT_BULLETIN_RPC to an unroutable address. getChainConfig() will
137+
// expose it as bulletinRpc and put the real endpoint in bulletinRpcFallbacks.
138+
// bulletin-deploy's deploy() internally builds [override, DEFAULT] as its
139+
// BULLETIN_ENDPOINTS list and polkadot-api's WS provider fails over
140+
// automatically when the primary is unreachable. The deploy MUST still
141+
// succeed — we're testing failover, not rejection.
142+
const frontendOnly = fixturePath("frontend-only");
143+
144+
const result = await execa(
145+
"bun",
146+
chaosDeployArgs(
147+
E2E_DOMAINS.chaos,
148+
resolve(frontendOnly, "dist"),
149+
frontendOnly,
150+
),
151+
{
152+
cwd: REPO_ROOT,
153+
env: {
154+
...process.env,
155+
DOT_TAG: "e2e-chaos-rpc",
156+
DOT_TELEMETRY: "1",
157+
DOT_BULLETIN_RPC: "ws://127.0.0.1:1/",
158+
},
159+
reject: false,
160+
timeout: 580_000,
161+
},
162+
);
163+
164+
expect(
165+
result.exitCode,
166+
`deploy failed: ${result.stdout}\n${result.stderr}`,
167+
).toBe(0);
168+
});
169+
});

src/config.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ export interface ChainConfig {
1717
assetHubRpc: string;
1818
/** WebSocket endpoint for Paseo Bulletin (immutable IPFS storage). */
1919
bulletinRpc: string;
20+
/**
21+
* Ordered fallback endpoints for Bulletin, used where the caller builds its
22+
* own WS provider (e.g. the dedicated metadata-upload client in
23+
* `src/utils/deploy/playground.ts`). Always excludes `bulletinRpc` itself.
24+
* Typically empty; populated when `DOT_BULLETIN_RPC` overrides the primary.
25+
*/
26+
bulletinRpcFallbacks: string[];
2027
/** WebSocket endpoints for the People chain (SSO / session discovery). */
2128
peopleEndpoints: string[];
2229
/** Viewer URL shown to users after a successful deploy. */
@@ -26,6 +33,7 @@ export interface ChainConfig {
2633
const TESTNET: ChainConfig = {
2734
assetHubRpc: "wss://asset-hub-paseo-rpc.n.dwellir.com",
2835
bulletinRpc: "wss://paseo-bulletin-rpc.polkadot.io",
36+
bulletinRpcFallbacks: [],
2937
peopleEndpoints: ["wss://paseo-people-next-rpc.polkadot.io"],
3038
appViewerOrigin: "https://dot.li",
3139
};
@@ -36,7 +44,23 @@ export function getChainConfig(env: Env = DEFAULT_ENV): ChainConfig {
3644
"`--env mainnet` is not yet supported. Use `--env testnet` (default) while mainnet launch is pending.",
3745
);
3846
}
39-
return TESTNET;
47+
const cfg = TESTNET;
48+
// CHAOS-test hook: when DOT_BULLETIN_RPC is set, use it as the primary
49+
// Bulletin endpoint and retain the built-in URL as a fallback so failover
50+
// works. bulletin-deploy's deploy() already applies this pattern internally
51+
// (it builds [userRpc, DEFAULT] from options.rpc), so storage.ts consumers
52+
// get failover for free. The dedicated WS client in playground.ts reads
53+
// bulletinRpcFallbacks explicitly and builds its own endpoint array.
54+
// Used by `e2e/cli/chaos.test.ts` to simulate an unreachable primary RPC.
55+
const override = process.env.DOT_BULLETIN_RPC;
56+
if (override) {
57+
return {
58+
...cfg,
59+
bulletinRpc: override,
60+
bulletinRpcFallbacks: [cfg.bulletinRpc],
61+
};
62+
}
63+
return cfg;
4064
}
4165

4266
/** Fixed CDM meta-registry contract on Asset Hub. Source: @dotdm/utils REGISTRY_ADDRESS. */

src/utils/deploy/playground.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export async function publishToPlayground(
168168
const bulletinClient = createClient(
169169
withPolkadotSdkCompat(
170170
getWsProvider({
171-
endpoints: [cfg.bulletinRpc],
171+
endpoints: [cfg.bulletinRpc, ...cfg.bulletinRpcFallbacks],
172172
heartbeatTimeout: BULLETIN_WS_HEARTBEAT_MS,
173173
}),
174174
),

0 commit comments

Comments
 (0)