@runfile/cli 0.15.1 → 0.17.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/bin/darwin-arm64/README.md +40 -6
- package/bin/darwin-arm64/run +0 -0
- package/bin/darwin-x64/README.md +40 -6
- package/bin/darwin-x64/run +0 -0
- package/bin/linux-arm64/README.md +40 -6
- package/bin/linux-arm64/run +0 -0
- package/bin/linux-x64/README.md +40 -6
- package/bin/linux-x64/run +0 -0
- package/bin/win32-arm64/run.exe +0 -0
- package/bin/win32-x64/run.exe +0 -0
- package/package.json +1 -1
|
@@ -146,7 +146,7 @@ AES-256-GCM secrets you can commit to git. Auto-decrypted at runtime, never writ
|
|
|
146
146
|
tool, no wrapper.
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
-
$ run :env init
|
|
149
|
+
$ run :env init .env.production
|
|
150
150
|
$ run :env set .env.production DB_PASS "s3cr3t" # auto-encrypted
|
|
151
151
|
$ run :env set .env.production DB_PASS # omit value → read from stdin (no shell history, no escaping)
|
|
152
152
|
```
|
|
@@ -160,9 +160,17 @@ You can also use Runfile as a drop-in `dotenvx`/`dotenv` replacement to inject e
|
|
|
160
160
|
any command — no Runfile needed:
|
|
161
161
|
|
|
162
162
|
```bash
|
|
163
|
-
$ run :env inject -- node app.js
|
|
164
|
-
$ run :env inject
|
|
165
|
-
$ run :env inject
|
|
163
|
+
$ run :env inject .env -- node app.js # one file
|
|
164
|
+
$ run :env inject .env .env.local -- pnpm dev # multiple files, last wins; parent env always wins
|
|
165
|
+
$ run :env inject .env.production -- ./deploy.sh # encrypted values auto-decrypted
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
In CI, the file path can be supplied via `RUNFILE_ENV_FILE_TARGET` (set automatically by the
|
|
169
|
+
[setup action's `env-file-source` input](.github/actions/setup/action.yml) for open-source
|
|
170
|
+
repos that keep their encrypted `.env` in a GitHub secret):
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
$ run :env inject -- node app.js # uses $RUNFILE_ENV_FILE_TARGET
|
|
166
174
|
```
|
|
167
175
|
|
|
168
176
|
#### Powerful argument substitution
|
|
@@ -240,15 +248,17 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
240
248
|
// trim : trim, trim_start, trim_end
|
|
241
249
|
// inspect : length, starts_with, ends_with, contains
|
|
242
250
|
// transform : escape, repeat, replace_all, remove_all
|
|
243
|
-
// regex : regex_replace, regex_remove, regex_matches
|
|
251
|
+
// regex : regex_replace, regex_remove, regex_matches, regex_capture
|
|
244
252
|
// build : concat, join
|
|
245
253
|
// split : nth, first, last, count_parts
|
|
254
|
+
// math : add, subtract, multiply, divide
|
|
255
|
+
// validate : one_of
|
|
246
256
|
// encoding : base64_encode, base64_decode
|
|
247
257
|
// hashing : sha256, md5
|
|
248
258
|
// files : read_file, file_exists
|
|
249
259
|
// json : json_get, json_set
|
|
250
260
|
// error : try
|
|
251
|
-
// shell : shell_quote
|
|
261
|
+
// shell : shell_quote, capture
|
|
252
262
|
// variables : define
|
|
253
263
|
// cwd : set_cwd
|
|
254
264
|
"echo deploying-{{ to_upper(ARGS.env) }}",
|
|
@@ -259,6 +269,10 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
259
269
|
"go test {{ replace_all(ARGS.flags, ' ', ' -tag=') }}",
|
|
260
270
|
// Strip every match of a regex (here: collapse whitespace runs to a single space):
|
|
261
271
|
"echo {{ regex_replace(ARGS.text, '\\s+', ' ') }}",
|
|
272
|
+
// Pull a capture group out of the first regex match — no `(?s)^.*X(...)X.*$`
|
|
273
|
+
// greedy-replace trick needed. Group 0 is the whole match; group N is the
|
|
274
|
+
// N-th `(...)`. Out-of-bounds returns "" (same convention as `nth`).
|
|
275
|
+
"echo version={{ regex_capture(read_file('app/build.gradle.kts'), 'versionName = \"([^\"]+)\"', '1') }}",
|
|
262
276
|
// Split-by-separator scalar accessors — string in, string out, no list type:
|
|
263
277
|
// basename idiom (last segment after `/`); empty string when input ends in `/`.
|
|
264
278
|
"echo basename={{ last(ARGS.path, '/') }}",
|
|
@@ -274,6 +288,26 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
274
288
|
// `shell_quote` picks the right quoting for the active shell:
|
|
275
289
|
"some-tool --json {{ shell_quote(base64_decode(ENV.SECRET_BASE64)) }}",
|
|
276
290
|
|
|
291
|
+
// Slurp shell-command stdout straight into a substitution. `capture` runs
|
|
292
|
+
// the command through the platform's default shell (sh / cmd) and trims
|
|
293
|
+
// the trailing newline. Results are memoized per-target so the same
|
|
294
|
+
// capture in multiple commands runs once. `--dry-run` substitutes a
|
|
295
|
+
// readable placeholder instead of spawning the shell.
|
|
296
|
+
"echo built-at={{ capture('date -u +%Y-%m-%dT%H:%M:%SZ') }}",
|
|
297
|
+
"{{ define(sha, capture('git rev-parse HEAD')) }}",
|
|
298
|
+
|
|
299
|
+
// Arithmetic — variadic (2+ args), coerces strings to numbers, errors on
|
|
300
|
+
// non-numeric input. The result is formatted as an integer when whole and
|
|
301
|
+
// as a decimal otherwise (so `add('5', '3')` → "8", `add('5', '1.1')` →
|
|
302
|
+
// "6.1"). Divide-by-zero errors out.
|
|
303
|
+
"echo next-build={{ add(VARS.versionCode, '1') }}",
|
|
304
|
+
"echo half={{ divide(VARS.total, '2') }}",
|
|
305
|
+
|
|
306
|
+
// Validate a value against a fixed allow-list. Returns the value on
|
|
307
|
+
// match; lists every valid option in the error on mismatch. Collapses
|
|
308
|
+
// the four-case `match { major: define(part, 'major'), ... }` boilerplate.
|
|
309
|
+
"{{ define(part, one_of(ARGS, 'major', 'minor', 'patch', 'build')) }}",
|
|
310
|
+
|
|
277
311
|
// Cache keys / content fingerprints. `sha256` for security-sensitive use,
|
|
278
312
|
// `md5` for cheap fingerprinting (NOT cryptographically secure).
|
|
279
313
|
"echo cache-key={{ sha256(read_file('package-lock.json')) }}",
|
package/bin/darwin-arm64/run
CHANGED
|
Binary file
|
package/bin/darwin-x64/README.md
CHANGED
|
@@ -146,7 +146,7 @@ AES-256-GCM secrets you can commit to git. Auto-decrypted at runtime, never writ
|
|
|
146
146
|
tool, no wrapper.
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
-
$ run :env init
|
|
149
|
+
$ run :env init .env.production
|
|
150
150
|
$ run :env set .env.production DB_PASS "s3cr3t" # auto-encrypted
|
|
151
151
|
$ run :env set .env.production DB_PASS # omit value → read from stdin (no shell history, no escaping)
|
|
152
152
|
```
|
|
@@ -160,9 +160,17 @@ You can also use Runfile as a drop-in `dotenvx`/`dotenv` replacement to inject e
|
|
|
160
160
|
any command — no Runfile needed:
|
|
161
161
|
|
|
162
162
|
```bash
|
|
163
|
-
$ run :env inject -- node app.js
|
|
164
|
-
$ run :env inject
|
|
165
|
-
$ run :env inject
|
|
163
|
+
$ run :env inject .env -- node app.js # one file
|
|
164
|
+
$ run :env inject .env .env.local -- pnpm dev # multiple files, last wins; parent env always wins
|
|
165
|
+
$ run :env inject .env.production -- ./deploy.sh # encrypted values auto-decrypted
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
In CI, the file path can be supplied via `RUNFILE_ENV_FILE_TARGET` (set automatically by the
|
|
169
|
+
[setup action's `env-file-source` input](.github/actions/setup/action.yml) for open-source
|
|
170
|
+
repos that keep their encrypted `.env` in a GitHub secret):
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
$ run :env inject -- node app.js # uses $RUNFILE_ENV_FILE_TARGET
|
|
166
174
|
```
|
|
167
175
|
|
|
168
176
|
#### Powerful argument substitution
|
|
@@ -240,15 +248,17 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
240
248
|
// trim : trim, trim_start, trim_end
|
|
241
249
|
// inspect : length, starts_with, ends_with, contains
|
|
242
250
|
// transform : escape, repeat, replace_all, remove_all
|
|
243
|
-
// regex : regex_replace, regex_remove, regex_matches
|
|
251
|
+
// regex : regex_replace, regex_remove, regex_matches, regex_capture
|
|
244
252
|
// build : concat, join
|
|
245
253
|
// split : nth, first, last, count_parts
|
|
254
|
+
// math : add, subtract, multiply, divide
|
|
255
|
+
// validate : one_of
|
|
246
256
|
// encoding : base64_encode, base64_decode
|
|
247
257
|
// hashing : sha256, md5
|
|
248
258
|
// files : read_file, file_exists
|
|
249
259
|
// json : json_get, json_set
|
|
250
260
|
// error : try
|
|
251
|
-
// shell : shell_quote
|
|
261
|
+
// shell : shell_quote, capture
|
|
252
262
|
// variables : define
|
|
253
263
|
// cwd : set_cwd
|
|
254
264
|
"echo deploying-{{ to_upper(ARGS.env) }}",
|
|
@@ -259,6 +269,10 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
259
269
|
"go test {{ replace_all(ARGS.flags, ' ', ' -tag=') }}",
|
|
260
270
|
// Strip every match of a regex (here: collapse whitespace runs to a single space):
|
|
261
271
|
"echo {{ regex_replace(ARGS.text, '\\s+', ' ') }}",
|
|
272
|
+
// Pull a capture group out of the first regex match — no `(?s)^.*X(...)X.*$`
|
|
273
|
+
// greedy-replace trick needed. Group 0 is the whole match; group N is the
|
|
274
|
+
// N-th `(...)`. Out-of-bounds returns "" (same convention as `nth`).
|
|
275
|
+
"echo version={{ regex_capture(read_file('app/build.gradle.kts'), 'versionName = \"([^\"]+)\"', '1') }}",
|
|
262
276
|
// Split-by-separator scalar accessors — string in, string out, no list type:
|
|
263
277
|
// basename idiom (last segment after `/`); empty string when input ends in `/`.
|
|
264
278
|
"echo basename={{ last(ARGS.path, '/') }}",
|
|
@@ -274,6 +288,26 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
274
288
|
// `shell_quote` picks the right quoting for the active shell:
|
|
275
289
|
"some-tool --json {{ shell_quote(base64_decode(ENV.SECRET_BASE64)) }}",
|
|
276
290
|
|
|
291
|
+
// Slurp shell-command stdout straight into a substitution. `capture` runs
|
|
292
|
+
// the command through the platform's default shell (sh / cmd) and trims
|
|
293
|
+
// the trailing newline. Results are memoized per-target so the same
|
|
294
|
+
// capture in multiple commands runs once. `--dry-run` substitutes a
|
|
295
|
+
// readable placeholder instead of spawning the shell.
|
|
296
|
+
"echo built-at={{ capture('date -u +%Y-%m-%dT%H:%M:%SZ') }}",
|
|
297
|
+
"{{ define(sha, capture('git rev-parse HEAD')) }}",
|
|
298
|
+
|
|
299
|
+
// Arithmetic — variadic (2+ args), coerces strings to numbers, errors on
|
|
300
|
+
// non-numeric input. The result is formatted as an integer when whole and
|
|
301
|
+
// as a decimal otherwise (so `add('5', '3')` → "8", `add('5', '1.1')` →
|
|
302
|
+
// "6.1"). Divide-by-zero errors out.
|
|
303
|
+
"echo next-build={{ add(VARS.versionCode, '1') }}",
|
|
304
|
+
"echo half={{ divide(VARS.total, '2') }}",
|
|
305
|
+
|
|
306
|
+
// Validate a value against a fixed allow-list. Returns the value on
|
|
307
|
+
// match; lists every valid option in the error on mismatch. Collapses
|
|
308
|
+
// the four-case `match { major: define(part, 'major'), ... }` boilerplate.
|
|
309
|
+
"{{ define(part, one_of(ARGS, 'major', 'minor', 'patch', 'build')) }}",
|
|
310
|
+
|
|
277
311
|
// Cache keys / content fingerprints. `sha256` for security-sensitive use,
|
|
278
312
|
// `md5` for cheap fingerprinting (NOT cryptographically secure).
|
|
279
313
|
"echo cache-key={{ sha256(read_file('package-lock.json')) }}",
|
package/bin/darwin-x64/run
CHANGED
|
Binary file
|
|
@@ -146,7 +146,7 @@ AES-256-GCM secrets you can commit to git. Auto-decrypted at runtime, never writ
|
|
|
146
146
|
tool, no wrapper.
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
-
$ run :env init
|
|
149
|
+
$ run :env init .env.production
|
|
150
150
|
$ run :env set .env.production DB_PASS "s3cr3t" # auto-encrypted
|
|
151
151
|
$ run :env set .env.production DB_PASS # omit value → read from stdin (no shell history, no escaping)
|
|
152
152
|
```
|
|
@@ -160,9 +160,17 @@ You can also use Runfile as a drop-in `dotenvx`/`dotenv` replacement to inject e
|
|
|
160
160
|
any command — no Runfile needed:
|
|
161
161
|
|
|
162
162
|
```bash
|
|
163
|
-
$ run :env inject -- node app.js
|
|
164
|
-
$ run :env inject
|
|
165
|
-
$ run :env inject
|
|
163
|
+
$ run :env inject .env -- node app.js # one file
|
|
164
|
+
$ run :env inject .env .env.local -- pnpm dev # multiple files, last wins; parent env always wins
|
|
165
|
+
$ run :env inject .env.production -- ./deploy.sh # encrypted values auto-decrypted
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
In CI, the file path can be supplied via `RUNFILE_ENV_FILE_TARGET` (set automatically by the
|
|
169
|
+
[setup action's `env-file-source` input](.github/actions/setup/action.yml) for open-source
|
|
170
|
+
repos that keep their encrypted `.env` in a GitHub secret):
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
$ run :env inject -- node app.js # uses $RUNFILE_ENV_FILE_TARGET
|
|
166
174
|
```
|
|
167
175
|
|
|
168
176
|
#### Powerful argument substitution
|
|
@@ -240,15 +248,17 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
240
248
|
// trim : trim, trim_start, trim_end
|
|
241
249
|
// inspect : length, starts_with, ends_with, contains
|
|
242
250
|
// transform : escape, repeat, replace_all, remove_all
|
|
243
|
-
// regex : regex_replace, regex_remove, regex_matches
|
|
251
|
+
// regex : regex_replace, regex_remove, regex_matches, regex_capture
|
|
244
252
|
// build : concat, join
|
|
245
253
|
// split : nth, first, last, count_parts
|
|
254
|
+
// math : add, subtract, multiply, divide
|
|
255
|
+
// validate : one_of
|
|
246
256
|
// encoding : base64_encode, base64_decode
|
|
247
257
|
// hashing : sha256, md5
|
|
248
258
|
// files : read_file, file_exists
|
|
249
259
|
// json : json_get, json_set
|
|
250
260
|
// error : try
|
|
251
|
-
// shell : shell_quote
|
|
261
|
+
// shell : shell_quote, capture
|
|
252
262
|
// variables : define
|
|
253
263
|
// cwd : set_cwd
|
|
254
264
|
"echo deploying-{{ to_upper(ARGS.env) }}",
|
|
@@ -259,6 +269,10 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
259
269
|
"go test {{ replace_all(ARGS.flags, ' ', ' -tag=') }}",
|
|
260
270
|
// Strip every match of a regex (here: collapse whitespace runs to a single space):
|
|
261
271
|
"echo {{ regex_replace(ARGS.text, '\\s+', ' ') }}",
|
|
272
|
+
// Pull a capture group out of the first regex match — no `(?s)^.*X(...)X.*$`
|
|
273
|
+
// greedy-replace trick needed. Group 0 is the whole match; group N is the
|
|
274
|
+
// N-th `(...)`. Out-of-bounds returns "" (same convention as `nth`).
|
|
275
|
+
"echo version={{ regex_capture(read_file('app/build.gradle.kts'), 'versionName = \"([^\"]+)\"', '1') }}",
|
|
262
276
|
// Split-by-separator scalar accessors — string in, string out, no list type:
|
|
263
277
|
// basename idiom (last segment after `/`); empty string when input ends in `/`.
|
|
264
278
|
"echo basename={{ last(ARGS.path, '/') }}",
|
|
@@ -274,6 +288,26 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
274
288
|
// `shell_quote` picks the right quoting for the active shell:
|
|
275
289
|
"some-tool --json {{ shell_quote(base64_decode(ENV.SECRET_BASE64)) }}",
|
|
276
290
|
|
|
291
|
+
// Slurp shell-command stdout straight into a substitution. `capture` runs
|
|
292
|
+
// the command through the platform's default shell (sh / cmd) and trims
|
|
293
|
+
// the trailing newline. Results are memoized per-target so the same
|
|
294
|
+
// capture in multiple commands runs once. `--dry-run` substitutes a
|
|
295
|
+
// readable placeholder instead of spawning the shell.
|
|
296
|
+
"echo built-at={{ capture('date -u +%Y-%m-%dT%H:%M:%SZ') }}",
|
|
297
|
+
"{{ define(sha, capture('git rev-parse HEAD')) }}",
|
|
298
|
+
|
|
299
|
+
// Arithmetic — variadic (2+ args), coerces strings to numbers, errors on
|
|
300
|
+
// non-numeric input. The result is formatted as an integer when whole and
|
|
301
|
+
// as a decimal otherwise (so `add('5', '3')` → "8", `add('5', '1.1')` →
|
|
302
|
+
// "6.1"). Divide-by-zero errors out.
|
|
303
|
+
"echo next-build={{ add(VARS.versionCode, '1') }}",
|
|
304
|
+
"echo half={{ divide(VARS.total, '2') }}",
|
|
305
|
+
|
|
306
|
+
// Validate a value against a fixed allow-list. Returns the value on
|
|
307
|
+
// match; lists every valid option in the error on mismatch. Collapses
|
|
308
|
+
// the four-case `match { major: define(part, 'major'), ... }` boilerplate.
|
|
309
|
+
"{{ define(part, one_of(ARGS, 'major', 'minor', 'patch', 'build')) }}",
|
|
310
|
+
|
|
277
311
|
// Cache keys / content fingerprints. `sha256` for security-sensitive use,
|
|
278
312
|
// `md5` for cheap fingerprinting (NOT cryptographically secure).
|
|
279
313
|
"echo cache-key={{ sha256(read_file('package-lock.json')) }}",
|
package/bin/linux-arm64/run
CHANGED
|
Binary file
|
package/bin/linux-x64/README.md
CHANGED
|
@@ -146,7 +146,7 @@ AES-256-GCM secrets you can commit to git. Auto-decrypted at runtime, never writ
|
|
|
146
146
|
tool, no wrapper.
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
-
$ run :env init
|
|
149
|
+
$ run :env init .env.production
|
|
150
150
|
$ run :env set .env.production DB_PASS "s3cr3t" # auto-encrypted
|
|
151
151
|
$ run :env set .env.production DB_PASS # omit value → read from stdin (no shell history, no escaping)
|
|
152
152
|
```
|
|
@@ -160,9 +160,17 @@ You can also use Runfile as a drop-in `dotenvx`/`dotenv` replacement to inject e
|
|
|
160
160
|
any command — no Runfile needed:
|
|
161
161
|
|
|
162
162
|
```bash
|
|
163
|
-
$ run :env inject -- node app.js
|
|
164
|
-
$ run :env inject
|
|
165
|
-
$ run :env inject
|
|
163
|
+
$ run :env inject .env -- node app.js # one file
|
|
164
|
+
$ run :env inject .env .env.local -- pnpm dev # multiple files, last wins; parent env always wins
|
|
165
|
+
$ run :env inject .env.production -- ./deploy.sh # encrypted values auto-decrypted
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
In CI, the file path can be supplied via `RUNFILE_ENV_FILE_TARGET` (set automatically by the
|
|
169
|
+
[setup action's `env-file-source` input](.github/actions/setup/action.yml) for open-source
|
|
170
|
+
repos that keep their encrypted `.env` in a GitHub secret):
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
$ run :env inject -- node app.js # uses $RUNFILE_ENV_FILE_TARGET
|
|
166
174
|
```
|
|
167
175
|
|
|
168
176
|
#### Powerful argument substitution
|
|
@@ -240,15 +248,17 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
240
248
|
// trim : trim, trim_start, trim_end
|
|
241
249
|
// inspect : length, starts_with, ends_with, contains
|
|
242
250
|
// transform : escape, repeat, replace_all, remove_all
|
|
243
|
-
// regex : regex_replace, regex_remove, regex_matches
|
|
251
|
+
// regex : regex_replace, regex_remove, regex_matches, regex_capture
|
|
244
252
|
// build : concat, join
|
|
245
253
|
// split : nth, first, last, count_parts
|
|
254
|
+
// math : add, subtract, multiply, divide
|
|
255
|
+
// validate : one_of
|
|
246
256
|
// encoding : base64_encode, base64_decode
|
|
247
257
|
// hashing : sha256, md5
|
|
248
258
|
// files : read_file, file_exists
|
|
249
259
|
// json : json_get, json_set
|
|
250
260
|
// error : try
|
|
251
|
-
// shell : shell_quote
|
|
261
|
+
// shell : shell_quote, capture
|
|
252
262
|
// variables : define
|
|
253
263
|
// cwd : set_cwd
|
|
254
264
|
"echo deploying-{{ to_upper(ARGS.env) }}",
|
|
@@ -259,6 +269,10 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
259
269
|
"go test {{ replace_all(ARGS.flags, ' ', ' -tag=') }}",
|
|
260
270
|
// Strip every match of a regex (here: collapse whitespace runs to a single space):
|
|
261
271
|
"echo {{ regex_replace(ARGS.text, '\\s+', ' ') }}",
|
|
272
|
+
// Pull a capture group out of the first regex match — no `(?s)^.*X(...)X.*$`
|
|
273
|
+
// greedy-replace trick needed. Group 0 is the whole match; group N is the
|
|
274
|
+
// N-th `(...)`. Out-of-bounds returns "" (same convention as `nth`).
|
|
275
|
+
"echo version={{ regex_capture(read_file('app/build.gradle.kts'), 'versionName = \"([^\"]+)\"', '1') }}",
|
|
262
276
|
// Split-by-separator scalar accessors — string in, string out, no list type:
|
|
263
277
|
// basename idiom (last segment after `/`); empty string when input ends in `/`.
|
|
264
278
|
"echo basename={{ last(ARGS.path, '/') }}",
|
|
@@ -274,6 +288,26 @@ and work as full substitution bodies *or* as chain segments:
|
|
|
274
288
|
// `shell_quote` picks the right quoting for the active shell:
|
|
275
289
|
"some-tool --json {{ shell_quote(base64_decode(ENV.SECRET_BASE64)) }}",
|
|
276
290
|
|
|
291
|
+
// Slurp shell-command stdout straight into a substitution. `capture` runs
|
|
292
|
+
// the command through the platform's default shell (sh / cmd) and trims
|
|
293
|
+
// the trailing newline. Results are memoized per-target so the same
|
|
294
|
+
// capture in multiple commands runs once. `--dry-run` substitutes a
|
|
295
|
+
// readable placeholder instead of spawning the shell.
|
|
296
|
+
"echo built-at={{ capture('date -u +%Y-%m-%dT%H:%M:%SZ') }}",
|
|
297
|
+
"{{ define(sha, capture('git rev-parse HEAD')) }}",
|
|
298
|
+
|
|
299
|
+
// Arithmetic — variadic (2+ args), coerces strings to numbers, errors on
|
|
300
|
+
// non-numeric input. The result is formatted as an integer when whole and
|
|
301
|
+
// as a decimal otherwise (so `add('5', '3')` → "8", `add('5', '1.1')` →
|
|
302
|
+
// "6.1"). Divide-by-zero errors out.
|
|
303
|
+
"echo next-build={{ add(VARS.versionCode, '1') }}",
|
|
304
|
+
"echo half={{ divide(VARS.total, '2') }}",
|
|
305
|
+
|
|
306
|
+
// Validate a value against a fixed allow-list. Returns the value on
|
|
307
|
+
// match; lists every valid option in the error on mismatch. Collapses
|
|
308
|
+
// the four-case `match { major: define(part, 'major'), ... }` boilerplate.
|
|
309
|
+
"{{ define(part, one_of(ARGS, 'major', 'minor', 'patch', 'build')) }}",
|
|
310
|
+
|
|
277
311
|
// Cache keys / content fingerprints. `sha256` for security-sensitive use,
|
|
278
312
|
// `md5` for cheap fingerprinting (NOT cryptographically secure).
|
|
279
313
|
"echo cache-key={{ sha256(read_file('package-lock.json')) }}",
|
package/bin/linux-x64/run
CHANGED
|
Binary file
|
package/bin/win32-arm64/run.exe
CHANGED
|
Binary file
|
package/bin/win32-x64/run.exe
CHANGED
|
Binary file
|
package/package.json
CHANGED