feat(cli): [group] manifest + pic plan/apply for a group node (Phase 5 C2)
Phase 5 C2. A `picloud.toml` can now declare a `[group]` node (instead of
`[app]`): the group's own scripts + `[vars]` (+ secret names). `pic plan` /
`pic apply` reconcile it via the C1 group endpoints — the same plan/apply/
bound-token flow as an app, routed by node kind.
* `Manifest` is now app-XOR-group: `app`/`group` are both optional with an
exactly-one check in `parse`, plus a group-node guard that rejects
`[[routes]]`/`[[triggers]]` (those bind to an app). Accessors `slug()` /
`is_group()` replace the hardcoded `manifest.app.slug`.
* `client`: `plan_node`/`apply_node` take a `NodeKind { App | Group }` that
selects the `apps` vs `groups` API path; the old `plan`/`apply` wrappers
are gone (callers pass the kind).
* `pic plan`/`apply` detect the node kind from the manifest and label output
`group`/`app`; `pic config --effective` cleanly rejects a group manifest
(effective config is an app's inherited view).
Live-validated: a `[group]` manifest with a script + var → `pic plan` (script
+ var creates) → `pic apply` (group-owned) → idempotent re-plan noop →
`pic scripts ls --group` shows it. Manifest unit test for group parse +
app-only-block rejection; init/pull/plan/apply/overlay journeys all green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,8 +45,14 @@ pub async fn run(
|
||||
// masked report targets the app those commands would act on — not the
|
||||
// base slug — when an overlay re-points slug/secrets.
|
||||
let manifest = Manifest::load_with_env(manifest_path, env)?;
|
||||
if manifest.is_group() {
|
||||
bail!(
|
||||
"`pic config --effective` resolves an APP's inherited config; \
|
||||
a [group] manifest has no single effective view"
|
||||
);
|
||||
}
|
||||
|
||||
let eff = client.config_effective(&manifest.app.slug).await?;
|
||||
let eff = client.config_effective(manifest.slug()).await?;
|
||||
|
||||
// --- vars: the resolved view, with winning owner + provenance. ---
|
||||
let mut vars_table = Table::new(["key", "value", "owner", "scope"]);
|
||||
|
||||
Reference in New Issue
Block a user