@sequenceholdings/studio-cli 0.1.21 → 0.1.24
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 +184 -16
- package/dist/agents/commands.d.ts +1 -1
- package/dist/agents/commands.js +24 -4
- package/dist/agents/source.d.ts +3 -1
- package/dist/agents/source.js +27 -4
- package/dist/app/commands.d.ts +16 -0
- package/dist/app/commands.js +227 -0
- package/dist/app/deploy.d.ts +49 -0
- package/dist/app/deploy.js +197 -0
- package/dist/app/kinds.d.ts +10 -0
- package/dist/app/kinds.js +36 -0
- package/dist/app/manifest.d.ts +94 -0
- package/dist/app/manifest.js +273 -0
- package/dist/app/scaffold.d.ts +28 -0
- package/dist/app/scaffold.js +263 -0
- package/dist/atlas-client.js +29 -0
- package/dist/auth.js +2 -0
- package/dist/functions/commands.js +1 -0
- package/dist/functions/manifest.d.ts +24 -0
- package/dist/functions/manifest.js +84 -9
- package/dist/main.d.ts +3 -0
- package/dist/main.js +21 -0
- package/dist/pipeline/codegen.d.ts +2 -0
- package/dist/pipeline/codegen.js +118 -0
- package/dist/pipeline/commands.d.ts +7 -0
- package/dist/pipeline/commands.js +105 -10
- package/dist/pipeline/lifecycle.d.ts +3 -12
- package/dist/pipeline/lifecycle.js +245 -33
- package/dist/pipeline/templates.js +3 -1
- package/dist/repos/commands.d.ts +53 -1
- package/dist/repos/commands.js +258 -1
- package/dist/secrets/commands.d.ts +3 -1
- package/dist/secrets/commands.js +87 -26
- package/package.json +8 -8
- package/dist/pipeline/pinning.d.ts +0 -5
- package/dist/pipeline/pinning.js +0 -9
package/README.md
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Standalone CLI for the Sequence platform: typed agents, Lattice processes, Artifact Studio
|
|
4
4
|
apps, Managed Functions, Managed Secrets, ORM namespaces, Data Pipelines stage
|
|
5
|
-
specs, and platform git repos.
|
|
6
|
-
HTTP — no monorepo checkout required.
|
|
5
|
+
specs, and platform git repos. Its published workflows run from any repo
|
|
6
|
+
against the platform over HTTP — no monorepo checkout required. The v0
|
|
7
|
+
app-monorepo commands below are currently internal; see their availability
|
|
8
|
+
notice.
|
|
7
9
|
|
|
8
10
|
```
|
|
9
11
|
seq-studio process lint
|
|
@@ -43,7 +45,7 @@ equivalent and would happily install a freshly-published malicious
|
|
|
43
45
|
version of any transitive dep. **External process repos scaffolded by
|
|
44
46
|
`seq-studio process init` ship a `pnpm-workspace.yaml` with the same
|
|
45
47
|
guard.** Stick with pnpm so the policy actually applies.
|
|
46
|
-
(The seq-studio publish chain — `atlas-ui`, `lattice-form-renderer`,
|
|
48
|
+
(The seq-studio publish chain — `agent-spec`, `atlas-ui`, `lattice-form-renderer`,
|
|
47
49
|
`artifact-studio`, `lattice`, `studio-cli` — is excluded from the quarantine;
|
|
48
50
|
those come from the Studio repo's own publish pipeline, so new `seq-studio`
|
|
49
51
|
releases install immediately.)
|
|
@@ -134,6 +136,54 @@ Pass `--env <name>` (or `-e <name>`) on commands that talk to the platform.
|
|
|
134
136
|
the artifact folder's `.artifact-studio/config.json` `defaultEnv` (set by
|
|
135
137
|
`artifact link` / `artifact env use`).
|
|
136
138
|
|
|
139
|
+
## App monorepo commands
|
|
140
|
+
|
|
141
|
+
One app repo can contain ORM, managed functions, and an Artifact Studio UI.
|
|
142
|
+
The root `sequence.app.yml` manifest declares the structure — required for
|
|
143
|
+
scaffolding and for the eventual Applications UI. Do not hand-author apps
|
|
144
|
+
without it.
|
|
145
|
+
|
|
146
|
+
> **Availability:** This is currently an internal orchestration workflow.
|
|
147
|
+
> Generated ORM apps depend on unpublished `@sequenceholdings/orm`, so
|
|
148
|
+
> standalone external installs and the function-to-ORM runtime path are not
|
|
149
|
+
> supported yet.
|
|
150
|
+
|
|
151
|
+
| Command | What it does |
|
|
152
|
+
|---------|--------------|
|
|
153
|
+
| `seq-studio init <dir> --with <kinds>` | Scaffold an app monorepo + `sequence.app.yml` + selected primitive subfolders |
|
|
154
|
+
| `seq-studio add function|artifact <name>` | Add a function or Artifact Studio UI to the current app (updates the manifest) |
|
|
155
|
+
| `seq-studio deploy -e <env> [--yes] [--only id1,id2] [--dry-run]` | Deploy every primitive in `deploy.order` (orm → functions → artifact) |
|
|
156
|
+
|
|
157
|
+
`init` supports v0 kinds `orm`, `function`, and `artifact`; pass them as a
|
|
158
|
+
comma-list (`--with orm,function,artifact`) or boolean flags (`--orm`). `add`
|
|
159
|
+
currently supports functions and one Artifact Studio UI; ORM is created only by
|
|
160
|
+
`init`.
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Full-stack toy (ORM + function + artifact) — workspace / internal CLI only
|
|
164
|
+
seq-studio init pokedex --with orm,function,artifact --function-name get-pokemon
|
|
165
|
+
cd pokedex
|
|
166
|
+
(cd orm/pokedex && pnpm install)
|
|
167
|
+
(cd functions/get-pokemon && pnpm install)
|
|
168
|
+
(cd artifact && pnpm install)
|
|
169
|
+
|
|
170
|
+
seq-studio login
|
|
171
|
+
seq-studio deploy -e local --yes
|
|
172
|
+
|
|
173
|
+
# Day-2: add a second function without re-init
|
|
174
|
+
seq-studio add function list-types
|
|
175
|
+
(cd functions/list-types && pnpm install)
|
|
176
|
+
seq-studio deploy -e local --only list-types --yes
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Each primitive keeps its own `package.json` / lockfile. `deploy` fans out to
|
|
180
|
+
the existing per-primitive commands (`orm apply`, `functions deploy`,
|
|
181
|
+
`artifact deploy`). Pass `--yes` for non-interactive function deploys.
|
|
182
|
+
|
|
183
|
+
`deploy.on_error` defaults to `stop`. Set it to `continue` to deploy independent
|
|
184
|
+
primitives after a failure; any primitive whose `depends_on` prerequisite failed
|
|
185
|
+
or was skipped is skipped as well.
|
|
186
|
+
|
|
137
187
|
## Agent commands
|
|
138
188
|
|
|
139
189
|
Typed agent repositories export one or more `defineAgent(...)` values from files
|
|
@@ -145,13 +195,17 @@ bundle; it never implicitly deletes agents.
|
|
|
145
195
|
| Command | What it does |
|
|
146
196
|
|---------|--------------|
|
|
147
197
|
| `seq-studio agents init <dir>` | Scaffold a standalone typed agent repository |
|
|
148
|
-
| `seq-studio agents validate [--dir <dir>] [--target <APP_ENV>]` | Compile and validate locally, without API access |
|
|
149
|
-
| `seq-studio agents plan [--dir <dir>]` | Offline compile/hash plan |
|
|
150
|
-
| `seq-studio agents plan [--dir <dir>] -e <env> [--target <APP_ENV>]` | Diff creates, updates, and unchanged definitions against an environment |
|
|
151
|
-
| `seq-studio agents apply [--dir <dir>] -e <env> [--target <APP_ENV>] [--yes]` | Apply creates and updates after showing the plan |
|
|
198
|
+
| `seq-studio agents validate [--dir <dir>] [--target <APP_ENV>] [--only <id1,id2>]` | Compile and validate locally, without API access |
|
|
199
|
+
| `seq-studio agents plan [--dir <dir>] [--only <id1,id2>]` | Offline compile/hash plan |
|
|
200
|
+
| `seq-studio agents plan [--dir <dir>] -e <env> [--target <APP_ENV>] [--only <id1,id2>]` | Diff creates, updates, and unchanged definitions against an environment |
|
|
201
|
+
| `seq-studio agents apply [--dir <dir>] -e <env> [--target <APP_ENV>] [--only <id1,id2>] [--yes]` | Apply creates and updates after showing the plan |
|
|
152
202
|
| `seq-studio agents list -e <env>` | List visible runtime agents |
|
|
153
203
|
| `seq-studio agents show <id> -e <env>` | Show one runtime agent |
|
|
154
204
|
|
|
205
|
+
For `validate`, `plan`, and `apply`, `--only` accepts a comma-separated list of
|
|
206
|
+
agent IDs after deployment-environment selection; every requested ID must be
|
|
207
|
+
selected.
|
|
208
|
+
|
|
155
209
|
An optional `deploy-manifest.json` targets definitions by deployment identity:
|
|
156
210
|
|
|
157
211
|
```json
|
|
@@ -187,8 +241,10 @@ Use `--repo agents/<name> [--ref <ref>]` or `--git-url <url>` instead of
|
|
|
187
241
|
## ORM commands
|
|
188
242
|
|
|
189
243
|
`seq-studio orm` authors and deploys governed ORM v2 namespaces: TypeScript
|
|
190
|
-
table definitions and policies plus named
|
|
191
|
-
persisted operations.
|
|
244
|
+
table definitions, Drizzle-authored read-only views, and policies plus named
|
|
245
|
+
GraphQL documents compiled into persisted operations. Import Drizzle query
|
|
246
|
+
helpers from `@sequenceholdings/orm/drizzle`; managed view builders are
|
|
247
|
+
compiled to canonical SQL before registration.
|
|
192
248
|
|
|
193
249
|
| Command | What it does |
|
|
194
250
|
|---------|--------------|
|
|
@@ -335,6 +391,75 @@ same repo share Git review and commit provenance, but keep separate manifests,
|
|
|
335
391
|
versions, runtime resources, secrets, and permissions. `--path` accepts only a
|
|
336
392
|
canonical relative directory inside a remote repo; use `--dir` for local source.
|
|
337
393
|
|
|
394
|
+
### Scaling
|
|
395
|
+
|
|
396
|
+
Managed functions scale to zero by default. Set a bounded warm pool in
|
|
397
|
+
`managed-function.yml` when first-request latency matters:
|
|
398
|
+
|
|
399
|
+
```yaml
|
|
400
|
+
limits:
|
|
401
|
+
min_instances: 1
|
|
402
|
+
max_instances: 3
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
`min_instances` defaults to `0`, cannot exceed `max_instances`, and incurs
|
|
406
|
+
Cloud Run idle-instance charges while warm.
|
|
407
|
+
|
|
408
|
+
### Server-owned resource authorization
|
|
409
|
+
|
|
410
|
+
Some functions expose regulated external resources whose authorization must be
|
|
411
|
+
enforced by Atlas rather than by author code. Those functions select a reviewed
|
|
412
|
+
adapter in `managed-function.yml`:
|
|
413
|
+
|
|
414
|
+
```yaml
|
|
415
|
+
authorization:
|
|
416
|
+
version: 1
|
|
417
|
+
adapter: encompass.loan-read-by-number
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
The adapter name is a closed platform registry. Authors cannot provide JSON
|
|
421
|
+
pointers or custom filtering logic. `seq-studio functions build` rejects an
|
|
422
|
+
unknown adapter, an adapter on an unregistered function, or a protected
|
|
423
|
+
function whose required adapter is missing. The manifest declares only the
|
|
424
|
+
server-owned adapter; authors cannot configure its runtime resource selection
|
|
425
|
+
or policy.
|
|
426
|
+
|
|
427
|
+
### ORM data access
|
|
428
|
+
|
|
429
|
+
A function declares its ORM Data API reach in `capabilities.data`, grouped by
|
|
430
|
+
namespace: `tables` it may read, v1 `actions` and ORM v2 persisted `operations`
|
|
431
|
+
it may invoke, and whether raw read `query` is allowed. At invoke time the
|
|
432
|
+
platform mints a short-lived data token scoped to exactly these refs — an
|
|
433
|
+
operation is scoped as `<namespace>/ops/<OperationName>` (the GraphQL operation
|
|
434
|
+
name from the namespace's `graphql/` documents, case-sensitive), and anything
|
|
435
|
+
undeclared is denied by the Data API. A function that reaches any namespace
|
|
436
|
+
must also attach a top-level `service_account`:
|
|
437
|
+
|
|
438
|
+
```yaml
|
|
439
|
+
service_account: lucky-svc
|
|
440
|
+
capabilities:
|
|
441
|
+
data:
|
|
442
|
+
lucky:
|
|
443
|
+
tables: [lucky_draws]
|
|
444
|
+
operations: [RollLuckyNumber]
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Managed Secret commands
|
|
448
|
+
|
|
449
|
+
| Command | What it does |
|
|
450
|
+
|---------|--------------|
|
|
451
|
+
| `seq-studio secrets create <NAME> -e <env> [--org <slug>]` | Register an org-owned secret (no value) |
|
|
452
|
+
| `seq-studio secrets set <NAME> -e <env> [--org <slug>] [--from-file <path>]` | Set the shared default (write-only; file is not echoed) |
|
|
453
|
+
| `seq-studio secrets list -e <env>` | Secrets you can see (never values) |
|
|
454
|
+
|
|
455
|
+
`--org` targets a managed-scope org other than the login tenant and selects
|
|
456
|
+
the intended same-named secret for `set`, `attach`, `detach`, `versions`,
|
|
457
|
+
`set-default`, and `pin`; it is required when the name exists in multiple
|
|
458
|
+
orgs. Tenant pipeline credentials must be created on that tenant's deployment:
|
|
459
|
+
`seq-studio secrets create NAME -e <tenant> --org <tenant>`. Sequence-owned
|
|
460
|
+
environments (`local`, `staging`, `production`) only accept `--org sequence`.
|
|
461
|
+
The API requires Managed Functions Admin on that org.
|
|
462
|
+
|
|
338
463
|
## Artifact commands
|
|
339
464
|
|
|
340
465
|
`seq-studio artifact <sub>` is the entry point for Artifact Studio. It runs
|
|
@@ -467,11 +592,34 @@ JSON API — the same repos `--repo <ns>/<name>` sources build from.
|
|
|
467
592
|
| `seq-studio repos clone <ns>/<name> \| --url <clone-url> \| --id <uuid> -e <env> [--ref <r>] [--out <dir>] [--force]` | smart-HTTP `git clone` when `ATLAS_GIT_PAT` is set (`--url`/`--id` need no seqapi); otherwise JSON materialize + PAT hint |
|
|
468
593
|
| `seq-studio repos pull <ns>/<name> -e <env> [--ref <r>] [--out <dir>] [--force]` | always materialize via JSON API (no `.git` dir); refuses a non-empty destination unless `--force` |
|
|
469
594
|
| `seq-studio repos delete <ns>/<name> -e <env> [--yes]` | delete a repo — interactive confirm unless `--yes` |
|
|
595
|
+
| `seq-studio repos ci show <ns>/<name> -e <env> [--ref <r>]` | preview CI checks discovered from the ref |
|
|
596
|
+
| `seq-studio repos ci require <ns>/<name> --check <name> -e <env>` | reserved for requiring a named CI check; currently refuses to write until the sandboxed runner is live |
|
|
597
|
+
| `seq-studio repos ci import <ns>/<name> -e <env> [--ref <r>]` | reserved for requiring every discovered check; currently refuses to write until the sandboxed runner is live |
|
|
470
598
|
|
|
471
599
|
`show` prints the smart-HTTP clone URL (`…/repos/<id>/git`). Basic auth:
|
|
472
600
|
any username, PAT as password. Prefer `repos clone` over hand-rolling the
|
|
473
601
|
tree API.
|
|
474
602
|
|
|
603
|
+
PR CI discovers `ci/check` from the first available `lint`, `typecheck`, or
|
|
604
|
+
`check` script and `ci/test` from `test`. A `.seq/ci.json` takes precedence;
|
|
605
|
+
its `checks` array can declare script/argv checks or be empty to opt out.
|
|
606
|
+
|
|
607
|
+
For example:
|
|
608
|
+
|
|
609
|
+
{ "checks": [
|
|
610
|
+
{ "phase": "check", "script": "lint" },
|
|
611
|
+
{ "phase": "test", "command": ["pnpm", "test"] }
|
|
612
|
+
] }
|
|
613
|
+
|
|
614
|
+
Each check needs `phase` (`check` or `test`) and exactly one of `script` or
|
|
615
|
+
`command`; `name` is optional and otherwise defaults to `ci/<phase>`
|
|
616
|
+
(`-2`, etc. for additional checks in that phase).
|
|
617
|
+
Discovery alone never blocks a merge. Until the sandboxed executor is live,
|
|
618
|
+
`repos ci show` is preview-only, Settings controls are disabled, and
|
|
619
|
+
`require`/`import` refuse to write (discovery currently posts `neutral`
|
|
620
|
+
check-runs). Once the executor is live, repo owners can opt in by requiring
|
|
621
|
+
check names in Settings or with `repos ci require`/`repos ci import`.
|
|
622
|
+
|
|
475
623
|
## Pipeline commands
|
|
476
624
|
|
|
477
625
|
`seq-studio pipeline <sub>` authors and validates Data Pipelines **stage
|
|
@@ -482,13 +630,33 @@ install it alongside the CLI to use this family.
|
|
|
482
630
|
|
|
483
631
|
| Command | What it does |
|
|
484
632
|
|---------|--------------|
|
|
485
|
-
| `seq-studio pipeline init --type ingestion\|transformation\|serving <name> [--dir <dir>]` | Scaffold `<name>.stage.yml` (commented per-kind template) plus a `src/` entrypoint stub (serving stages are declarative — no stub). Refuses to overwrite an existing spec |
|
|
486
|
-
| `seq-studio pipeline validate [dir] [--assets <file\|url>] [--json]` | Run the full offline spec gate: envelope + body validation, `schema_ref` resolution, and repo-level graph validation (reference resolution, single-writer, cycles, column subsets, serving projection checks). Exit 0/1 |
|
|
487
|
-
| `seq-studio pipeline plan --repo pipelines/<slug> --ref <sha\|branch> -e <env> [--json]` | Plan a Pipeline deploy (materialize → SDK/`validateSpecGraph` → compile → live-diff → provision findings). Does **not** run Databricks `bundle validate` (that is a Trigger deploy-path hard gate). Exit 1 on destructive findings (CI-safe). `--json` emits the stable plan envelope |
|
|
488
|
-
| `seq-studio pipeline deploy --repo pipelines/<slug> --ref <sha> -e <env> [--approved-by <sub>] [--no-wait]` | Plan then enqueue deploy; Trigger runs `bundle validate` then `bundle deploy` against reviewed bytes. Polls to terminal unless `--no-wait`.
|
|
489
|
-
| `seq-studio pipeline
|
|
490
|
-
| `seq-studio pipeline
|
|
491
|
-
| `seq-studio pipeline
|
|
633
|
+
| `seq-studio pipeline init --type ingestion\|transformation\|serving <name> [--dir <dir>]` | Scaffold `<name>.stage.yml` (commented per-kind template) plus a `src/` Databricks-notebook entrypoint stub (begins with `# Databricks notebook source`; serving stages are declarative — no stub). Refuses to overwrite an existing spec |
|
|
634
|
+
| `seq-studio pipeline validate [dir] [--assets <file\|url>] [--orm-contracts <file\|url>] [--json]` | Run the full offline spec gate: envelope + body validation, `schema_ref` resolution, and repo-level graph validation (reference resolution, single-writer, cycles, column subsets, serving projection checks). Auto-loads `orm-contracts.json` from the pipeline dir when present. Exit 0/1 |
|
|
635
|
+
| `seq-studio pipeline plan --repo pipelines/<slug> --ref <sha\|branch> -e <env> [--target <id>] [--json]` | Plan a Pipeline deploy (materialize → SDK/`validateSpecGraph` → compile → live-diff → provision findings). Fails closed listing **every** missing target binding (alert channels, workspace, Databricks `source.credential`) plus Data Sync edge-worker machine/operation/`credEnvFamilies` mismatches before registry writes. Does **not** run Databricks `bundle validate` (that is a Trigger deploy-path hard gate). Exit 1 on destructive findings (CI-safe). `--json` emits the stable plan envelope |
|
|
636
|
+
| `seq-studio pipeline deploy --repo pipelines/<slug> --ref <sha\|branch> -e <env> [--target <id>] [--approved-by <sub>] [--no-wait]` | Plan then enqueue deploy; Trigger runs `bundle validate` then `bundle deploy` against reviewed bytes. Polls to terminal unless `--no-wait`. Targets that require approval need `--approved-by` naming the authenticated caller. |
|
|
637
|
+
| `seq-studio pipeline adopt --stage <slug> --ref <sha\|branch> -e <env> [--target <id>] --native-id <id> --approved-by <you> [--resource-key <key>] [--kind job\|dlt_pipeline] [--old-source-removal-pr <url>] [--repo pipelines/<slug>]` | Bind a live Databricks job/pipeline into the stage without recreation (`bundle deployment bind` on Trigger). Always requires `--approved-by` naming the caller. When the key is still in the monorepo DAB, pass `--old-source-removal-pr` and follow the returned cutover checklist: unbind the old bundle state without deleting the remote, then remove its DAB declaration and add the target-specific adopted-resource entry in the same PR before redeploying. |
|
|
638
|
+
| `seq-studio pipeline unbind --stage <slug> --ref <sha\|branch> -e <env> [--target <id>] --approved-by <you> [--resource-key <key>] [--repo pipelines/<slug>]` | Release an adopted binding on Trigger; the remote object stays live (never deleted) |
|
|
639
|
+
| `seq-studio pipeline run-now --stage <slug> -e <env> [--target <id>] [--repo pipelines/<slug>] [--json]` | Run the stage's active job or DLT pipeline immediately and print its Databricks run URL |
|
|
640
|
+
| `seq-studio pipeline promote --stage <slug> --version <v> -e <env> [--target <id>] [--repo pipelines/<slug>] [--approved-by <you>] [--no-wait]` | Promote a validated version to another target. Targets that require approval need `--approved-by`; `--repo` disambiguates a slug that exists in multiple Pipelines |
|
|
641
|
+
| `seq-studio pipeline rollback --stage <slug> -e <env> [--target <id>] [--repo pipelines/<slug>] [--approved-by <you>] [--no-wait]` | Redeploy the previously retired deployment's version. Targets that require approval need `--approved-by`. |
|
|
642
|
+
|
|
643
|
+
`-e/--env` selects the Atlas connection. `--target` selects the logical
|
|
644
|
+
pipeline target advertised by that endpoint. It is optional when the alias
|
|
645
|
+
matches a target id or when the endpoint has exactly one target.
|
|
646
|
+
|
|
647
|
+
Unless `--no-wait` is set, `deploy`, `promote`, and `rollback` report status or
|
|
648
|
+
status-detail changes while waiting, then emit a 20-second progress heartbeat.
|
|
649
|
+
Terminal output includes the deployment ID and elapsed time; failures include
|
|
650
|
+
the status detail, and any available Trigger run ID is shown. `--json` output
|
|
651
|
+
is unchanged.
|
|
652
|
+
|
|
653
|
+
### Managed Pipelines asset identity
|
|
654
|
+
|
|
655
|
+
Compiled Databricks assets use stable, environment-qualified identities: display names are `{env}-MP-{type}-{stage}` (with `-trigger` for a scheduled DLT runner), DAB resource keys are `mp_{type}_{stage_snake_case}` (with `_trigger` for that runner), task keys are `{type}_{task}`, and bundles are `{env}-MP-pipelines-{domain}`. Compiled jobs and pipelines also carry `mp: "true"` and `mp_type: <type>` tags.
|
|
656
|
+
|
|
657
|
+
Changing a DAB resource key is a delete-and-create operation. Treat these identities as the existing-resource contract when planning, adopting, unbinding, or inspecting a Managed Pipeline; Unity Catalog catalogs, volumes, tables, and synced tables are not renamed by this convention.
|
|
658
|
+
|
|
659
|
+
The `{env}-MP-…` scheme itself is a one-shot break from the unprefixed names (`silverlake-core`, `pipelines-<domain>-<env>`). We do not migrate DAB bundle state or DLT resource identity: the first deploy after this change creates a new bundle and new jobs/pipelines, and can cascade-drop DLT-managed tables on the deleted resource. Operators should pause or delete leftover unprefixed jobs once the new ones are healthy. Each enabled OpCo deployment advertises and owns its own target profile.
|
|
492
660
|
|
|
493
661
|
`validate` is offline — no network or database. `--assets` supplies a
|
|
494
662
|
registry **asset export** (JSON) so inputs referencing other Pipelines'
|
|
@@ -6,5 +6,5 @@ export declare function agentsPlanCommand(args: ParsedArgs): Promise<number>;
|
|
|
6
6
|
export declare function agentsApplyCommand(args: ParsedArgs): Promise<number>;
|
|
7
7
|
export declare function agentsListCommand(args: ParsedArgs): Promise<number>;
|
|
8
8
|
export declare function agentsShowCommand(args: ParsedArgs): Promise<number>;
|
|
9
|
-
export declare const AGENTS_USAGE = "usage:\n seq-studio agents init <dir> scaffold a typed agent\n seq-studio agents validate [--dir d] [--target app] offline compile + validation\n seq-studio agents plan [--dir d] [-e <env>] offline bundle plan or live diff\n seq-studio agents apply [--dir d] -e <env> [--yes] apply creates/updates; never deletes\n seq-studio agents list -e <env> list visible agents\n seq-studio agents show <id> -e <env> show one agent\n\n Source: local --dir (default .), --repo agents/<name>, or --git-url <url>.\n Use --ref for remote sources. --target selects the deployment APP_ENV when it\n differs from the CLI environment alias (notably OpCo registrations).\n";
|
|
9
|
+
export declare const AGENTS_USAGE = "usage:\n seq-studio agents init <dir> scaffold a typed agent\n seq-studio agents validate [--dir d] [--target app] [--only ids] offline compile + validation\n seq-studio agents plan [--dir d] [-e <env>] [--only ids] offline bundle plan or live diff\n seq-studio agents apply [--dir d] -e <env> [--only ids] [--yes] apply creates/updates; never deletes\n seq-studio agents list -e <env> list visible agents\n seq-studio agents show <id> -e <env> show one agent\n\n Source: local --dir (default .), --repo agents/<name>, or --git-url <url>.\n Use --ref for remote sources. --target selects the deployment APP_ENV when it\n differs from the CLI environment alias (notably OpCo registrations). --only\n accepts a comma-separated list of agent IDs after environment selection.\n";
|
|
10
10
|
export declare function runAgentsCommand(sub: string | undefined, args: ParsedArgs): Promise<number>;
|
package/dist/agents/commands.js
CHANGED
|
@@ -7,6 +7,22 @@ import { compileAgentSource as compileSource, materializeAgentSource as material
|
|
|
7
7
|
import { agentsInitCommand } from './scaffold.js';
|
|
8
8
|
export { agentsInitCommand };
|
|
9
9
|
const LOG = '[seq-studio]';
|
|
10
|
+
function requestedAgentIds(args) {
|
|
11
|
+
const only = args.flags.only;
|
|
12
|
+
if (only === undefined)
|
|
13
|
+
return undefined;
|
|
14
|
+
if (typeof only !== 'string') {
|
|
15
|
+
throw new Error('--only must be a comma-separated list of agent IDs');
|
|
16
|
+
}
|
|
17
|
+
const ids = only
|
|
18
|
+
.split(',')
|
|
19
|
+
.map((id) => id.trim())
|
|
20
|
+
.filter(Boolean);
|
|
21
|
+
if (ids.length === 0) {
|
|
22
|
+
throw new Error('--only must include at least one agent ID');
|
|
23
|
+
}
|
|
24
|
+
return [...new Set(ids)];
|
|
25
|
+
}
|
|
10
26
|
export async function agentsValidateCommand(args) {
|
|
11
27
|
const { source } = await materialize({ args, requireEnvironment: false });
|
|
12
28
|
try {
|
|
@@ -15,6 +31,7 @@ export async function agentsValidateCommand(args) {
|
|
|
15
31
|
directory: source.dir,
|
|
16
32
|
targetEnvironment: target,
|
|
17
33
|
deployEnvironments: await deployEnvironmentNames(),
|
|
34
|
+
onlyIds: requestedAgentIds(args),
|
|
18
35
|
});
|
|
19
36
|
if (bundle.definitions.length === 0) {
|
|
20
37
|
console.error(`${LOG} no named agent.ts definitions found`);
|
|
@@ -34,6 +51,7 @@ async function deploymentBundle({ args, source, context, }) {
|
|
|
34
51
|
directory: source.dir,
|
|
35
52
|
targetEnvironment: target,
|
|
36
53
|
deployEnvironments: await deployEnvironmentNames(),
|
|
54
|
+
onlyIds: requestedAgentIds(args),
|
|
37
55
|
});
|
|
38
56
|
}
|
|
39
57
|
/**
|
|
@@ -75,6 +93,7 @@ export async function agentsPlanCommand(args) {
|
|
|
75
93
|
directory: source.dir,
|
|
76
94
|
targetEnvironment: target,
|
|
77
95
|
deployEnvironments: await deployEnvironmentNames(),
|
|
96
|
+
onlyIds: requestedAgentIds(args),
|
|
78
97
|
});
|
|
79
98
|
console.log(`${LOG} offline plan: ${bundle.definitions.length} valid definition${bundle.definitions.length === 1 ? '' : 's'}, bundle ${bundle.hash}`);
|
|
80
99
|
console.log(`${LOG} pass -e <env> for create/update/unchanged live diff`);
|
|
@@ -174,15 +193,16 @@ export async function agentsShowCommand(args) {
|
|
|
174
193
|
}
|
|
175
194
|
export const AGENTS_USAGE = `usage:
|
|
176
195
|
seq-studio agents init <dir> scaffold a typed agent
|
|
177
|
-
seq-studio agents validate [--dir d] [--target app] offline compile + validation
|
|
178
|
-
seq-studio agents plan [--dir d] [-e <env>] offline bundle plan or live diff
|
|
179
|
-
seq-studio agents apply [--dir d] -e <env> [--yes] apply creates/updates; never deletes
|
|
196
|
+
seq-studio agents validate [--dir d] [--target app] [--only ids] offline compile + validation
|
|
197
|
+
seq-studio agents plan [--dir d] [-e <env>] [--only ids] offline bundle plan or live diff
|
|
198
|
+
seq-studio agents apply [--dir d] -e <env> [--only ids] [--yes] apply creates/updates; never deletes
|
|
180
199
|
seq-studio agents list -e <env> list visible agents
|
|
181
200
|
seq-studio agents show <id> -e <env> show one agent
|
|
182
201
|
|
|
183
202
|
Source: local --dir (default .), --repo agents/<name>, or --git-url <url>.
|
|
184
203
|
Use --ref for remote sources. --target selects the deployment APP_ENV when it
|
|
185
|
-
differs from the CLI environment alias (notably OpCo registrations).
|
|
204
|
+
differs from the CLI environment alias (notably OpCo registrations). --only
|
|
205
|
+
accepts a comma-separated list of agent IDs after environment selection.
|
|
186
206
|
`;
|
|
187
207
|
export async function runAgentsCommand(sub, args) {
|
|
188
208
|
try {
|
package/dist/agents/source.d.ts
CHANGED
|
@@ -10,9 +10,11 @@ export declare function materializeAgentSource({ args, requireEnvironment, }: {
|
|
|
10
10
|
source: ResolvedSource;
|
|
11
11
|
context: CommandContext | null;
|
|
12
12
|
}>;
|
|
13
|
-
export declare function compileAgentSource({ directory, targetEnvironment, deployEnvironments, }: {
|
|
13
|
+
export declare function compileAgentSource({ directory, targetEnvironment, deployEnvironments, onlyIds, }: {
|
|
14
14
|
directory: string;
|
|
15
15
|
targetEnvironment?: string;
|
|
16
16
|
/** Registered deployment environments, so a real env absent from the manifest is not read as a typo. */
|
|
17
17
|
deployEnvironments?: readonly string[];
|
|
18
|
+
/** Restrict a plan or apply to explicit agent IDs after environment selection. */
|
|
19
|
+
onlyIds?: readonly string[];
|
|
18
20
|
}): Promise<CompiledAgentBundle>;
|
package/dist/agents/source.js
CHANGED
|
@@ -87,10 +87,25 @@ async function compileManifestEntries({ directory, entries, allowDuplicateIds =
|
|
|
87
87
|
sources: compiled.sources,
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
|
-
export async function compileAgentSource({ directory, targetEnvironment, deployEnvironments = [], }) {
|
|
90
|
+
export async function compileAgentSource({ directory, targetEnvironment, deployEnvironments = [], onlyIds, }) {
|
|
91
91
|
const manifest = await readManifest(directory);
|
|
92
|
-
if (!manifest)
|
|
93
|
-
|
|
92
|
+
if (!manifest) {
|
|
93
|
+
const compiled = await compileAgentDirectory({ rootDir: directory });
|
|
94
|
+
if (!onlyIds || onlyIds.length === 0)
|
|
95
|
+
return compiled;
|
|
96
|
+
const requested = new Set(onlyIds);
|
|
97
|
+
const definitions = compiled.definitions.filter((definition) => requested.has(definition.id));
|
|
98
|
+
const missing = [...requested].filter((id) => !definitions.some((definition) => definition.id === id));
|
|
99
|
+
if (missing.length > 0) {
|
|
100
|
+
throw new Error(`Requested agent IDs were not selected: ${missing.join(', ')}`);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
...compiled,
|
|
104
|
+
definitions,
|
|
105
|
+
hash: hashAgentBundle({ definitions }),
|
|
106
|
+
sources: compiled.sources.filter((source) => requested.has(source.definition.id)),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
94
109
|
if (targetEnvironment !== undefined) {
|
|
95
110
|
assertKnownTargetEnvironment({
|
|
96
111
|
manifest,
|
|
@@ -109,10 +124,18 @@ export async function compileAgentSource({ directory, targetEnvironment, deployE
|
|
|
109
124
|
}
|
|
110
125
|
// With a target: last-wins by id (tenant overrides). Without: every distinct
|
|
111
126
|
// path, so validate still compiles override sources that lose a collapse.
|
|
112
|
-
const
|
|
127
|
+
const selectedEntries = selectAgentEntries({
|
|
113
128
|
manifest,
|
|
114
129
|
environment: targetEnvironment,
|
|
115
130
|
});
|
|
131
|
+
const requested = new Set(onlyIds);
|
|
132
|
+
const entries = requested.size === 0
|
|
133
|
+
? selectedEntries
|
|
134
|
+
: selectedEntries.filter((entry) => requested.has(entry.id));
|
|
135
|
+
const missing = [...requested].filter((id) => !entries.some((entry) => entry.id === id));
|
|
136
|
+
if (missing.length > 0) {
|
|
137
|
+
throw new Error(`Requested agent IDs were not selected: ${missing.join(', ')}`);
|
|
138
|
+
}
|
|
116
139
|
return compileManifestEntries({
|
|
117
140
|
directory,
|
|
118
141
|
entries,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level app monorepo commands:
|
|
3
|
+
* seq-studio init <dir> --with orm,function,artifact
|
|
4
|
+
* seq-studio add <kind> <name>
|
|
5
|
+
* seq-studio deploy -e <env>
|
|
6
|
+
*/
|
|
7
|
+
import type { ParsedArgs } from '../process/commands.js';
|
|
8
|
+
export declare const APP_INIT_USAGE: string;
|
|
9
|
+
export declare const APP_ADD_USAGE = "usage:\n seq-studio add <kind> <name>\n\n Scaffold another primitive into the current app monorepo (must contain\n sequence.app.yml) and append it to the manifest.\n\n Kinds: function | artifact\n (orm is only created at init today)\n\n Examples:\n seq-studio add function list-types\n seq-studio add artifact ui\n\n Run from the app root (directory with sequence.app.yml).\n";
|
|
10
|
+
export declare const APP_DEPLOY_USAGE = "usage:\n seq-studio deploy -e <env> [options]\n\n Deploy every primitive in sequence.app.yml in manifest deploy.order\n (default: orm \u2192 functions \u2192 artifact). Runs each kind's existing command:\n orm \u2192 seq-studio orm apply <path> -e <env>\n function \u2192 seq-studio functions deploy --dir <path> -e <env> [--yes]\n artifact \u2192 seq-studio artifact deploy <path> -e <env>\n\n Options:\n -e, --env <name> target environment (required)\n --dir <path> app root (default: cwd; must contain sequence.app.yml)\n --only <id1,id2> deploy only these primitive ids (order preserved)\n --yes non-interactive (forwarded to functions deploy)\n --dry-run print the plan without deploying\n\n Examples:\n seq-studio deploy -e staging --yes\n seq-studio deploy -e local --only get-pokemon --yes\n seq-studio deploy --dir ./pokedex -e staging --dry-run\n\n Run from the app root (directory with sequence.app.yml), or pass --dir.\n";
|
|
11
|
+
export declare function runAppInitCommand(args: ParsedArgs): Promise<number>;
|
|
12
|
+
export declare function runAppAddCommand({ kindArg, args, }: {
|
|
13
|
+
kindArg: string | undefined;
|
|
14
|
+
args: ParsedArgs;
|
|
15
|
+
}): Promise<number>;
|
|
16
|
+
export declare function runAppDeployCommand(args: ParsedArgs): Promise<number>;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level app monorepo commands:
|
|
3
|
+
* seq-studio init <dir> --with orm,function,artifact
|
|
4
|
+
* seq-studio add <kind> <name>
|
|
5
|
+
* seq-studio deploy -e <env>
|
|
6
|
+
*/
|
|
7
|
+
import { basename, resolve } from 'node:path';
|
|
8
|
+
import { REQUIRE_EXPLICIT_ENV_MESSAGE } from '../env-flags.js';
|
|
9
|
+
import { deployApp } from './deploy.js';
|
|
10
|
+
import { resolveRequestedKinds } from './kinds.js';
|
|
11
|
+
import { APP_MANIFEST_FILENAME, isPrimitiveKind, PRIMITIVE_KINDS, slugifyAppId, } from './manifest.js';
|
|
12
|
+
import { addPrimitiveToApp, defaultScaffoldNames, initAppMonorepo, printInitNextSteps, } from './scaffold.js';
|
|
13
|
+
const LOG = '[seq-studio]';
|
|
14
|
+
export const APP_INIT_USAGE = `usage:
|
|
15
|
+
seq-studio init <dir> --with <kinds> [options]
|
|
16
|
+
seq-studio init <dir> --orm --function --artifact [options]
|
|
17
|
+
|
|
18
|
+
Scaffold an app monorepo with ${APP_MANIFEST_FILENAME} and one subfolder per
|
|
19
|
+
selected primitive. At least one kind is required.
|
|
20
|
+
|
|
21
|
+
Kinds: ${PRIMITIVE_KINDS.join(', ')}
|
|
22
|
+
|
|
23
|
+
Options:
|
|
24
|
+
--with <k1,k2,…> comma-separated kinds to scaffold
|
|
25
|
+
--orm --function … boolean aliases for --with
|
|
26
|
+
--function-name <n> name/slug for the first function (default: hello)
|
|
27
|
+
--description <text> optional app.description in the manifest
|
|
28
|
+
|
|
29
|
+
Examples:
|
|
30
|
+
seq-studio init pokedex --with orm,function,artifact
|
|
31
|
+
seq-studio init pokedex --with orm,function,artifact --function-name get-pokemon
|
|
32
|
+
seq-studio init loan-tools --with function --function-name get-loan
|
|
33
|
+
`;
|
|
34
|
+
export const APP_ADD_USAGE = `usage:
|
|
35
|
+
seq-studio add <kind> <name>
|
|
36
|
+
|
|
37
|
+
Scaffold another primitive into the current app monorepo (must contain
|
|
38
|
+
${APP_MANIFEST_FILENAME}) and append it to the manifest.
|
|
39
|
+
|
|
40
|
+
Kinds: function | artifact
|
|
41
|
+
(orm is only created at init today)
|
|
42
|
+
|
|
43
|
+
Examples:
|
|
44
|
+
seq-studio add function list-types
|
|
45
|
+
seq-studio add artifact ui
|
|
46
|
+
|
|
47
|
+
Run from the app root (directory with ${APP_MANIFEST_FILENAME}).
|
|
48
|
+
`;
|
|
49
|
+
export const APP_DEPLOY_USAGE = `usage:
|
|
50
|
+
seq-studio deploy -e <env> [options]
|
|
51
|
+
|
|
52
|
+
Deploy every primitive in ${APP_MANIFEST_FILENAME} in manifest deploy.order
|
|
53
|
+
(default: orm → functions → artifact). Runs each kind's existing command:
|
|
54
|
+
orm → seq-studio orm apply <path> -e <env>
|
|
55
|
+
function → seq-studio functions deploy --dir <path> -e <env> [--yes]
|
|
56
|
+
artifact → seq-studio artifact deploy <path> -e <env>
|
|
57
|
+
|
|
58
|
+
Options:
|
|
59
|
+
-e, --env <name> target environment (required)
|
|
60
|
+
--dir <path> app root (default: cwd; must contain ${APP_MANIFEST_FILENAME})
|
|
61
|
+
--only <id1,id2> deploy only these primitive ids (order preserved)
|
|
62
|
+
--yes non-interactive (forwarded to functions deploy)
|
|
63
|
+
--dry-run print the plan without deploying
|
|
64
|
+
|
|
65
|
+
Examples:
|
|
66
|
+
seq-studio deploy -e staging --yes
|
|
67
|
+
seq-studio deploy -e local --only get-pokemon --yes
|
|
68
|
+
seq-studio deploy --dir ./pokedex -e staging --dry-run
|
|
69
|
+
|
|
70
|
+
Run from the app root (directory with ${APP_MANIFEST_FILENAME}), or pass --dir.
|
|
71
|
+
`;
|
|
72
|
+
function printError(error) {
|
|
73
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
74
|
+
console.error(`${LOG} ${message}`);
|
|
75
|
+
}
|
|
76
|
+
export async function runAppInitCommand(args) {
|
|
77
|
+
if (args.flags.help === true || args.flags.h === true) {
|
|
78
|
+
console.log(APP_INIT_USAGE);
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
const target = args.positional[0];
|
|
82
|
+
if (!target) {
|
|
83
|
+
console.error(APP_INIT_USAGE);
|
|
84
|
+
return 1;
|
|
85
|
+
}
|
|
86
|
+
let kinds;
|
|
87
|
+
try {
|
|
88
|
+
kinds = resolveRequestedKinds(args.flags);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
printError(error);
|
|
92
|
+
console.error(APP_INIT_USAGE);
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
if (kinds.length === 0) {
|
|
96
|
+
console.error(`${LOG} select at least one primitive via --with orm,function,artifact`);
|
|
97
|
+
console.error(APP_INIT_USAGE);
|
|
98
|
+
return 1;
|
|
99
|
+
}
|
|
100
|
+
const appRoot = resolve(target);
|
|
101
|
+
const appId = slugifyAppId(basename(appRoot));
|
|
102
|
+
if (!appId) {
|
|
103
|
+
console.error(`${LOG} could not derive an app id from "${target}" — use a directory name with letters/numbers`);
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
106
|
+
const names = defaultScaffoldNames(appId);
|
|
107
|
+
if (typeof args.flags['function-name'] === 'string') {
|
|
108
|
+
names.functionName = slugifyAppId(args.flags['function-name']) || names.functionName;
|
|
109
|
+
}
|
|
110
|
+
else if (args.flags['function-name'] === true) {
|
|
111
|
+
console.error(`${LOG} --function-name requires a value`);
|
|
112
|
+
return 1;
|
|
113
|
+
}
|
|
114
|
+
const description = typeof args.flags.description === 'string' ? args.flags.description : undefined;
|
|
115
|
+
if (args.flags.description === true) {
|
|
116
|
+
console.error(`${LOG} --description requires a value`);
|
|
117
|
+
return 1;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const manifest = await initAppMonorepo({
|
|
121
|
+
rootDir: appRoot,
|
|
122
|
+
appId,
|
|
123
|
+
kinds,
|
|
124
|
+
names,
|
|
125
|
+
description,
|
|
126
|
+
});
|
|
127
|
+
printInitNextSteps({ appRoot, manifest });
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
printError(error);
|
|
132
|
+
return 1;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export async function runAppAddCommand({ kindArg, args, }) {
|
|
136
|
+
if (!kindArg || kindArg === 'help' || kindArg === '--help' || kindArg === '-h') {
|
|
137
|
+
console.log(APP_ADD_USAGE);
|
|
138
|
+
return kindArg ? 0 : 1;
|
|
139
|
+
}
|
|
140
|
+
if (!isPrimitiveKind(kindArg)) {
|
|
141
|
+
console.error(`${LOG} unknown kind '${kindArg}' — expected one of: ${PRIMITIVE_KINDS.join(', ')}`);
|
|
142
|
+
console.error(APP_ADD_USAGE);
|
|
143
|
+
return 1;
|
|
144
|
+
}
|
|
145
|
+
if (kindArg === 'orm') {
|
|
146
|
+
console.error(`${LOG} \`seq-studio add orm\` is not supported — orm is created at init`);
|
|
147
|
+
return 1;
|
|
148
|
+
}
|
|
149
|
+
const nameRaw = args.positional[0];
|
|
150
|
+
if (!nameRaw) {
|
|
151
|
+
console.error(`${LOG} usage: seq-studio add ${kindArg} <name>`);
|
|
152
|
+
return 1;
|
|
153
|
+
}
|
|
154
|
+
const name = slugifyAppId(nameRaw);
|
|
155
|
+
if (!name) {
|
|
156
|
+
console.error(`${LOG} invalid name "${nameRaw}" — use kebab-case`);
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
const { entry } = await addPrimitiveToApp({
|
|
161
|
+
rootDir: process.cwd(),
|
|
162
|
+
kind: kindArg,
|
|
163
|
+
name,
|
|
164
|
+
});
|
|
165
|
+
console.log(`${LOG} added ${entry.kind} "${entry.id}" at ${entry.path}`);
|
|
166
|
+
console.log(`${LOG} updated ${APP_MANIFEST_FILENAME}`);
|
|
167
|
+
if (entry.kind === 'function') {
|
|
168
|
+
console.log(`${LOG} next: cd ${entry.path} && pnpm install && seq-studio functions deploy --dir ${entry.path} -e local`);
|
|
169
|
+
}
|
|
170
|
+
return 0;
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
printError(error);
|
|
174
|
+
return 1;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function flagString(flags, key) {
|
|
178
|
+
const value = flags[key];
|
|
179
|
+
return typeof value === 'string' ? value : undefined;
|
|
180
|
+
}
|
|
181
|
+
function flagBool(flags, key) {
|
|
182
|
+
return flags[key] === true;
|
|
183
|
+
}
|
|
184
|
+
export async function runAppDeployCommand(args) {
|
|
185
|
+
if (args.flags.help === true || args.flags.h === true) {
|
|
186
|
+
console.log(APP_DEPLOY_USAGE);
|
|
187
|
+
return 0;
|
|
188
|
+
}
|
|
189
|
+
const env = flagString(args.flags, 'env') ?? flagString(args.flags, 'e');
|
|
190
|
+
if (!env) {
|
|
191
|
+
console.error(`${LOG} ${REQUIRE_EXPLICIT_ENV_MESSAGE}`);
|
|
192
|
+
console.error(APP_DEPLOY_USAGE);
|
|
193
|
+
return 1;
|
|
194
|
+
}
|
|
195
|
+
const dirFlag = flagString(args.flags, 'dir');
|
|
196
|
+
const rootDir = resolve(dirFlag ?? process.cwd());
|
|
197
|
+
let only;
|
|
198
|
+
const onlyRaw = flagString(args.flags, 'only');
|
|
199
|
+
if (args.flags.only === true) {
|
|
200
|
+
console.error(`${LOG} --only requires a comma-separated list of primitive ids`);
|
|
201
|
+
return 1;
|
|
202
|
+
}
|
|
203
|
+
if (onlyRaw) {
|
|
204
|
+
only = onlyRaw
|
|
205
|
+
.split(',')
|
|
206
|
+
.map((part) => part.trim())
|
|
207
|
+
.filter(Boolean);
|
|
208
|
+
if (only.length === 0) {
|
|
209
|
+
console.error(`${LOG} --only requires at least one primitive id`);
|
|
210
|
+
return 1;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
const result = await deployApp({
|
|
215
|
+
rootDir,
|
|
216
|
+
env,
|
|
217
|
+
only,
|
|
218
|
+
yes: flagBool(args.flags, 'yes'),
|
|
219
|
+
dryRun: flagBool(args.flags, 'dry-run'),
|
|
220
|
+
});
|
|
221
|
+
return result.exitCode;
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
printError(error);
|
|
225
|
+
return 1;
|
|
226
|
+
}
|
|
227
|
+
}
|