@ar.io/deploy 0.1.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.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +695 -0
  3. package/bin/dev.js +5 -0
  4. package/bin/run.js +5 -0
  5. package/dist/chunks/cache-C1tEeUx2.js +6 -0
  6. package/dist/chunks/cache-C1tEeUx2.js.map +1 -0
  7. package/dist/chunks/display-DRcjDj9k.js +104 -0
  8. package/dist/chunks/display-DRcjDj9k.js.map +1 -0
  9. package/dist/chunks/upload-workflow-DSS5FIa5.js +204 -0
  10. package/dist/chunks/upload-workflow-DSS5FIa5.js.map +1 -0
  11. package/dist/chunks/uploader-B2tC-1Qw.js +472 -0
  12. package/dist/chunks/uploader-B2tC-1Qw.js.map +1 -0
  13. package/dist/commands/deploy.js +187 -0
  14. package/dist/commands/deploy.js.map +1 -0
  15. package/dist/commands/upload.js +122 -0
  16. package/dist/commands/upload.js.map +1 -0
  17. package/dist/constants/flags.js +241 -0
  18. package/dist/constants/flags.js.map +1 -0
  19. package/dist/index.js +2 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/prompts/arns.js +80 -0
  22. package/dist/prompts/arns.js.map +1 -0
  23. package/dist/prompts/deployment.js +27 -0
  24. package/dist/prompts/deployment.js.map +1 -0
  25. package/dist/prompts/wallet.js +52 -0
  26. package/dist/prompts/wallet.js.map +1 -0
  27. package/dist/src/commands/deploy.d.ts +9 -0
  28. package/dist/src/commands/deploy.d.ts.map +1 -0
  29. package/dist/src/commands/upload.d.ts +9 -0
  30. package/dist/src/commands/upload.d.ts.map +1 -0
  31. package/dist/src/constants/cache.d.ts +4 -0
  32. package/dist/src/constants/cache.d.ts.map +1 -0
  33. package/dist/src/constants/flags.d.ts +122 -0
  34. package/dist/src/constants/flags.d.ts.map +1 -0
  35. package/dist/src/index.d.ts +2 -0
  36. package/dist/src/index.d.ts.map +1 -0
  37. package/dist/src/prompts/arns.d.ts +13 -0
  38. package/dist/src/prompts/arns.d.ts.map +1 -0
  39. package/dist/src/prompts/deployment.d.ts +6 -0
  40. package/dist/src/prompts/deployment.d.ts.map +1 -0
  41. package/dist/src/prompts/wallet.d.ts +11 -0
  42. package/dist/src/prompts/wallet.d.ts.map +1 -0
  43. package/dist/src/types/index.d.ts +31 -0
  44. package/dist/src/types/index.d.ts.map +1 -0
  45. package/dist/src/utils/__tests__/cache.test.d.ts +2 -0
  46. package/dist/src/utils/__tests__/cache.test.d.ts.map +1 -0
  47. package/dist/src/utils/__tests__/constants.test.d.ts +2 -0
  48. package/dist/src/utils/__tests__/constants.test.d.ts.map +1 -0
  49. package/dist/src/utils/__tests__/display.test.d.ts +2 -0
  50. package/dist/src/utils/__tests__/display.test.d.ts.map +1 -0
  51. package/dist/src/utils/cache.d.ts +48 -0
  52. package/dist/src/utils/cache.d.ts.map +1 -0
  53. package/dist/src/utils/chalk.d.ts +9 -0
  54. package/dist/src/utils/chalk.d.ts.map +1 -0
  55. package/dist/src/utils/config-resolver.d.ts +72 -0
  56. package/dist/src/utils/config-resolver.d.ts.map +1 -0
  57. package/dist/src/utils/constants.d.ts +4 -0
  58. package/dist/src/utils/constants.d.ts.map +1 -0
  59. package/dist/src/utils/deploy-key.d.ts +15 -0
  60. package/dist/src/utils/deploy-key.d.ts.map +1 -0
  61. package/dist/src/utils/display.d.ts +7 -0
  62. package/dist/src/utils/display.d.ts.map +1 -0
  63. package/dist/src/utils/path.d.ts +5 -0
  64. package/dist/src/utils/path.d.ts.map +1 -0
  65. package/dist/src/utils/signer.d.ts +19 -0
  66. package/dist/src/utils/signer.d.ts.map +1 -0
  67. package/dist/src/utils/solana.d.ts +29 -0
  68. package/dist/src/utils/solana.d.ts.map +1 -0
  69. package/dist/src/utils/upload-types.d.ts +35 -0
  70. package/dist/src/utils/upload-types.d.ts.map +1 -0
  71. package/dist/src/utils/uploader.d.ts +50 -0
  72. package/dist/src/utils/uploader.d.ts.map +1 -0
  73. package/dist/src/utils/validators.d.ts +21 -0
  74. package/dist/src/utils/validators.d.ts.map +1 -0
  75. package/dist/src/workflows/upload-workflow.d.ts +28 -0
  76. package/dist/src/workflows/upload-workflow.d.ts.map +1 -0
  77. package/dist/tests/constants.d.ts +11 -0
  78. package/dist/tests/constants.d.ts.map +1 -0
  79. package/dist/tests/e2e/deploy-command.test.d.ts +2 -0
  80. package/dist/tests/e2e/deploy-command.test.d.ts.map +1 -0
  81. package/dist/tests/global-setup.d.ts +6 -0
  82. package/dist/tests/global-setup.d.ts.map +1 -0
  83. package/dist/tests/mocks/turbo-handlers.d.ts +106 -0
  84. package/dist/tests/mocks/turbo-handlers.d.ts.map +1 -0
  85. package/dist/tests/setup.d.ts +11 -0
  86. package/dist/tests/setup.d.ts.map +1 -0
  87. package/dist/tests/types/payment-service.d.ts +218 -0
  88. package/dist/tests/types/payment-service.d.ts.map +1 -0
  89. package/dist/tests/types/upload-service.d.ts +168 -0
  90. package/dist/tests/types/upload-service.d.ts.map +1 -0
  91. package/dist/tests/unit/deploy-key.test.d.ts +2 -0
  92. package/dist/tests/unit/deploy-key.test.d.ts.map +1 -0
  93. package/dist/tests/unit/signer.test.d.ts +2 -0
  94. package/dist/tests/unit/signer.test.d.ts.map +1 -0
  95. package/dist/tests/unit/solana.test.d.ts +2 -0
  96. package/dist/tests/unit/solana.test.d.ts.map +1 -0
  97. package/dist/tests/unit/uploader-tags.test.d.ts +2 -0
  98. package/dist/tests/unit/uploader-tags.test.d.ts.map +1 -0
  99. package/dist/tests/unit/validators.test.d.ts +2 -0
  100. package/dist/tests/unit/validators.test.d.ts.map +1 -0
  101. package/dist/types/index.js +2 -0
  102. package/dist/types/index.js.map +1 -0
  103. package/dist/utils/config-resolver.js +39 -0
  104. package/dist/utils/config-resolver.js.map +1 -0
  105. package/dist/utils/constants.js +6 -0
  106. package/dist/utils/constants.js.map +1 -0
  107. package/dist/utils/path.js +15 -0
  108. package/dist/utils/path.js.map +1 -0
  109. package/dist/utils/signer.js +45 -0
  110. package/dist/utils/signer.js.map +1 -0
  111. package/dist/utils/uploader.js +5 -0
  112. package/dist/utils/uploader.js.map +1 -0
  113. package/dist/utils/validators.js +43 -0
  114. package/dist/utils/validators.js.map +1 -0
  115. package/dist/workflows/upload-workflow.js +9 -0
  116. package/dist/workflows/upload-workflow.js.map +1 -0
  117. package/package.json +116 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Permanent Data Solutions, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,695 @@
