From 181622a84a9a6170f4b26038f7162d4cc70dee28 Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Thu, 25 Jun 2026 08:03:26 +0200 Subject: [PATCH] feat(cli): `pic pull` exports an app's own vars into `[vars]` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Completes the vars round-trip: pull now fetches the app's OWN env-agnostic vars (`vars_list` filtered to scope `*`, non-tombstone) and writes them into the manifest `[vars]` block, alongside scripts/routes/secrets. Inherited group vars stay out (pull exports own rows only, §4.6); a value TOML can't represent (e.g. JSON null) is skipped with a warning. So `pic pull` → edit → `pic apply` is now lossless for app config vars. Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/picloud-cli/src/cmds/pull.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/picloud-cli/src/cmds/pull.rs b/crates/picloud-cli/src/cmds/pull.rs index 628617c..bf2124f 100644 --- a/crates/picloud-cli/src/cmds/pull.rs +++ b/crates/picloud-cli/src/cmds/pull.rs @@ -49,6 +49,24 @@ pub async fn run(app_ident: &str, dir: &Path, force: bool, mode: OutputMode) -> .secrets_list(VarOwnerArg::App(app_ident), None) .await? .secrets; + // App's OWN env-agnostic vars become the manifest `[vars]` block. Inherited + // group vars and tombstones are excluded (pull exports own rows only, §4.6); + // a value TOML can't represent (e.g. JSON null) is skipped with a warning. + let mut manifest_vars = std::collections::BTreeMap::new(); + for v in client.vars_list(VarOwnerArg::App(app_ident)).await?.vars { + if v.env != "*" || v.is_tombstone { + continue; + } + match toml::Value::try_from(&v.value) { + Ok(tv) => { + manifest_vars.insert(v.key, tv); + } + Err(_) => eprintln!( + "warning: skipping var `{}` — its value can't be represented in TOML", + v.key + ), + } + } let name_by_id: HashMap = scripts.iter().map(|s| (s.id, s.name.clone())).collect(); @@ -204,7 +222,7 @@ pub async fn run(app_ident: &str, dir: &Path, force: bool, mode: OutputMode) -> secrets: ManifestSecrets { names: secrets.iter().map(|s| s.name.clone()).collect(), }, - vars: std::collections::BTreeMap::new(), + vars: manifest_vars, }; std::fs::write(&manifest_path, manifest.to_toml()?)