//! `pic apply --prune` journey: a resource dropped from the manifest //! survives a plain (additive) apply but is deleted with `--prune`. use std::fs; use tempfile::TempDir; use crate::common; use crate::common::cleanup::AppGuard; fn scripts_ls(env: &common::TestEnv, slug: &str) -> String { String::from_utf8( common::pic_as(env) .args(["scripts", "ls", "--app", slug]) .output() .unwrap() .stdout, ) .unwrap() } #[ignore = "needs DATABASE_URL pointing at a running Postgres"] #[test] fn prune_deletes_stale_resources() { let Some(fx) = common::fixture_or_skip() else { return; }; let env = common::admin_env(fx); let slug = common::unique_slug("prune"); common::pic_as(&env) .args(["apps", "create", &slug]) .assert() .success(); let _guard = AppGuard::new(&env.url, &env.token, &slug); let dir = TempDir::new().unwrap(); fs::create_dir_all(dir.path().join("scripts")).unwrap(); fs::write(dir.path().join("scripts/keep.rhai"), "let x = 1; x").unwrap(); fs::write(dir.path().join("scripts/drop.rhai"), "let y = 2; y").unwrap(); let manifest_path = dir.path().join("picloud.toml"); // v1: two scripts + a route on `drop`. let v1 = format!( "[app]\nslug = \"{slug}\"\nname = \"Prune Test\"\n\n\ [[scripts]]\nname = \"keep\"\nfile = \"scripts/keep.rhai\"\n\n\ [[scripts]]\nname = \"drop\"\nfile = \"scripts/drop.rhai\"\n\n\ [[routes]]\nscript = \"drop\"\nmethod = \"GET\"\n\ host_kind = \"any\"\npath_kind = \"exact\"\npath = \"/drop\"\n" ); fs::write(&manifest_path, &v1).unwrap(); common::pic_as(&env) .args(["apply", "--file"]) .arg(&manifest_path) .assert() .success(); // v2: drop `drop` and its route. let v2 = format!( "[app]\nslug = \"{slug}\"\nname = \"Prune Test\"\n\n\ [[scripts]]\nname = \"keep\"\nfile = \"scripts/keep.rhai\"\n" ); fs::write(&manifest_path, &v2).unwrap(); // Plain apply is additive — `drop` survives. common::pic_as(&env) .args(["apply", "--file"]) .arg(&manifest_path) .assert() .success(); assert!( scripts_ls(&env, &slug).contains("drop"), "additive apply must not delete" ); // Prune apply removes `drop` and its route. let out = common::pic_as(&env) .args(["apply", "--file"]) .arg(&manifest_path) .arg("--prune") .output() .expect("apply --prune"); assert!( out.status.success(), "prune failed: {}", String::from_utf8_lossy(&out.stderr) ); let report = String::from_utf8(out.stdout).unwrap(); assert!( report.contains("-1"), "expected deletions in report:\n{report}" ); let s = scripts_ls(&env, &slug); assert!(!s.contains("drop"), "prune should delete `drop`:\n{s}"); assert!(s.contains("keep"), "prune must keep `keep`:\n{s}"); // Plan is clean after prune. let p = String::from_utf8( common::pic_as(&env) .args(["plan", "--file"]) .arg(&manifest_path) .output() .unwrap() .stdout, ) .unwrap(); assert!( !p.contains("delete"), "plan should be clean after prune:\n{p}" ); }