bulletin-deploy 0.7.12 → 0.7.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -4
- package/assets/environments.json +238 -0
- package/bin/bulletin-deploy +49 -1
- package/dist/bug-report.js +4 -4
- package/dist/chunk-2VYG7NXN.js +266 -0
- package/dist/{chunk-VQJLGE5J.js → chunk-KU6N5DD3.js} +10 -7
- package/dist/{chunk-LOZ5PSD3.js → chunk-MRB5E7YM.js} +9 -9
- package/dist/{chunk-7WKHLBZA.js → chunk-RBFXJVAG.js} +73 -23
- package/dist/{chunk-RVCY2VEY.js → chunk-TTSFL3JB.js} +1 -1
- package/dist/{chunk-N2OZLFJA.js → chunk-Y54W6NVZ.js} +2 -2
- package/dist/{chunk-WK2GKDMX.js → chunk-YX5USCHH.js} +55 -30
- package/dist/chunk-ZOC4GITL.js +13 -0
- package/dist/deploy.d.ts +20 -6
- package/dist/deploy.js +12 -9
- package/dist/dotns.d.ts +24 -2
- package/dist/dotns.js +5 -3
- package/dist/environments.d.ts +65 -0
- package/dist/environments.js +28 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +18 -16
- package/dist/memory-report.js +2 -2
- package/dist/run-state.js +1 -1
- package/dist/telemetry.js +2 -2
- package/dist/version-check.js +3 -3
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -53,21 +53,49 @@ bulletin-deploy <build-dir> <domain.dot>
|
|
|
53
53
|
Examples:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
# Basic deploy
|
|
56
|
+
# Basic deploy (defaults to --env paseo-next)
|
|
57
57
|
bulletin-deploy ./dist my-app00.dot
|
|
58
58
|
|
|
59
|
+
# Pick a different environment
|
|
60
|
+
bulletin-deploy ./dist my-app00.dot --env paseo-review
|
|
61
|
+
|
|
62
|
+
# List supported environments
|
|
63
|
+
bulletin-deploy --list-environments
|
|
64
|
+
|
|
65
|
+
# Refresh the environments cache before deploying
|
|
66
|
+
bulletin-deploy ./dist my-app00.dot --refresh-environments --env paseo-next
|
|
67
|
+
|
|
59
68
|
# Direct signer deploy
|
|
60
69
|
bulletin-deploy ./dist my-app00.dot --mnemonic "..."
|
|
61
70
|
|
|
62
|
-
# Custom Bulletin RPC
|
|
71
|
+
# Custom Bulletin RPC override (asset-hub still comes from --env)
|
|
63
72
|
bulletin-deploy ./dist my-app00.dot --rpc wss://custom-bulletin.example.com
|
|
64
73
|
```
|
|
65
74
|
|
|
75
|
+
### Selecting an environment
|
|
76
|
+
|
|
77
|
+
`--env <id>` selects a target environment by id. The list of environments and their RPC endpoints is sourced dynamically from [`paritytech/bulletin-deploy/assets/environments.json`](./assets/environments.json), which mirrors [`paritytech/triangle-status/environments.json`](https://github.com/paritytech/triangle-status/blob/main/environments.json) (the latter is private; bulletin-deploy serves as the public mirror).
|
|
78
|
+
|
|
79
|
+
| Env id | Network | Bulletin available? |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `paseo-next` (default) | testnet | yes |
|
|
82
|
+
| `paseo-review` | testnet | yes |
|
|
83
|
+
| `preview` | testnet | yes |
|
|
84
|
+
| `polkadot` | mainnet | not yet |
|
|
85
|
+
| `kusama` | mainnet | not yet |
|
|
86
|
+
|
|
87
|
+
A single env id drives both the bulletin RPC and the asset-hub RPC used internally for DotNS, so they cannot drift. When you pass `--rpc`, it overrides only the bulletin endpoint within the chosen env; the asset-hub endpoint still comes from `--env`.
|
|
88
|
+
|
|
89
|
+
The runtime uses a 24-hour cache at `${XDG_CACHE_HOME:-~/.cache}/bulletin-deploy/environments.json`; `--refresh-environments` busts it and re-fetches. The npm tarball ships a bundled snapshot that is used when the live URL is unreachable.
|
|
90
|
+
|
|
66
91
|
### Options
|
|
67
92
|
|
|
68
93
|
| Flag | What it does |
|
|
69
94
|
|---|---|
|
|
70
|
-
| `--
|
|
95
|
+
| `--env <id>` | Target environment. Default: `paseo-next`. See `--list-environments` for valid ids. |
|
|
96
|
+
| `--list-environments` | Print the environments table and exit. |
|
|
97
|
+
| `--refresh-environments` | Bust the cache and re-fetch environments.json. Composes with `--env` (refresh-then-deploy) or runs solo. |
|
|
98
|
+
| `--rpc wss://...` | Override the Bulletin RPC endpoint within the chosen `--env`. Also readable from `BULLETIN_RPC`. |
|
|
71
99
|
| `--mnemonic "..."` | Use a specific mnemonic as the direct signer for Bulletin uploads and DotNS updates. Also readable from `MNEMONIC`. |
|
|
72
100
|
| `--derivation-path "..."` | Apply a Substrate derivation path to `--mnemonic`, for example `//deploy/3`. |
|
|
73
101
|
| `--pool-size N` | Change the number of derived pool accounts available for pool-mode Bulletin uploads. Default: `10`. |
|
|
@@ -138,9 +166,11 @@ await deploy("./dist", "my-app00.dot", { jsMerkle: true });
|
|
|
138
166
|
|
|
139
167
|
| Variable | Default | Description |
|
|
140
168
|
|---|---|---|
|
|
141
|
-
| `BULLETIN_RPC` | `wss://paseo-bulletin-rpc.polkadot.io` | Bulletin chain WebSocket RPC |
|
|
169
|
+
| `BULLETIN_RPC` | `wss://paseo-bulletin-rpc.polkadot.io` | Override the Bulletin chain WebSocket RPC for the chosen `--env`. |
|
|
170
|
+
| `BULLETIN_ENVIRONMENTS_URL` | bulletin-deploy public mirror | Override the runtime URL for environments.json. Internal teams point this at a fork or local proxy. |
|
|
142
171
|
| `BULLETIN_DEPLOY_TELEMETRY` | off for external users, on for internal users | `1` to opt in, `0` to force off |
|
|
143
172
|
| `BULLETIN_DEPLOY_UPDATE_CHECK` | `1` | Set to `0` to disable version checks on failure |
|
|
173
|
+
| `BULLETIN_DEPLOY_DOTNS_CLI` | bundled `@parity/dotns-cli`, then host dispatch | Set to `host` for `process.execPath dotns ...` dispatch in bundled host CLIs, or to a `dotns` command/path |
|
|
144
174
|
| `DOTNS_STATUS` | `full` on testnet, `none` on mainnet | PoP level to self-grant before registration: `none`, `lite`, or `full` |
|
|
145
175
|
| `IPFS_CID` | unset | Skip storage and reuse an existing CID |
|
|
146
176
|
| `DEPLOY_TAG` | unset | Telemetry label equivalent to `--tag` |
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
{
|
|
2
|
+
"environments": [
|
|
3
|
+
{
|
|
4
|
+
"id": "preview",
|
|
5
|
+
"name": "Preview",
|
|
6
|
+
"network": "testnet",
|
|
7
|
+
"description": "Product Preview net, used by Product Teams",
|
|
8
|
+
"backend": "https://polkadot-app-stg.parity.io/",
|
|
9
|
+
"ipfs": "https://previewnet.substrate.dev/ipfs/"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "paseo-next",
|
|
13
|
+
"name": "Paseo Next",
|
|
14
|
+
"network": "testnet",
|
|
15
|
+
"badge": "Testflight",
|
|
16
|
+
"description": "Production testnet for Polkadot App Testflight",
|
|
17
|
+
"backend": "https://identity-backend.parity-testnet.parity.io",
|
|
18
|
+
"ipfs": "https://paseo-ipfs.polkadot.io/ipfs",
|
|
19
|
+
"uptimeUrl": "https://stats.uptimerobot.com/LISM1LRA8m"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "paseo-review",
|
|
23
|
+
"name": "Paseo Review",
|
|
24
|
+
"network": "testnet",
|
|
25
|
+
"description": "Used for App Store review builds",
|
|
26
|
+
"backend": "https://identity-backend-review.parity-testnet.parity.io",
|
|
27
|
+
"ipfs": "https://paseo-bulletin-review-ipfs.polkadot.io",
|
|
28
|
+
"uptimeUrl": "https://stats.uptimerobot.com/bckl1cu0AO"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "polkadot",
|
|
32
|
+
"name": "Polkadot",
|
|
33
|
+
"network": "mainnet",
|
|
34
|
+
"description": "Polkadot mainnet"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": "kusama",
|
|
38
|
+
"name": "Kusama",
|
|
39
|
+
"network": "mainnet",
|
|
40
|
+
"description": "Kusama canary network"
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"chains": [
|
|
44
|
+
{
|
|
45
|
+
"id": "relay",
|
|
46
|
+
"name": "Relay",
|
|
47
|
+
"endpoints": {
|
|
48
|
+
"preview": {
|
|
49
|
+
"wss": "wss://previewnet.substrate.dev/relay/alice"
|
|
50
|
+
},
|
|
51
|
+
"paseo-next": {
|
|
52
|
+
"wss": "wss://paseo-rpc.n.dwellir.com",
|
|
53
|
+
"uptimeUrl": "https://stats.uptimerobot.com/UrEXbl6Xyt"
|
|
54
|
+
},
|
|
55
|
+
"paseo-review": {
|
|
56
|
+
"wss": "wss://paseo-rpc.n.dwellir.com",
|
|
57
|
+
"uptimeUrl": "https://stats.uptimerobot.com/UrEXbl6Xyt"
|
|
58
|
+
},
|
|
59
|
+
"polkadot": {
|
|
60
|
+
"wss": [
|
|
61
|
+
"wss://polkadot-rpc.n.dwellir.com",
|
|
62
|
+
"wss://polkadot.ibp.network",
|
|
63
|
+
"wss://polkadot.dotters.network",
|
|
64
|
+
"wss://rpc.polkadot.io"
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
"kusama": {
|
|
68
|
+
"wss": [
|
|
69
|
+
"wss://kusama-rpc.n.dwellir.com",
|
|
70
|
+
"wss://kusama.ibp.network",
|
|
71
|
+
"wss://kusama.dotters.network",
|
|
72
|
+
"wss://kusama-rpc.polkadot.io"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "asset-hub",
|
|
79
|
+
"name": "Asset Hub",
|
|
80
|
+
"endpoints": {
|
|
81
|
+
"preview": {
|
|
82
|
+
"wss": "wss://previewnet.substrate.dev/asset-hub",
|
|
83
|
+
"parachainId": 1000
|
|
84
|
+
},
|
|
85
|
+
"paseo-next": {
|
|
86
|
+
"wss": "wss://asset-hub-paseo-rpc.n.dwellir.com",
|
|
87
|
+
"parachainId": 1000,
|
|
88
|
+
"uptimeUrl": "https://stats.uptimerobot.com/UrEXbl6Xyt"
|
|
89
|
+
},
|
|
90
|
+
"paseo-review": {
|
|
91
|
+
"wss": "wss://asset-hub-paseo-rpc.n.dwellir.com",
|
|
92
|
+
"parachainId": 1000,
|
|
93
|
+
"uptimeUrl": "https://stats.uptimerobot.com/UrEXbl6Xyt"
|
|
94
|
+
},
|
|
95
|
+
"polkadot": {
|
|
96
|
+
"wss": [
|
|
97
|
+
"wss://asset-hub-polkadot-rpc.n.dwellir.com",
|
|
98
|
+
"wss://asset-hub-polkadot.ibp.network",
|
|
99
|
+
"wss://asset-hub-polkadot.dotters.network",
|
|
100
|
+
"wss://polkadot-asset-hub-rpc.polkadot.io"
|
|
101
|
+
],
|
|
102
|
+
"parachainId": 1000
|
|
103
|
+
},
|
|
104
|
+
"kusama": {
|
|
105
|
+
"wss": [
|
|
106
|
+
"wss://asset-hub-kusama-rpc.n.dwellir.com",
|
|
107
|
+
"wss://asset-hub-kusama.ibp.network",
|
|
108
|
+
"wss://asset-hub-kusama.dotters.network",
|
|
109
|
+
"wss://kusama-asset-hub-rpc.polkadot.io"
|
|
110
|
+
],
|
|
111
|
+
"parachainId": 1000
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"id": "bridge-hub",
|
|
117
|
+
"name": "Bridge Hub",
|
|
118
|
+
"endpoints": {
|
|
119
|
+
"polkadot": {
|
|
120
|
+
"wss": [
|
|
121
|
+
"wss://bridge-hub-polkadot-rpc.n.dwellir.com",
|
|
122
|
+
"wss://bridge-hub-polkadot.ibp.network",
|
|
123
|
+
"wss://bridge-hub-polkadot.dotters.network",
|
|
124
|
+
"wss://polkadot-bridge-hub-rpc.polkadot.io"
|
|
125
|
+
],
|
|
126
|
+
"parachainId": 1002
|
|
127
|
+
},
|
|
128
|
+
"kusama": {
|
|
129
|
+
"wss": [
|
|
130
|
+
"wss://bridge-hub-kusama-rpc.n.dwellir.com",
|
|
131
|
+
"wss://bridge-hub-kusama.ibp.network",
|
|
132
|
+
"wss://bridge-hub-kusama.dotters.network",
|
|
133
|
+
"wss://kusama-bridge-hub-rpc.polkadot.io"
|
|
134
|
+
],
|
|
135
|
+
"parachainId": 1002
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"id": "collectives",
|
|
141
|
+
"name": "Collectives",
|
|
142
|
+
"endpoints": {
|
|
143
|
+
"polkadot": {
|
|
144
|
+
"wss": [
|
|
145
|
+
"wss://collectives-polkadot-rpc.n.dwellir.com",
|
|
146
|
+
"wss://collectives-polkadot.ibp.network",
|
|
147
|
+
"wss://collectives-polkadot.dotters.network",
|
|
148
|
+
"wss://polkadot-collectives-rpc.polkadot.io"
|
|
149
|
+
],
|
|
150
|
+
"parachainId": 1001
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"id": "coretime",
|
|
156
|
+
"name": "Coretime",
|
|
157
|
+
"endpoints": {
|
|
158
|
+
"polkadot": {
|
|
159
|
+
"wss": [
|
|
160
|
+
"wss://coretime-polkadot-rpc.n.dwellir.com",
|
|
161
|
+
"wss://coretime-polkadot.ibp.network",
|
|
162
|
+
"wss://coretime-polkadot.dotters.network",
|
|
163
|
+
"wss://polkadot-coretime-rpc.polkadot.io"
|
|
164
|
+
],
|
|
165
|
+
"parachainId": 1005
|
|
166
|
+
},
|
|
167
|
+
"kusama": {
|
|
168
|
+
"wss": [
|
|
169
|
+
"wss://coretime-kusama-rpc.n.dwellir.com",
|
|
170
|
+
"wss://coretime-kusama.ibp.network",
|
|
171
|
+
"wss://coretime-kusama.dotters.network",
|
|
172
|
+
"wss://kusama-coretime-rpc.polkadot.io"
|
|
173
|
+
],
|
|
174
|
+
"parachainId": 1005
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"id": "people",
|
|
180
|
+
"name": "People",
|
|
181
|
+
"endpoints": {
|
|
182
|
+
"preview": {
|
|
183
|
+
"wss": "wss://previewnet.substrate.dev/people",
|
|
184
|
+
"parachainId": 1004
|
|
185
|
+
},
|
|
186
|
+
"paseo-next": {
|
|
187
|
+
"wss": "wss://paseo-people-next-rpc.polkadot.io",
|
|
188
|
+
"parachainId": 5140,
|
|
189
|
+
"uptimeUrl": "https://stats.uptimerobot.com/LISM1LRA8m"
|
|
190
|
+
},
|
|
191
|
+
"paseo-review": {
|
|
192
|
+
"wss": "wss://paseo-people-review-rpc.polkadot.io",
|
|
193
|
+
"parachainId": 5167,
|
|
194
|
+
"uptimeUrl": "https://stats.uptimerobot.com/bckl1cu0AO"
|
|
195
|
+
},
|
|
196
|
+
"polkadot": {
|
|
197
|
+
"wss": [
|
|
198
|
+
"wss://people-polkadot-rpc.n.dwellir.com",
|
|
199
|
+
"wss://people-polkadot.ibp.network",
|
|
200
|
+
"wss://people-polkadot.dotters.network",
|
|
201
|
+
"wss://polkadot-people-rpc.polkadot.io"
|
|
202
|
+
],
|
|
203
|
+
"parachainId": 1004
|
|
204
|
+
},
|
|
205
|
+
"kusama": {
|
|
206
|
+
"wss": [
|
|
207
|
+
"wss://people-kusama-rpc.n.dwellir.com",
|
|
208
|
+
"wss://people-kusama.ibp.network",
|
|
209
|
+
"wss://people-kusama.dotters.network",
|
|
210
|
+
"wss://kusama-people-rpc.polkadot.io"
|
|
211
|
+
],
|
|
212
|
+
"parachainId": 1004
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"id": "bulletin",
|
|
218
|
+
"name": "Bulletin",
|
|
219
|
+
"endpoints": {
|
|
220
|
+
"preview": {
|
|
221
|
+
"wss": "wss://previewnet.substrate.dev/bulletin",
|
|
222
|
+
"parachainId": 2487
|
|
223
|
+
},
|
|
224
|
+
"paseo-next": {
|
|
225
|
+
"wss": "wss://paseo-bulletin-rpc.polkadot.io",
|
|
226
|
+
"parachainId": 5118,
|
|
227
|
+
"uptimeUrl": "https://stats.uptimerobot.com/LISM1LRA8m"
|
|
228
|
+
},
|
|
229
|
+
"paseo-review": {
|
|
230
|
+
"wss": "wss://paseo-bulletin-review-rpc.polkadot.io",
|
|
231
|
+
"parachainId": 5168,
|
|
232
|
+
"uptimeUrl": "https://stats.uptimerobot.com/bckl1cu0AO"
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
],
|
|
237
|
+
"source": "https://docs.google.com/document/d/1xQoAmWDpbjhuXKT79DTNKFzv7ZkFr5npjo0BvrxXDIw"
|
|
238
|
+
}
|
package/bin/bulletin-deploy
CHANGED
|
@@ -5,6 +5,7 @@ import { VERSION, setDeployAttribute, captureWarning, closeTelemetry, setRunStat
|
|
|
5
5
|
import { handleFailedDeploy, preReleaseWarning } from "../dist/version-check.js";
|
|
6
6
|
import { setDeployContext, installLogCapture, buildCliFlagsSummary } from "../dist/bug-report.js";
|
|
7
7
|
import { loadRunState, writeRunState, shouldSkipStaleWarning, shouldShowOomHint, probablyOomRssMb } from "../dist/run-state.js";
|
|
8
|
+
import { loadEnvironments, listEnvironments, formatEnvironmentTable, DEFAULT_ENV_ID, DEFAULT_ENVIRONMENTS_URL } from "../dist/environments.js";
|
|
8
9
|
import * as fs from "fs";
|
|
9
10
|
|
|
10
11
|
// Install early so anything printed during flag parsing / preflight is
|
|
@@ -21,6 +22,9 @@ for (let i = 0; i < args.length; i++) {
|
|
|
21
22
|
else if (args[i] === "--mnemonic") { flags.mnemonic = args[++i]; }
|
|
22
23
|
else if (args[i] === "--derivation-path") { flags.derivationPath = args[++i]; }
|
|
23
24
|
else if (args[i] === "--rpc") { flags.rpc = args[++i]; }
|
|
25
|
+
else if (args[i] === "--env") { flags.env = args[++i]; }
|
|
26
|
+
else if (args[i] === "--list-environments") { flags.listEnvironments = true; }
|
|
27
|
+
else if (args[i] === "--refresh-environments") { flags.refreshEnvironments = true; }
|
|
24
28
|
else if (args[i] === "--password") { flags.password = args[++i]; }
|
|
25
29
|
else if (args[i] === "--js-merkle") { flags.jsMerkle = true; }
|
|
26
30
|
else if (args[i] === "--tag") { flags.tag = args[++i]; }
|
|
@@ -42,6 +46,32 @@ if (flags.removedBootstrap) {
|
|
|
42
46
|
process.exit(1);
|
|
43
47
|
}
|
|
44
48
|
|
|
49
|
+
// --list-environments: print the environments table and exit. Composes with
|
|
50
|
+
// nothing else (deploy positional args are ignored).
|
|
51
|
+
if (flags.listEnvironments) {
|
|
52
|
+
try {
|
|
53
|
+
const { doc } = await loadEnvironments();
|
|
54
|
+
console.log(formatEnvironmentTable(listEnvironments(doc)));
|
|
55
|
+
process.exit(0);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
console.error(`Error: failed to load environments: ${e?.message ?? e}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// --refresh-environments alone (no positional args): refresh and exit. With
|
|
63
|
+
// positional args, refresh first, then deploy.
|
|
64
|
+
if (flags.refreshEnvironments && positional.length === 0) {
|
|
65
|
+
try {
|
|
66
|
+
const { doc } = await loadEnvironments({ forceRefresh: true });
|
|
67
|
+
console.log(`Refreshed ${doc.environments.length} environments from ${process.env.BULLETIN_ENVIRONMENTS_URL ?? DEFAULT_ENVIRONMENTS_URL}`);
|
|
68
|
+
process.exit(0);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
console.error(`Error: failed to refresh environments: ${e?.message ?? e}`);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
45
75
|
if (flags.help || positional.length === 0) {
|
|
46
76
|
console.log(`bulletin-deploy v${VERSION}
|
|
47
77
|
|
|
@@ -49,9 +79,16 @@ Usage:
|
|
|
49
79
|
bulletin-deploy <build-dir> <domain.dot> Deploy an app
|
|
50
80
|
|
|
51
81
|
Options:
|
|
82
|
+
--env <id> Target environment from environments.json (default: paseo-next).
|
|
83
|
+
Drives both the bulletin RPC and the asset-hub RPC used
|
|
84
|
+
by DotNS. See --list-environments for valid ids.
|
|
85
|
+
--list-environments Print the environments table and exit.
|
|
86
|
+
--refresh-environments Bust the cache and re-fetch environments.json. Composes
|
|
87
|
+
with --env (refresh-then-deploy) or runs solo.
|
|
52
88
|
--mnemonic "..." DotNS owner mnemonic (or set MNEMONIC env var)
|
|
53
89
|
--derivation-path "..." Optional Substrate-style path applied to --mnemonic (e.g. //deploy/3)
|
|
54
|
-
--rpc wss://...
|
|
90
|
+
--rpc wss://... Override the bulletin RPC for the chosen --env (or set BULLETIN_RPC).
|
|
91
|
+
Precedence: --rpc > BULLETIN_RPC > --env's bulletin endpoint.
|
|
55
92
|
--pool-size N Number of pool accounts (default: 10)
|
|
56
93
|
--password "..." Encrypt SPA content (users will be prompted to decrypt)
|
|
57
94
|
--js-merkle Use pure-JS merkleization (no IPFS Kubo binary required)
|
|
@@ -159,6 +196,16 @@ try {
|
|
|
159
196
|
if (!domain) { console.error("Error: domain required (e.g. my-app.dot)"); process.exit(1); }
|
|
160
197
|
if (!fs.existsSync(buildDir)) { console.error(`Error: ${buildDir} does not exist`); process.exit(1); }
|
|
161
198
|
|
|
199
|
+
// --refresh-environments composed with a deploy: bust the cache before
|
|
200
|
+
// deploy() loads it, so deploy() picks up fresh data on the next loadEnvironments().
|
|
201
|
+
if (flags.refreshEnvironments) {
|
|
202
|
+
try {
|
|
203
|
+
await loadEnvironments({ forceRefresh: true });
|
|
204
|
+
} catch (e) {
|
|
205
|
+
console.error(`Error: failed to refresh environments: ${e?.message ?? e}`);
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
162
209
|
const effectiveRpc = flags.rpc ?? process.env.BULLETIN_RPC ?? DEFAULT_BULLETIN_RPC;
|
|
163
210
|
const deployTag = flags.tag ?? process.env.DEPLOY_TAG;
|
|
164
211
|
const ci = process.env.GITHUB_ACTIONS === "true" ? {
|
|
@@ -184,6 +231,7 @@ try {
|
|
|
184
231
|
mnemonic: flags.mnemonic,
|
|
185
232
|
derivationPath: flags.derivationPath,
|
|
186
233
|
rpc: flags.rpc,
|
|
234
|
+
env: flags.env,
|
|
187
235
|
poolSize: flags.poolSize,
|
|
188
236
|
password: flags.password,
|
|
189
237
|
jsMerkle: flags.jsMerkle,
|
package/dist/bug-report.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
offerBugReport,
|
|
10
10
|
scrubSecrets,
|
|
11
11
|
setDeployContext
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-Y54W6NVZ.js";
|
|
13
|
+
import "./chunk-TTSFL3JB.js";
|
|
14
|
+
import "./chunk-MRB5E7YM.js";
|
|
15
|
+
import "./chunk-KU6N5DD3.js";
|
|
16
16
|
import "./chunk-QGM4M3NI.js";
|
|
17
17
|
export {
|
|
18
18
|
buildCliFlagsSummary,
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NonRetryableError
|
|
3
|
+
} from "./chunk-ZOC4GITL.js";
|
|
4
|
+
|
|
5
|
+
// src/environments.ts
|
|
6
|
+
import * as fs from "fs/promises";
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
import * as os from "os";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
var DEFAULT_ENVIRONMENTS_URL = "https://raw.githubusercontent.com/paritytech/bulletin-deploy/main/assets/environments.json";
|
|
11
|
+
var DEFAULT_ENV_ID = "paseo-next";
|
|
12
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
13
|
+
var FETCH_TIMEOUT_MS = 5e3;
|
|
14
|
+
var HARDCODED_FALLBACK = {
|
|
15
|
+
environments: [
|
|
16
|
+
{
|
|
17
|
+
id: "paseo-next",
|
|
18
|
+
name: "Paseo Next",
|
|
19
|
+
network: "testnet",
|
|
20
|
+
description: "Production testnet for Polkadot App Testflight (hardcoded fallback)"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
chains: [
|
|
24
|
+
{
|
|
25
|
+
id: "bulletin",
|
|
26
|
+
name: "Bulletin",
|
|
27
|
+
endpoints: {
|
|
28
|
+
"paseo-next": {
|
|
29
|
+
wss: "wss://paseo-bulletin-rpc.polkadot.io",
|
|
30
|
+
parachainId: 5118
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "asset-hub",
|
|
36
|
+
name: "Asset Hub",
|
|
37
|
+
endpoints: {
|
|
38
|
+
"paseo-next": {
|
|
39
|
+
wss: [
|
|
40
|
+
"wss://asset-hub-paseo.dotters.network",
|
|
41
|
+
"wss://sys.ibp.network/asset-hub-paseo",
|
|
42
|
+
"wss://pas-rpc.stakeworld.io/assethub"
|
|
43
|
+
],
|
|
44
|
+
parachainId: 1e3
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
};
|
|
50
|
+
function defaultCacheDir() {
|
|
51
|
+
const xdg = process.env.XDG_CACHE_HOME;
|
|
52
|
+
const base = xdg && xdg.length > 0 ? xdg : path.join(os.homedir(), ".cache");
|
|
53
|
+
return path.join(base, "bulletin-deploy");
|
|
54
|
+
}
|
|
55
|
+
function defaultCachePath() {
|
|
56
|
+
return path.join(defaultCacheDir(), "environments.json");
|
|
57
|
+
}
|
|
58
|
+
function defaultBundledPath() {
|
|
59
|
+
return fileURLToPath(new URL("../assets/environments.json", import.meta.url));
|
|
60
|
+
}
|
|
61
|
+
function isValidDoc(value) {
|
|
62
|
+
if (!value || typeof value !== "object") return false;
|
|
63
|
+
const v = value;
|
|
64
|
+
return Array.isArray(v.environments) && Array.isArray(v.chains);
|
|
65
|
+
}
|
|
66
|
+
async function readCache(cachePath) {
|
|
67
|
+
try {
|
|
68
|
+
const raw = await fs.readFile(cachePath, "utf8");
|
|
69
|
+
const parsed = JSON.parse(raw);
|
|
70
|
+
if (parsed && typeof parsed === "object" && typeof parsed.fetchedAt === "string" && isValidDoc(parsed.doc)) {
|
|
71
|
+
return parsed;
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async function writeCache(cachePath, doc, now) {
|
|
79
|
+
try {
|
|
80
|
+
await fs.mkdir(path.dirname(cachePath), { recursive: true });
|
|
81
|
+
const payload = {
|
|
82
|
+
fetchedAt: new Date(now).toISOString(),
|
|
83
|
+
doc
|
|
84
|
+
};
|
|
85
|
+
await fs.writeFile(cachePath, JSON.stringify(payload, null, 2), "utf8");
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function isFresh(cache, now) {
|
|
90
|
+
const fetched = Date.parse(cache.fetchedAt);
|
|
91
|
+
if (Number.isNaN(fetched)) return false;
|
|
92
|
+
return now - fetched < CACHE_TTL_MS;
|
|
93
|
+
}
|
|
94
|
+
async function fetchLive(url, fetchImpl) {
|
|
95
|
+
const ctrl = new AbortController();
|
|
96
|
+
const timer = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);
|
|
97
|
+
try {
|
|
98
|
+
const res = await fetchImpl(url, { signal: ctrl.signal });
|
|
99
|
+
if (!res.ok) {
|
|
100
|
+
throw new Error(`fetch ${url} returned HTTP ${res.status}`);
|
|
101
|
+
}
|
|
102
|
+
const json = await res.json();
|
|
103
|
+
if (!isValidDoc(json)) {
|
|
104
|
+
throw new Error(`fetch ${url} returned malformed environments doc`);
|
|
105
|
+
}
|
|
106
|
+
return json;
|
|
107
|
+
} finally {
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async function readBundled(bundledPath) {
|
|
112
|
+
try {
|
|
113
|
+
const raw = await fs.readFile(bundledPath, "utf8");
|
|
114
|
+
const parsed = JSON.parse(raw);
|
|
115
|
+
return isValidDoc(parsed) ? parsed : null;
|
|
116
|
+
} catch {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function loadEnvironments(opts = {}) {
|
|
121
|
+
const url = opts.url ?? process.env.BULLETIN_ENVIRONMENTS_URL ?? DEFAULT_ENVIRONMENTS_URL;
|
|
122
|
+
const cachePath = path.join(opts.cacheDir ?? defaultCacheDir(), "environments.json");
|
|
123
|
+
const bundledPath = opts.bundledPath ?? defaultBundledPath();
|
|
124
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
125
|
+
const nowFn = opts.now ?? Date.now;
|
|
126
|
+
const warn = opts.warn ?? ((msg) => console.error(msg));
|
|
127
|
+
const capture = opts.capture ?? (() => {
|
|
128
|
+
});
|
|
129
|
+
const now = nowFn();
|
|
130
|
+
if (opts.forceRefresh) {
|
|
131
|
+
const doc = await fetchLive(url, fetchImpl);
|
|
132
|
+
await writeCache(cachePath, doc, now);
|
|
133
|
+
return { doc, source: "live" };
|
|
134
|
+
}
|
|
135
|
+
const cache = await readCache(cachePath);
|
|
136
|
+
if (cache && isFresh(cache, now)) {
|
|
137
|
+
return { doc: cache.doc, source: "cache-fresh" };
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const doc = await fetchLive(url, fetchImpl);
|
|
141
|
+
await writeCache(cachePath, doc, now);
|
|
142
|
+
return { doc, source: "live" };
|
|
143
|
+
} catch (err) {
|
|
144
|
+
if (cache) {
|
|
145
|
+
warn(
|
|
146
|
+
`bulletin-deploy: live environments.json fetch failed; using cached copy from ${cache.fetchedAt} (${err.message ?? err})`
|
|
147
|
+
);
|
|
148
|
+
return { doc: cache.doc, source: "cache-stale" };
|
|
149
|
+
}
|
|
150
|
+
const bundled = await readBundled(bundledPath);
|
|
151
|
+
if (bundled) {
|
|
152
|
+
warn(
|
|
153
|
+
`bulletin-deploy: live environments.json fetch failed and no cache; using bundled snapshot (${err.message ?? err})`
|
|
154
|
+
);
|
|
155
|
+
return { doc: bundled, source: "bundled" };
|
|
156
|
+
}
|
|
157
|
+
capture(err);
|
|
158
|
+
warn(
|
|
159
|
+
`bulletin-deploy: live and bundled environments.json both unavailable; using hardcoded paseo-next fallback`
|
|
160
|
+
);
|
|
161
|
+
return { doc: HARDCODED_FALLBACK, source: "hardcoded-fallback" };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function normalizeWss(value) {
|
|
165
|
+
if (value === void 0) return [];
|
|
166
|
+
return Array.isArray(value) ? value.slice() : [value];
|
|
167
|
+
}
|
|
168
|
+
function levenshtein(a, b) {
|
|
169
|
+
if (a === b) return 0;
|
|
170
|
+
const m = a.length, n = b.length;
|
|
171
|
+
if (m === 0) return n;
|
|
172
|
+
if (n === 0) return m;
|
|
173
|
+
let prev = new Array(n + 1);
|
|
174
|
+
let curr = new Array(n + 1);
|
|
175
|
+
for (let j = 0; j <= n; j++) prev[j] = j;
|
|
176
|
+
for (let i = 1; i <= m; i++) {
|
|
177
|
+
curr[0] = i;
|
|
178
|
+
for (let j = 1; j <= n; j++) {
|
|
179
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
180
|
+
curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);
|
|
181
|
+
}
|
|
182
|
+
[prev, curr] = [curr, prev];
|
|
183
|
+
}
|
|
184
|
+
return prev[n];
|
|
185
|
+
}
|
|
186
|
+
function suggestEnv(envId, doc) {
|
|
187
|
+
let best = null;
|
|
188
|
+
for (const env of doc.environments) {
|
|
189
|
+
const d = levenshtein(envId.toLowerCase(), env.id.toLowerCase());
|
|
190
|
+
if (best === null || d < best.dist) best = { id: env.id, dist: d };
|
|
191
|
+
}
|
|
192
|
+
if (best && best.dist <= Math.max(2, Math.floor(envId.length / 3))) {
|
|
193
|
+
return best.id;
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
function resolveEndpoints(doc, envId) {
|
|
198
|
+
const env = doc.environments.find((e) => e.id === envId);
|
|
199
|
+
if (!env) {
|
|
200
|
+
const valid = doc.environments.map((e) => e.id).join(", ");
|
|
201
|
+
const hint = suggestEnv(envId, doc);
|
|
202
|
+
const suffix = hint ? ` Did you mean '${hint}'?` : "";
|
|
203
|
+
throw new NonRetryableError(
|
|
204
|
+
`Unknown environment '${envId}'. Valid: ${valid}.${suffix}`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const bulletinChain = doc.chains.find((c) => c.id === "bulletin");
|
|
208
|
+
const assetHubChain = doc.chains.find((c) => c.id === "asset-hub");
|
|
209
|
+
const bulletin = normalizeWss(bulletinChain?.endpoints?.[envId]?.wss);
|
|
210
|
+
const assetHub = normalizeWss(assetHubChain?.endpoints?.[envId]?.wss);
|
|
211
|
+
if (bulletin.length === 0) {
|
|
212
|
+
throw new NonRetryableError(
|
|
213
|
+
`Bulletin chain not yet available on environment '${envId}'. The selected environment has no bulletin endpoint in https://github.com/paritytech/triangle-status/blob/main/environments.json. Pick a testnet (paseo-next, paseo-review, preview) or wait for the mainnet rollout.`
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
if (assetHub.length === 0) {
|
|
217
|
+
throw new NonRetryableError(
|
|
218
|
+
`Asset Hub endpoint missing for environment '${envId}'. Check https://github.com/paritytech/triangle-status/blob/main/environments.json.`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
return { bulletin, assetHub, network: env.network, envName: env.name };
|
|
222
|
+
}
|
|
223
|
+
function listEnvironments(doc) {
|
|
224
|
+
const bulletinChain = doc.chains.find((c) => c.id === "bulletin");
|
|
225
|
+
return doc.environments.map((env) => {
|
|
226
|
+
const ep = bulletinChain?.endpoints?.[env.id];
|
|
227
|
+
const hasBulletin = !!ep && normalizeWss(ep.wss).length > 0;
|
|
228
|
+
return {
|
|
229
|
+
id: env.id,
|
|
230
|
+
name: env.name,
|
|
231
|
+
network: env.network,
|
|
232
|
+
hasBulletin,
|
|
233
|
+
description: env.description ?? ""
|
|
234
|
+
};
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
function formatEnvironmentTable(rows) {
|
|
238
|
+
const headers = ["ID", "Name", "Network", "Bulletin?", "Description"];
|
|
239
|
+
const data = rows.map((r) => [
|
|
240
|
+
r.id,
|
|
241
|
+
r.name,
|
|
242
|
+
r.network,
|
|
243
|
+
r.hasBulletin ? "yes" : "no",
|
|
244
|
+
r.description
|
|
245
|
+
]);
|
|
246
|
+
const widths = headers.map(
|
|
247
|
+
(h, i) => Math.max(h.length, ...data.map((row) => row[i].length))
|
|
248
|
+
);
|
|
249
|
+
const fmtRow = (row) => row.map((cell, i) => cell.padEnd(widths[i])).join(" ");
|
|
250
|
+
const sep = widths.map((w) => "-".repeat(w)).join(" ");
|
|
251
|
+
return [fmtRow(headers), sep, ...data.map(fmtRow)].join("\n");
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export {
|
|
255
|
+
DEFAULT_ENVIRONMENTS_URL,
|
|
256
|
+
DEFAULT_ENV_ID,
|
|
257
|
+
CACHE_TTL_MS,
|
|
258
|
+
FETCH_TIMEOUT_MS,
|
|
259
|
+
defaultCacheDir,
|
|
260
|
+
defaultCachePath,
|
|
261
|
+
defaultBundledPath,
|
|
262
|
+
loadEnvironments,
|
|
263
|
+
resolveEndpoints,
|
|
264
|
+
listEnvironments,
|
|
265
|
+
formatEnvironmentTable
|
|
266
|
+
};
|