bulletin-deploy 0.4.4 → 0.5.0
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 +5 -27
- package/package.json +1 -1
- package/src/deploy.js +4 -4
- package/src/dotns.js +5 -5
- package/workflows/deploy-on-pr.yml +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Deploy static sites and apps to the Polkadot Triangle network with decentralized
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install -g
|
|
8
|
+
npm install -g bulletin-deploy
|
|
9
9
|
# Build your app (e.g. npm run build)
|
|
10
10
|
bulletin-deploy ./dist my-app00.dot
|
|
11
11
|
```
|
|
@@ -31,8 +31,6 @@ ipfs init
|
|
|
31
31
|
|
|
32
32
|
## CLI Usage
|
|
33
33
|
|
|
34
|
-
### Deploy an app
|
|
35
|
-
|
|
36
34
|
```bash
|
|
37
35
|
bulletin-deploy <build-dir> <domain.dot>
|
|
38
36
|
```
|
|
@@ -43,9 +41,6 @@ Examples:
|
|
|
43
41
|
# Basic deploy
|
|
44
42
|
bulletin-deploy ./dist my-app00.dot
|
|
45
43
|
|
|
46
|
-
# With DotNS owner mnemonic
|
|
47
|
-
MNEMONIC="word1 word2 ..." bulletin-deploy ./dist my-app00.dot
|
|
48
|
-
|
|
49
44
|
# Custom RPC endpoint
|
|
50
45
|
bulletin-deploy --rpc wss://custom-bulletin.example.com ./dist my-app00.dot
|
|
51
46
|
```
|
|
@@ -54,7 +49,6 @@ bulletin-deploy --rpc wss://custom-bulletin.example.com ./dist my-app00.dot
|
|
|
54
49
|
|
|
55
50
|
```
|
|
56
51
|
Options:
|
|
57
|
-
--mnemonic "..." DotNS owner mnemonic (or set MNEMONIC env var)
|
|
58
52
|
--rpc wss://... Bulletin RPC (or set BULLETIN_RPC env var)
|
|
59
53
|
--help Show help
|
|
60
54
|
```
|
|
@@ -62,9 +56,8 @@ Options:
|
|
|
62
56
|
## GitHub Actions
|
|
63
57
|
|
|
64
58
|
1. Copy `workflows/deploy-on-pr.yml` to your repo's `.github/workflows/` directory
|
|
65
|
-
2.
|
|
66
|
-
3.
|
|
67
|
-
4. Push and watch the deploy
|
|
59
|
+
2. Customize the **Build** step for your framework (Vite, Next.js, etc.)
|
|
60
|
+
3. Push and watch the deploy
|
|
68
61
|
|
|
69
62
|
The template workflow:
|
|
70
63
|
- Deploys on push to main and on PRs
|
|
@@ -75,9 +68,8 @@ The template workflow:
|
|
|
75
68
|
## Programmatic API
|
|
76
69
|
|
|
77
70
|
```javascript
|
|
78
|
-
import { deploy, DotNS } from "
|
|
71
|
+
import { deploy, DotNS } from "bulletin-deploy";
|
|
79
72
|
|
|
80
|
-
// Deploy a directory
|
|
81
73
|
const result = await deploy("./dist", "my-app00.dot");
|
|
82
74
|
console.log(result.cid, result.domainName);
|
|
83
75
|
```
|
|
@@ -87,12 +79,8 @@ console.log(result.cid, result.domainName);
|
|
|
87
79
|
| Variable | Default | Description |
|
|
88
80
|
|---|---|---|
|
|
89
81
|
| `BULLETIN_RPC` | `wss://paseo-bulletin-rpc.polkadot.io` | Bulletin chain WebSocket RPC |
|
|
90
|
-
| `BULLETIN_POOL_SIZE` | `10` | Number of pool accounts to derive |
|
|
91
|
-
| `BULLETIN_POOL_MNEMONIC` | Dev phrase (Alice) | Mnemonic for pool account derivation |
|
|
92
|
-
| `MNEMONIC` | Dev phrase | DotNS domain owner mnemonic |
|
|
93
82
|
| `BULLETIN_DEPLOY_TELEMETRY` | `1` (enabled) | Set to `0` to disable Sentry telemetry |
|
|
94
83
|
| `IPFS_CID` | _(none)_ | Skip storage, use pre-existing CID |
|
|
95
|
-
| `GITHUB_OUTPUT` | _(none)_ | GitHub Actions output file (set automatically in CI) |
|
|
96
84
|
|
|
97
85
|
## How It Works
|
|
98
86
|
|
|
@@ -125,18 +113,15 @@ When a pool account's authorization drops below thresholds (50 transactions or 5
|
|
|
125
113
|
|
|
126
114
|
## Telemetry
|
|
127
115
|
|
|
128
|
-
Sentry telemetry is enabled by default for deploy observability.
|
|
116
|
+
Sentry telemetry is enabled by default for deploy observability. Set `BULLETIN_DEPLOY_TELEMETRY=0` to disable.
|
|
129
117
|
|
|
130
118
|
What's tracked:
|
|
131
119
|
- Deploy duration and success/failure
|
|
132
120
|
- Storage phase timing (merkleize, chunk upload, root node)
|
|
133
121
|
- DotNS phase timing (registration, contenthash update)
|
|
134
122
|
- Pool account selection
|
|
135
|
-
- Chunk retry counts
|
|
136
123
|
- Source metadata (repo, branch, PR number, CI vs local)
|
|
137
124
|
|
|
138
|
-
Telemetry is enabled by default. Set `BULLETIN_DEPLOY_TELEMETRY=0` to disable.
|
|
139
|
-
|
|
140
125
|
Dashboard: https://polkadot-community-foundation.sentry.io/dashboards/92523/
|
|
141
126
|
|
|
142
127
|
## Troubleshooting
|
|
@@ -148,7 +133,6 @@ Dashboard: https://polkadot-community-foundation.sentry.io/dashboards/92523/
|
|
|
148
133
|
| `IPFS CLI not installed` | Install Kubo: `brew install ipfs && ipfs init` |
|
|
149
134
|
| `CommitmentNotFound` | DotNS timing issue during registration. Retry the deploy. |
|
|
150
135
|
| `All pool accounts exhausted` | Auto-authorization will top up the best available account |
|
|
151
|
-
| `File exceeds 8MB limit` | File is automatically chunked. This shouldn't appear for directories. |
|
|
152
136
|
| `fetchNonce timed out` | Bulletin RPC may be down. Check endpoint or try a different one. |
|
|
153
137
|
|
|
154
138
|
## Configuration for Different Chains
|
|
@@ -160,11 +144,5 @@ By default, bulletin-deploy targets the **Paseo testnet**:
|
|
|
160
144
|
To point at a different chain, set the `BULLETIN_RPC` environment variable:
|
|
161
145
|
|
|
162
146
|
```bash
|
|
163
|
-
# Local development
|
|
164
|
-
BULLETIN_RPC=ws://127.0.0.1:9944 bulletin-deploy ./dist my-app00.dot
|
|
165
|
-
|
|
166
|
-
# Custom endpoint
|
|
167
147
|
BULLETIN_RPC=wss://your-bulletin-rpc.example.com bulletin-deploy ./dist my-app00.dot
|
|
168
148
|
```
|
|
169
|
-
|
|
170
|
-
The Asset Hub RPC endpoints are configured in `src/dotns.js` and support automatic failover across multiple providers.
|
package/package.json
CHANGED
package/src/deploy.js
CHANGED
|
@@ -268,12 +268,12 @@ export async function merkleize(directoryPath, outputCarPath) {
|
|
|
268
268
|
|
|
269
269
|
export async function storeDirectory(directoryPath) {
|
|
270
270
|
const carPath = path.join(path.dirname(directoryPath), `${path.basename(directoryPath)}.car`);
|
|
271
|
-
const { cid: ipfsCid } = await withSpan("deploy.merkleize", "merkleize", { "deploy.directory": directoryPath }, async () => {
|
|
271
|
+
const { cid: ipfsCid } = await withSpan("deploy.merkleize", "1a. merkleize", { "deploy.directory": directoryPath }, async () => {
|
|
272
272
|
return merkleize(directoryPath, carPath);
|
|
273
273
|
});
|
|
274
274
|
const carBuffer = fs.readFileSync(carPath);
|
|
275
275
|
const carChunks = chunk(carBuffer, CHUNK_SIZE);
|
|
276
|
-
const storageCid = await withSpan("deploy.chunk-upload", "chunk-upload", { "deploy.chunks.total": carChunks.length, "deploy.car.bytes": carBuffer.length }, async () => {
|
|
276
|
+
const storageCid = await withSpan("deploy.chunk-upload", "1b. chunk-upload", { "deploy.chunks.total": carChunks.length, "deploy.car.bytes": carBuffer.length }, async () => {
|
|
277
277
|
return storeChunkedContent(carChunks);
|
|
278
278
|
});
|
|
279
279
|
return { storageCid, ipfsCid };
|
|
@@ -296,7 +296,7 @@ export async function deploy(content, domainName = null) {
|
|
|
296
296
|
console.log("Storage");
|
|
297
297
|
console.log("=".repeat(60));
|
|
298
298
|
|
|
299
|
-
await withSpan("deploy.storage", "storage", {}, async () => {
|
|
299
|
+
await withSpan("deploy.storage", "1. storage", {}, async () => {
|
|
300
300
|
if (process.env.IPFS_CID) {
|
|
301
301
|
cid = process.env.IPFS_CID;
|
|
302
302
|
ipfsCid = cid;
|
|
@@ -344,7 +344,7 @@ export async function deploy(content, domainName = null) {
|
|
|
344
344
|
console.log("DotNS");
|
|
345
345
|
console.log("=".repeat(60));
|
|
346
346
|
|
|
347
|
-
await withSpan("deploy.dotns", "dotns", { "deploy.domain": name }, async () => {
|
|
347
|
+
await withSpan("deploy.dotns", "2. dotns", { "deploy.domain": name }, async () => {
|
|
348
348
|
const dotns = new DotNS();
|
|
349
349
|
await dotns.connect();
|
|
350
350
|
const { owned, owner } = await dotns.checkOwnership(name);
|
package/src/dotns.js
CHANGED
|
@@ -492,7 +492,7 @@ export class DotNS {
|
|
|
492
492
|
}
|
|
493
493
|
|
|
494
494
|
async setContenthash(domainName, contenthashHex) {
|
|
495
|
-
return withSpan("deploy.dotns.set-contenthash", "set-contenthash", {}, async () => {
|
|
495
|
+
return withSpan("deploy.dotns.set-contenthash", "2b. set-contenthash", {}, async () => {
|
|
496
496
|
this.ensureConnected();
|
|
497
497
|
const node = namehash(`${domainName}.dot`);
|
|
498
498
|
let ipfsCid = null;
|
|
@@ -512,7 +512,7 @@ export class DotNS {
|
|
|
512
512
|
}
|
|
513
513
|
|
|
514
514
|
async register(label, options = {}) {
|
|
515
|
-
return withSpan("deploy.dotns.register", `register ${label}.dot`, {}, async () => {
|
|
515
|
+
return withSpan("deploy.dotns.register", `2a. register ${label}.dot`, {}, async () => {
|
|
516
516
|
const status = parseProofOfPersonhoodStatus(options.status || process.env.DOTNS_STATUS);
|
|
517
517
|
const reverse = options.reverse ?? (process.env.DOTNS_REVERSE ?? "false").toLowerCase() === "true";
|
|
518
518
|
if (!this.connected) await this.connect(options);
|
|
@@ -523,10 +523,10 @@ export class DotNS {
|
|
|
523
523
|
this.setUserPopStatus(status),
|
|
524
524
|
]);
|
|
525
525
|
const { commitment, registration } = await this.generateCommitment(label, reverse);
|
|
526
|
-
await withSpan("deploy.dotns.submit-commitment", "submit-commitment", {}, () => this.submitCommitment(commitment));
|
|
527
|
-
await withSpan("deploy.dotns.wait-commitment-age", "wait-commitment-age", {}, () => this.waitForCommitmentAge());
|
|
526
|
+
await withSpan("deploy.dotns.submit-commitment", "2a-i. submit-commitment", {}, () => this.submitCommitment(commitment));
|
|
527
|
+
await withSpan("deploy.dotns.wait-commitment-age", "2a-ii. wait-commitment-age", {}, () => this.waitForCommitmentAge());
|
|
528
528
|
const pricing = await this.getPriceAndValidate(label);
|
|
529
|
-
await withSpan("deploy.dotns.finalize-registration", "finalize-registration", {}, () => this.finalizeRegistration(registration, pricing.priceWei));
|
|
529
|
+
await withSpan("deploy.dotns.finalize-registration", "2a-iii. finalize-registration", {}, () => this.finalizeRegistration(registration, pricing.priceWei));
|
|
530
530
|
await this.verifyOwnership(label);
|
|
531
531
|
console.log(`\n Registration complete!`);
|
|
532
532
|
return { label, owner: this.evmAddress };
|