The §11 Phase-1 `config --effective` surface. Single-app today, "config" = the app's secrets, so it cross-references the manifest's declared secret names against what's set on the server and renders each masked: `<set>` (managed / on-server-not-in-manifest) or `<unset>` (declared but not pushed). Values are never fetched or shown (§4.6). Shaped to grow an `--explain` mode and inherited `vars` when groups/vars arrive (Phase 3). Tested: a journey verifying declared-but-unset → `<unset>`, post-`secret set` → `<set>`/managed, and the value never appears in output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
58 lines
1.8 KiB
Rust
58 lines
1.8 KiB
Rust
//! `pic config --effective` — masked secret resolution against the manifest.
|
|
|
|
use std::fs;
|
|
|
|
use predicates::prelude::*;
|
|
use tempfile::TempDir;
|
|
|
|
use crate::common;
|
|
use crate::common::cleanup::AppGuard;
|
|
|
|
#[ignore = "needs DATABASE_URL pointing at a running Postgres"]
|
|
#[test]
|
|
fn config_effective_masks_and_classifies_secrets() {
|
|
let Some(fx) = common::fixture_or_skip() else {
|
|
return;
|
|
};
|
|
let env = common::admin_env(fx);
|
|
let slug = common::unique_slug("config");
|
|
common::pic_as(&env)
|
|
.args(["apps", "create", &slug])
|
|
.assert()
|
|
.success();
|
|
let _guard = AppGuard::new(&env.url, &env.token, &slug);
|
|
|
|
let dir = TempDir::new().unwrap();
|
|
let manifest_path = dir.path().join("picloud.toml");
|
|
fs::write(
|
|
&manifest_path,
|
|
format!("[app]\nslug = \"{slug}\"\nname = \"Cfg\"\n\n[secrets]\nnames = [\"API_KEY\"]\n"),
|
|
)
|
|
.unwrap();
|
|
|
|
// Declared but not pushed → masked + flagged unset; value never shown.
|
|
common::pic_as(&env)
|
|
.args(["config", "--effective", "--file"])
|
|
.arg(&manifest_path)
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("API_KEY"))
|
|
.stdout(predicate::str::contains("<unset>"))
|
|
.stdout(predicate::str::contains("not pushed"));
|
|
|
|
// Push it → now masked as <set> / managed, still never the value.
|
|
common::pic_as(&env)
|
|
.args(["secrets", "set", "--app", &slug, "API_KEY"])
|
|
.write_stdin("super-secret-value")
|
|
.assert()
|
|
.success();
|
|
common::pic_as(&env)
|
|
.args(["config", "--effective", "--file"])
|
|
.arg(&manifest_path)
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("<set>"))
|
|
.stdout(predicate::str::contains("managed"))
|
|
.stdout(predicate::str::contains("super-secret-value").not());
|
|
}
|