1
+ # ARIO Deploy
2
+
3
+ `ario-deploy` is a Node.js command-line tool designed to streamline the deployment of web applications to the permaweb using Arweave. It uploads your build folder or a single file, creates Arweave manifests, and can optionally update ArNS (Ar.io Name System) records via ANT (Ar.io Name Token) with the transaction ID.
4
+
5
+ ## Table of Contents
6
+
7
+ <!-- toc -->
8
+
9
+ - [Table of Contents](#table-of-contents)
10
+ - [Features](#features)
11
+ - [Installation](#installation)
12
+ - [Prerequisites](#prerequisites)
13
+ - [Commands](#commands)
14
+ - [On-Demand Payment](#on-demand-payment)
15
+ - [Bundler service](#bundler-service)
16
+ - [Command Options](#command-options)
17
+ - [Deduplication](#deduplication)
18
+ - [Package.json Scripts](#packagejson-scripts)
19
+ - [GitHub Action](#github-action)
20
+ - [CLI in GitHub Actions](#cli-in-github-actions)
21
+ - [Development](#development)
22
+ - [Security & Best Practices](#security--best-practices)
23
+ - [Troubleshooting](#troubleshooting)
24
+ - [Contributing](#contributing)
25
+ - [Dependencies](#dependencies)
26
+ - [License](#license)
27
+ - [Resources](#resources)
28
+
29
+ <!-- tocstop -->
30
+
31
+ ## Features
32
+
33
+ - **Turbo SDK Integration:** Uses Turbo SDK for fast, reliable file uploads to Arweave
34
+ - **On-Demand Payment:** Pay with ARIO or Base-ETH tokens on-demand during upload
35
+ - **Arweave Manifest v0.2.0:** Creates manifests with fallback support for SPAs
36
+ - **Optional ArNS Updates:** Updates ArNS records via ANT with new transaction IDs
37
+ - **Automated Workflow:** Integrates with GitHub Actions for continuous deployment
38
+ - **Git Hash Tagging:** In CI (GitHub Actions), tags uploaded data items with the deploying commit SHA
39
+ - **404 Fallback Detection:** Automatically detects and sets 404.html as fallback
40
+ - **Network Support:** ArNS updates run against the Solana ARIO programs on `mainnet` or `devnet`, with an optional custom RPC URL
41
+ - **Flexible Deployment:** Supports deploying a folder or a single file
42
+ - **Modern CLI:** Built with oclif for a robust command-line experience
43
+ - **TypeScript:** Fully typed for better developer experience
44
+
45
+ ## Installation
46
+
47
+ Install the package using pnpm (recommended):
48
+
49
+ ```bash
50
+ pnpm add -D @ar.io/deploy
51
+ ```
52
+
53
+ Or with npm:
54
+
55
+ ```bash
56
+ npm install --save-dev @ar.io/deploy
57
+ ```
58
+
59
+ Or with yarn:
60
+
61
+ ```bash
62
+ yarn add --dev @ar.io/deploy
63
+ ```
64
+
65
+ ## Prerequisites
66
+
67
+ 1. **For Arweave signer (default):** Encode your Arweave wallet key in base64 format and set it as a GitHub secret:
68
+
69
+ ```bash
70
+ base64 -i wallet.json | pbcopy
71
+ ```
72
+
73
+ 2. **For Ethereum/Polygon/KYVE signers:** Use your raw private key (no encoding needed) as the `DEPLOY_KEY`.
74
+ 3. **For Solana signers:** Use a base58-encoded secret key (the "export private key" format) as the `DEPLOY_KEY`, or a `solana-keygen` `id.json` byte-array wallet file via `--wallet`.
75
+ 4. Ensure that the secret name for the encoded wallet or private key is `DEPLOY_KEY`.
76
+
77
+ ⚠️ **Important:** Use a dedicated wallet for deployments to minimize security risks. Ensure your wallet has sufficient Turbo Credits for uploads.
78
+
79
+ > **ArNS updates require a Solana signer.** ArNS/ANT records now live on Solana programs, so any deployment that updates ArNS (`--use-arns` / `--arns-name`) must use `--sig-type solana`. Uploads alone can use any supported signer.
80
+
81
+ ## Commands
82
+
83
+ ### Interactive Mode (Easiest)
84
+
85
+ **Command Menu:**
86
+
87
+ Simply run the CLI for an interactive command selector:
88
+
89
+ ```bash
90
+ ario-deploy
91
+ # or explicitly
92
+ ario-deploy interactive
93
+ ```
94
+
95
+ This shows a menu with options:
96
+
97
+ - **Deploy to Permaweb** - Start the deployment wizard
98
+ - **Show Help** - Display help information
99
+ - **Exit** - Exit the CLI
100
+
101
+ **Interactive Deploy (Guided):**
102
+
103
+ Run the deploy command without arguments to be guided through all deployment options:
104
+
105
+ ```bash
106
+ ario-deploy deploy
107
+ ```
108
+
109
+ This uploads to the permaweb by default. Use `--use-arns` or `--arns-name` to run the guided ArNS update flow, which will prompt you for:
110
+
111
+ - ArNS name
112
+ - Wallet method (file, string, or environment variable)
113
+ - Signer type (Arweave, Ethereum, Polygon, KYVE, Solana)
114
+ - What to deploy (folder or file)
115
+ - Advanced options (optional: undername, TTL, Solana cluster)
116
+
117
+ ### Direct Commands
118
+
119
+ Use flags for faster, scriptable deployments:
120
+
121
+ ```bash
122
+ # Basic deployment with wallet file
123
+ ario-deploy deploy --wallet ./wallet.json
124
+
125
+ # Deployment with ArNS update (ArNS requires a Solana signer)
126
+ ario-deploy deploy --use-arns --arns-name my-app --sig-type solana --wallet ./id.json
127
+ ```
128
+
129
+ Deploy using private key directly:
130
+
131
+ ```bash
132
+ ario-deploy deploy --private-key "$(cat wallet.json)"
133
+ ```
134
+
135
+ Deploy using environment variable:
136
+
137
+ ```bash
138
+ DEPLOY_KEY=$(base64 -i wallet.json) ario-deploy deploy --deploy-folder ./dist
139
+ ```
140
+
141
+ Deploy a specific folder:
142
+
143
+ ```bash
144
+ ario-deploy deploy --wallet ./wallet.json --deploy-folder ./build
145
+ ```
146
+
147
+ Deploy a single file:
148
+
149
+ ```bash
150
+ ario-deploy deploy --wallet ./wallet.json --deploy-file ./path/to/file.txt
151
+ ```
152
+
153
+ ### Upload/deploy without ArNS
154
+
155
+ `deploy` uploads without updating ArNS by default. You can also use the `upload` command explicitly for the same Turbo upload, dedupe cache, and payment options as deploy, minus ArNS flags:
156
+
157
+ ```bash
158
+ ario-deploy deploy --wallet ./wallet.json --deploy-folder ./dist
159
+ ario-deploy upload --wallet ./wallet.json --deploy-folder ./dist
160
+ ario-deploy upload --wallet ./wallet.json --deploy-file ./dist/index.html
161
+ DEPLOY_KEY=$(base64 -i wallet.json) ario-deploy upload --deploy-folder ./dist
162
+ ```
163
+
164
+ ### Advanced Usage
165
+
166
+ Deploy to an undername (subdomain) — ArNS, so a Solana signer is required:
167
+
168
+ ```bash
169
+ ario-deploy deploy --use-arns --arns-name my-app --sig-type solana --wallet ./id.json --undername staging
170
+ ```
171
+
172
+ Deploy with a custom TTL:
173
+
174
+ ```bash
175
+ ario-deploy deploy --use-arns --arns-name my-app --sig-type solana --wallet ./id.json --ttl-seconds 7200
176
+ ```
177
+
178
+ Update ArNS on devnet (or against a custom RPC):
179
+
180
+ ```bash
181
+ ario-deploy deploy --use-arns --arns-name my-app --sig-type solana --wallet ./id.json --cluster devnet
182
+ ario-deploy deploy --use-arns --arns-name my-app --sig-type solana --wallet ./id.json --rpc-url https://my-rpc.example.com
183
+ ```
184
+
185
+ Upload using an Ethereum wallet (file):
186
+
187
+ ```bash
188
+ ario-deploy deploy --sig-type ethereum --wallet ./private-key.txt
189
+ ```
190
+
191
+ Upload using a Solana wallet (base58 private key):
192
+
193
+ ```bash
194
+ ario-deploy deploy --sig-type solana --private-key "<base58-secret-key>"
195
+ ```
196
+
197
+ ## On-Demand Payment
198
+
199
+ Use on-demand payment to automatically fund uploads with ARIO or Base-ETH tokens when your Turbo balance is insufficient:
200
+
201
+ Deploy with ARIO on-demand payment:
202
+
203
+ ```bash
204
+ ario-deploy deploy --wallet ./wallet.json --deploy-folder ./dist --on-demand ario --max-token-amount 1.5
205
+ ```
206
+
207
+ Deploy with Base-ETH on-demand payment (using Ethereum signer):
208
+
209
+ ```bash
210
+ ario-deploy deploy --sig-type ethereum --private-key "0x..." --on-demand base-eth --max-token-amount 0.1
211
+ ```
212
+
213
+ **On-Demand Payment Options:**
214
+
215
+ - `--on-demand`: Token to use for on-demand payment (`ario` or `base-eth`)
216
+ - `--max-token-amount`: Maximum token amount to spend (in native token units, e.g., `1.5` for 1.5 ARIO or `0.1` for 0.1 ETH)
217
+
218
+ **How it works:**
219
+
220
+ 1. Checks your Turbo balance before upload
221
+ 2. If balance is insufficient, converts tokens to Turbo credits on-demand
222
+ 3. Automatically adds a 10% buffer (`topUpBufferMultiplier: 1.1`) for reliability
223
+ 4. Proceeds with upload once funded
224
+
225
+ **Token compatibility:**
226
+
227
+ - **ARIO**: Works with Arweave signer
228
+ - **Base-ETH**: Works with Ethereum signer (Base Network)
229
+
230
+ ## Bundler service
231
+
232
+ Uploads go through a bundler service that accepts signed data items and posts them to Arweave. By default, ario-deploy uses the [Turbo](https://docs.ardrive.io/docs/turbo/) API and ArDrive’s production bundler (`https://upload.ardrive.io`). **`--uploader`** sets the **base URL** of the bundler service to use (scheme + host; typically no path).
233
+
234
+ | When to use | Example value |
235
+ | ------------------------- | ------------------------------------------------------- |
236
+ | **Default** (omit flag) | ArDrive production bundler — same as Turbo CLI defaults |
237
+ | **Arweave bundler** | `https://turbo.ardrive.io` |
238
+ | **Development / staging** | `https://upload.ardrive.dev` |
239
+ | **Custom or self-hosted** | Your own base URL if it implements the Turbo API |
240
+
241
+ **Examples:**
242
+
243
+ ```bash
244
+ # Deploy using Arweave’s bundler service
245
+ ario-deploy deploy --wallet ./wallet.json --deploy-folder ./dist --uploader https://turbo.ardrive.io
246
+
247
+ ario-deploy upload --wallet ./wallet.json --deploy-folder ./dist --uploader https://turbo.ardrive.io
248
+ ```
249
+
250
+ **Notes:**
251
+
252
+ - Turbo billing and signer behavior follow Turbo.
253
+ - Use a **base URL only** (e.g. `https://turbo.ardrive.io`), not a path to a specific file or route.
254
+
255
+ ## Command Options
256
+
257
+ **`deploy`** (upload by default, optional ArNS update):
258
+
259
+ - `--use-arns`: Update an ArNS/ANT record after upload. **Requires `--sig-type solana`.**
260
+ - `--arns-name, -n`: The ArNS name to update. Required when using `--use-arns`; also implies ArNS mode for backwards compatibility.
261
+ - `--cluster, -p`: Solana cluster for ArNS updates. Choices: `mainnet`, `devnet`. Default: `mainnet`
262
+ - `--rpc-url`: Optional Solana RPC URL override for ArNS updates
263
+ - `--deploy-folder, -d`: Folder to deploy. Default: `./dist`
264
+ - `--deploy-file, -f`: Deploy a single file instead of a folder
265
+ - `--undername, -u`: ANT undername to update. Default: `@`
266
+ - `--ttl-seconds, -t`: TTL in seconds for the ANT record (60-86400). Default: `60`
267
+ - `--sig-type, -s`: Signer type for deployment. Choices: `arweave`, `ethereum`, `polygon`, `kyve`, `solana`. Default: `arweave`
268
+ - `--wallet, -w`: Path to wallet file (JWK for Arweave, private key for Ethereum/Polygon/KYVE, `solana-keygen` `id.json` for Solana)
269
+ - `--private-key, -k`: Private key string (alternative to `--wallet`). JWK JSON for Arweave, hex for EVM chains, base58 secret key for Solana
270
+ - `--on-demand`: Enable on-demand payment with specified token. Choices: `ario`, `base-eth`
271
+ - `--max-token-amount`: Maximum token amount for on-demand payment (used with `--on-demand`)
272
+ - `--no-dedupe`: Disable deduplication (do not cache or reuse previous uploads)
273
+ - `--dedupe-cache-max-entries`: Maximum number of entries to keep in the dedupe cache (LRU). Default: `10000`
274
+ - `--uploader`: Custom Turbo upload service base URL. See the **Bundler service** section.
275
+
276
+ **`upload`** (explicit upload without ArNS): accepts `--deploy-folder`, `--deploy-file`, wallet/signer flags, `--uploader`, `--on-demand` / `--max-token-amount`, and dedupe flags only.
277
+
278
+ ## Deduplication
279
+
280
+ By default, ario-deploy caches your deployment log to prevent uploading duplicate (unchanged) files. This saves both time and upload costs by reusing existing data on Arweave.
281
+
282
+ **How it works:**
283
+
284
+ 1. When you deploy, ario-deploy hashes each file in your build
285
+ 2. It checks the local cache for matching hashes from previous uploads
286
+ 3. Files that haven't changed are skipped - the existing transaction ID is reused
287
+ 4. Only new or modified files are uploaded to Arweave
288
+ 5. The cache is stored locally in `.ario-deploy/transaction-cache.json`
289
+
290
+ **Disable deduplication:**
291
+
292
+ If you need to force a fresh upload of all files (e.g., for debugging or to ensure a completely new deployment):
293
+
294
+ ```bash
295
+ ario-deploy deploy --wallet ./wallet.json --no-dedupe
296
+ ```
297
+
298
+ **Limit cache size:**
299
+
300
+ The dedupe cache uses an LRU (Least Recently Used) eviction strategy. By default, it keeps up to 10,000 entries. You can adjust this limit:
301
+
302
+ ```bash
303
+ # Keep only the last 1000 file entries
304
+ ario-deploy deploy --wallet ./wallet.json --dedupe-cache-max-entries 1000
305
+ ```
306
+
307
+ **Cache location:**
308
+
309
+ The cache file is stored at `.ario-deploy/transaction-cache.json` in your project root. You can:
310
+
311
+ - Add it to `.gitignore` if you don't want to share cache across team members
312
+ - Commit it to share cached transaction IDs with your team (reduces duplicate uploads)
313
+ - Delete it to start fresh: `rm -rf .ario-deploy/`
314
+
315
+ ## Package.json Scripts
316
+
317
+ Add deployment scripts to your `package.json`:
318
+
319
+ ```json
320
+ {
321
+ "scripts": {
322
+ "build": "vite build",
323
+ "deploy": "pnpm build && ario-deploy deploy --arns-name <ARNS_NAME> --sig-type solana",
324
+ "deploy:staging": "pnpm build && ario-deploy deploy --arns-name <ARNS_NAME> --sig-type solana --undername staging",
325
+ "deploy:devnet": "pnpm build && ario-deploy deploy --arns-name <ARNS_NAME> --sig-type solana --cluster devnet",
326
+ "deploy:on-demand": "pnpm build && ario-deploy deploy --arns-name <ARNS_NAME> --sig-type solana --on-demand ario --max-token-amount 1.5"
327
+ }
328
+ }
329
+ ```
330
+
331
+ Then deploy with:
332
+
333
+ ```bash
334
+ DEPLOY_KEY=$(base64 -i wallet.json) pnpm deploy
335
+ ```
336
+
337
+ Or with on-demand payment:
338
+
339
+ ```bash
340
+ DEPLOY_KEY=$(base64 -i wallet.json) pnpm deploy:on-demand
341
+ ```
342
+
343
+ ## GitHub Action
344
+
345
+ The easiest way to integrate ario-deploy into your CI/CD pipeline is using our official GitHub Action.
346
+
347
+ ### Basic Usage
348
+
349
+ ```yaml
350
+ - uses: ar-io/ar-io-deploy@v1
351
+ with:
352
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
353
+ arns-name: myapp
354
+ deploy-folder: ./dist
355
+ sig-type: solana # ArNS updates require a Solana signer
356
+ ```
357
+
358
+ ### PR Preview Deployments
359
+
360
+ Automatically deploy preview builds for each pull request. The `preview` mode auto-generates an undername from the PR number and posts a comment with the preview URL:
361
+
362
+ ```yaml
363
+ name: Deploy PR Preview
364
+
365
+ on:
366
+ pull_request:
367
+ types: [opened, synchronize]
368
+
369
+ jobs:
370
+ deploy-preview:
371
+ runs-on: ubuntu-latest
372
+ steps:
373
+ - uses: actions/checkout@v4
374
+
375
+ - name: Setup Node.js
376
+ uses: actions/setup-node@v4
377
+ with:
378
+ node-version: '20'
379
+
380
+ - name: Install dependencies
381
+ run: npm ci
382
+
383
+ - name: Build
384
+ run: npm run build
385
+
386
+ - name: Deploy Preview
387
+ uses: ar-io/ar-io-deploy@v1
388
+ with:
389
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
390
+ arns-name: myapp
391
+ sig-type: solana
392
+ preview: 'true'
393
+ github-token: ${{ secrets.GITHUB_TOKEN }}
394
+ deploy-folder: ./dist
395
+ ```
396
+
397
+ When `preview` is enabled, the action will:
398
+
399
+ - Auto-generate an undername like `pr-123` from the PR number
400
+ - Post a comment on the PR with the preview URL
401
+ - Update the comment on subsequent pushes instead of creating new ones
402
+
403
+ ### Production Deployment
404
+
405
+ Deploy to your base ArNS name when pushing to main:
406
+
407
+ ```yaml
408
+ name: Deploy to Production
409
+
410
+ on:
411
+ push:
412
+ branches: [main]
413
+
414
+ jobs:
415
+ deploy:
416
+ runs-on: ubuntu-latest
417
+ steps:
418
+ - uses: actions/checkout@v4
419
+
420
+ - name: Setup Node.js
421
+ uses: actions/setup-node@v4
422
+ with:
423
+ node-version: '20'
424
+
425
+ - name: Install dependencies
426
+ run: npm ci
427
+
428
+ - name: Build
429
+ run: npm run build
430
+
431
+ - name: Deploy to Permaweb
432
+ uses: ar-io/ar-io-deploy@v1
433
+ with:
434
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
435
+ arns-name: myapp
436
+ sig-type: solana
437
+ deploy-folder: ./dist
438
+ ```
439
+
440
+ ### With On-Demand Payment
441
+
442
+ ```yaml
443
+ - name: Deploy with ARIO on-demand
444
+ uses: ar-io/ar-io-deploy@v1
445
+ with:
446
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
447
+ arns-name: myapp
448
+ sig-type: solana
449
+ deploy-folder: ./dist
450
+ on-demand: ario
451
+ max-token-amount: '2.0'
452
+ ```
453
+
454
+ ### Updating ArNS (Solana)
455
+
456
+ ArNS updates run against the Solana ARIO programs, so set `sig-type: solana` and provide a Solana `DEPLOY_KEY` (base58 secret key). Use `cluster` to target `mainnet` (default) or `devnet`, and `rpc-url` for a custom RPC endpoint.
457
+
458
+ ```yaml
459
+ - name: Deploy and update ArNS
460
+ uses: ar-io/ar-io-deploy@v1
461
+ with:
462
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
463
+ arns-name: myapp
464
+ deploy-folder: ./dist
465
+ sig-type: solana
466
+ cluster: mainnet
467
+ ```
468
+
469
+ ### Disabling Deduplication
470
+
471
+ By default, the action caches transaction IDs to avoid re-uploading unchanged files. To disable this:
472
+
473
+ ```yaml
474
+ - name: Deploy without dedupe
475
+ uses: ar-io/ar-io-deploy@v1
476
+ with:
477
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
478
+ deploy-folder: ./dist
479
+ no-dedupe: 'true'
480
+ ```
481
+
482
+ You can also limit the cache size:
483
+
484
+ ```yaml
485
+ - name: Deploy with limited cache
486
+ uses: ar-io/ar-io-deploy@v1
487
+ with:
488
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
489
+ deploy-folder: ./dist
490
+ dedupe-cache-max-entries: '1000'
491
+ ```
492
+
493
+ ---
494
+
495
+ ## CLI in GitHub Actions
496
+
497
+ You can also use the CLI directly in your workflows:
498
+
499
+ **Basic Workflow:**
500
+
501
+ ```yaml
502
+ name: Deploy to Permaweb
503
+
504
+ on:
505
+ push:
506
+ branches:
507
+ - main
508
+
509
+ jobs:
510
+ publish:
511
+ runs-on: ubuntu-latest
512
+ steps:
513
+ - uses: actions/checkout@v4
514
+
515
+ - uses: pnpm/action-setup@v3
516
+ with:
517
+ version: 9
518
+
519
+ - uses: actions/setup-node@v4
520
+ with:
521
+ node-version: 20
522
+ cache: 'pnpm'
523
+
524
+ - run: pnpm install
525
+
526
+ - run: pnpm deploy
527
+ env:
528
+ DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
529
+ ```
530
+
531
+ **With On-Demand Payment:**
532
+
533
+ ```yaml
534
+ name: Deploy to Permaweb with On-Demand Payment
535
+
536
+ on:
537
+ push:
538
+ branches:
539
+ - main
540
+
541
+ jobs:
542
+ publish:
543
+ runs-on: ubuntu-latest
544
+ steps:
545
+ - uses: actions/checkout@v4
546
+
547
+ - uses: pnpm/action-setup@v3
548
+ with:
549
+ version: 9
550
+
551
+ - uses: actions/setup-node@v4
552
+ with:
553
+ node-version: 20
554
+ cache: 'pnpm'
555
+
556
+ - run: pnpm install
557
+ - run: pnpm build
558
+
559
+ - name: Deploy with ARIO on-demand
560
+ run: ario-deploy deploy --arns-name my-app --sig-type solana --on-demand ario --max-token-amount 2.0
561
+ env:
562
+ DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
563
+
564
+ # Or upload with Ethereum and Base-ETH on-demand payment (upload only; ArNS requires Solana):
565
+ # - name: Upload with Base-ETH on-demand
566
+ # run: |
567
+ # ario-deploy upload \
568
+ # --sig-type ethereum \
569
+ # --on-demand base-eth \
570
+ # --max-token-amount 0.2
571
+ # env:
572
+ # DEPLOY_KEY: ${{ secrets.ETH_PRIVATE_KEY }}
573
+ ```
574
+
575
+ ## Development
576
+
577
+ ### Setup
578
+
579
+ ```bash
580
+ # Install dependencies
581
+ pnpm install
582
+
583
+ # Build the project
584
+ pnpm build
585
+
586
+ # Run in development mode
587
+ pnpm dev
588
+
589
+ # Run tests
590
+ pnpm test
591
+
592
+ # Run linter
593
+ pnpm lint
594
+
595
+ # Format code
596
+ pnpm format
597
+ ```
598
+
599
+ ### Project Structure
600
+
601
+ ```
602
+ ar-io-deploy/
603
+ ├── src/
604
+ │ ├── commands/ # oclif commands
605
+ │ │ ├── deploy.ts
606
+ │ │ └── upload.ts
607
+ │ ├── types/ # TypeScript type definitions
608
+ │ │ └── index.ts
609
+ │ ├── utils/ # Utility functions
610
+ │ │ ├── constants.ts
611
+ │ │ ├── signer.ts
612
+ │ │ ├── uploader.ts
613
+ │ │ └── __tests__/ # Unit tests
614
+ │ └── index.ts # Main entry point
615
+ ├── bin/ # Executable scripts
616
+ │ ├── run.js
617
+ │ └── dev.js
618
+ ├── .changeset/ # Changesets configuration
619
+ ├── .husky/ # Git hooks
620
+ └── dist/ # Build output
621
+ ```
622
+
623
+ ## Security & Best Practices
624
+
625
+ - **Dedicated Wallet:** Always use a dedicated wallet for deployments to minimize security risks
626
+ - **Wallet Encoding:** Arweave wallets must be base64 encoded to be used in the deployment script
627
+ - **ArNS Name:** Required only when updating an ANT/ArNS target undername or root record
628
+ - **Turbo Credits:** Ensure your wallet has sufficient Turbo Credits, or use on-demand payment for automatic funding
629
+ - **On-Demand Limits:** Set reasonable `--max-token-amount` limits to prevent unexpected costs
630
+ - **Secret Management:** Keep your `DEPLOY_KEY` secret secure and never commit it to your repository
631
+ - **Build Security:** Always check your build for exposed environmental secrets before deployment, as data on Arweave is permanent
632
+
633
+ ## Troubleshooting
634
+
635
+ - **Error: "DEPLOY_KEY environment variable not set":** Verify your base64 encoded wallet is set as the `DEPLOY_KEY` environment variable
636
+ - **Error: "deploy-folder does not exist":** Check that your build folder exists and the path is correct
637
+ - **Error: "deploy-file does not exist":** Check that your build file exists and the path is correct
638
+ - **Error: "ArNS name does not exist":** Verify the ArNS name is correct and exists in the specified network
639
+ - **Upload timeouts:** Files have a timeout for upload. Large files may fail and require optimization
640
+ - **Insufficient Turbo Credits:** Use `--on-demand` with `--max-token-amount` to automatically fund uploads when balance is low
641
+ - **On-demand payment fails:** Ensure your wallet has sufficient tokens (ARIO or Base-ETH) and the token type matches your signer (`ario` with Arweave, `base-eth` with Ethereum)
642
+
643
+ ## Contributing
644
+
645
+ Contributions are welcome! Please follow these guidelines:
646
+
647
+ 1. Fork the repository
648
+ 2. Create a feature branch
649
+ 3. Make your changes
650
+ 4. Run tests and linter: `pnpm test && pnpm lint`
651
+ 5. Create a changeset: `pnpm changeset`
652
+ 6. Commit your changes using conventional commits
653
+ 7. Push and create a pull request
654
+
655
+ ### Conventional Commits
656
+
657
+ This project uses [Conventional Commits](https://www.conventionalcommits.org/). Commit messages should follow this format:
658
+
659
+ ```
660
+ type(scope): subject
661
+
662
+ body (optional)
663
+ ```
664
+
665
+ Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`
666
+
667
+ ### Changesets
668
+
669
+ We use [changesets](https://github.com/changesets/changesets) for version management. When making changes:
670
+
671
+ ```bash
672
+ pnpm changeset
673
+ ```
674
+
675
+ Follow the prompts to describe your changes.
676
+
677
+ ## Dependencies
678
+
679
+ - **@ar.io/sdk** - For ANT operations and ArNS management on Solana
680
+ - **@ardrive/turbo-sdk** - For fast file uploads to Arweave (and signer types)
681
+ - **@solana/kit** - Solana RPC clients and transaction signers for ArNS updates
682
+ - **bs58** - Base58 encoding/decoding for Solana keys
683
+ - **@oclif/core** - CLI framework
684
+ - **mime-types** - MIME type detection
685
+
686
+ ## License
687
+
688
+ MIT — © Permanent Data Solutions, Inc.
689
+
690
+ ## Resources
691
+
692
+ - [GitHub Repository](https://github.com/ar-io/ar-io-deploy)
693
+ - [Issues](https://github.com/ar-io/ar-io-deploy/issues)
694
+ - [Arweave Documentation](https://docs.arweave.org/)
695
+ - [AR.IO Documentation](https://docs.ar.io/)