test(cli): journey for declarative app-var reconciliation
`apply_reconciles_app_vars` drives the full cycle through `pic` against a
real server: a manifest `[vars] region = "eu"` is applied (var created +
injected — a script `vars::get("region")` returns "eu"), the value is
changed and re-applied (Update, returns "us"), then the var is dropped and
`apply --prune` removes it (`vars::get` resolves to `()` / JSON null).
Exercises the Bundle.vars wire, diff_vars create/update/delete, the in-tx
writes, and the runtime resolver end to end.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -151,3 +151,105 @@ fn apply_rejects_bad_bundle_atomically() {
|
||||
"a failed apply must leave nothing behind:\n{s}"
|
||||
);
|
||||
}
|
||||
|
||||
#[ignore = "needs DATABASE_URL pointing at a running Postgres"]
|
||||
#[test]
|
||||
fn apply_reconciles_app_vars() {
|
||||
let Some(fx) = common::fixture_or_skip() else {
|
||||
return;
|
||||
};
|
||||
let env = common::admin_env(fx);
|
||||
let slug = common::unique_slug("apply-vars");
|
||||
common::pic_as(&env)
|
||||
.args(["apps", "create", &slug])
|
||||
.assert()
|
||||
.success();
|
||||
let _guard = AppGuard::new(&env.url, &env.token, &slug);
|
||||
|
||||
let dir = manifest_dir();
|
||||
// The script returns the resolved `region` var verbatim, so an invoke
|
||||
// reflects exactly what `apply` wrote.
|
||||
fs::write(
|
||||
dir.path().join("scripts/read.rhai"),
|
||||
"vars::get(\"region\")",
|
||||
)
|
||||
.unwrap();
|
||||
let manifest = |vars_block: &str| {
|
||||
format!(
|
||||
"[app]\nslug = \"{slug}\"\nname = \"Vars Test\"\n\n\
|
||||
[[scripts]]\nname = \"read\"\nfile = \"scripts/read.rhai\"\n\n\
|
||||
[[routes]]\nscript = \"read\"\nmethod = \"POST\"\n\
|
||||
host_kind = \"any\"\npath_kind = \"exact\"\npath = \"/read\"\n\n\
|
||||
{vars_block}"
|
||||
)
|
||||
};
|
||||
let manifest_path = dir.path().join("picloud.toml");
|
||||
|
||||
// 1. Apply with `region = "eu"` → the var is created and injected.
|
||||
fs::write(&manifest_path, manifest("[vars]\nregion = \"eu\"\n")).unwrap();
|
||||
let out = common::pic_as(&env)
|
||||
.args(["apply", "--file"])
|
||||
.arg(&manifest_path)
|
||||
.output()
|
||||
.expect("apply");
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"apply failed: {}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let id = script_id(&env, &slug);
|
||||
assert_eq!(
|
||||
invoke_body(&env, &id),
|
||||
serde_json::json!("eu"),
|
||||
"var applied"
|
||||
);
|
||||
|
||||
// 2. Change the value → Update (not Create).
|
||||
fs::write(&manifest_path, manifest("[vars]\nregion = \"us\"\n")).unwrap();
|
||||
common::pic_as(&env)
|
||||
.args(["apply", "--file"])
|
||||
.arg(&manifest_path)
|
||||
.assert()
|
||||
.success();
|
||||
assert_eq!(
|
||||
invoke_body(&env, &id),
|
||||
serde_json::json!("us"),
|
||||
"var updated"
|
||||
);
|
||||
|
||||
// 3. Drop the var + `--prune` → Delete; `vars::get` now returns `()`.
|
||||
fs::write(&manifest_path, manifest("")).unwrap();
|
||||
common::pic_as(&env)
|
||||
.args(["apply", "--file"])
|
||||
.arg(&manifest_path)
|
||||
.args(["--prune", "--yes"])
|
||||
.assert()
|
||||
.success();
|
||||
assert_eq!(
|
||||
invoke_body(&env, &id),
|
||||
serde_json::Value::Null,
|
||||
"var pruned → unresolved"
|
||||
);
|
||||
}
|
||||
|
||||
fn script_id(env: &common::TestEnv, slug: &str) -> String {
|
||||
let ls = common::pic_as(env)
|
||||
.args(["scripts", "ls", "--app", slug])
|
||||
.output()
|
||||
.expect("scripts ls");
|
||||
common::parse_first_id(std::str::from_utf8(&ls.stdout).unwrap())
|
||||
.expect("scripts ls should produce one row")
|
||||
}
|
||||
|
||||
fn invoke_body(env: &common::TestEnv, id: &str) -> serde_json::Value {
|
||||
let out = common::pic_as(env)
|
||||
.args(["scripts", "invoke", id])
|
||||
.output()
|
||||
.expect("scripts invoke");
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"invoke failed: {}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
serde_json::from_slice(&out.stdout).expect("invoke body is JSON")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user