P3.4a: dist ci publish happy path + persistence (manifest->store->validate->publish->db.json->JSON)
Real local publish success pipeline replacing the ci-publish stub: validate manifest, find/create app + draft release, per-artifact content-address store (P2.2) + common validation (P3.3) with optional manifest-declared size/sha256 (PO ruling), publish via the repo integrity transaction with channel promotion + audit events (P2.3), persist db.json (P2.3), emit stable JSON (release id, artifact ids, sha256, file:// URLs) with --json purity. make publish-example target + tests/publish_happy.sx (fail-before/pass-after). Salvaged from a worker that completed the work (make test 10/10) but hit the 50-min wall before committing; manager-verified at ground truth (make test green, make publish-example exit 0, stored object re-hashes to its key via shasum, db.json records release/2 artifacts/ channel/4 audit events).
This commit is contained in:
@@ -8,10 +8,13 @@
|
||||
//
|
||||
// 1. no args → human help/usage on STDERR + EX_USAGE (64).
|
||||
// 2. unknown command → human error on STDERR + EX_USAGE (64).
|
||||
// 3. `ci publish --json` → STDOUT is a SINGLE valid JSON object (parses
|
||||
// via std.json with no trailing junk); the human acknowledgement is
|
||||
// on STDERR, never stdout.
|
||||
// 3. `release promote --json` → STDOUT is a SINGLE valid JSON object
|
||||
// (parses via std.json with no trailing junk); the human acknowledgement
|
||||
// is on STDERR, never stdout. (`release promote` is still a stub; the
|
||||
// real `ci publish` json output is exercised by publish_happy.sx.)
|
||||
// 4. `--help` → lists the `ci` / `release` groups, exits 0.
|
||||
// 5. `ci publish --json` with NO required flags → EX_USAGE (64), error on
|
||||
// stderr (the --manifest / --local-store contract).
|
||||
//
|
||||
// `make test` depends on `build`, so `build/dist` exists before this runs;
|
||||
// the relative path resolves from the repo root (the `make test` cwd).
|
||||
@@ -65,27 +68,27 @@ main :: () -> s32 {
|
||||
// ── 3a. `--json` stdout purity: a single valid JSON object, nothing
|
||||
// else. `2>/dev/null` drops the human note so the pipe carries
|
||||
// ONLY stdout; std.json.parse rejects trailing junk. ─────────
|
||||
if r := proc.run("build/dist ci publish --json 2>/dev/null") {
|
||||
if r := proc.run("build/dist release promote --json 2>/dev/null") {
|
||||
proc.assert(r.exit_code == 0, "stub --json command must succeed (EX_OK)");
|
||||
v, e := json.parse(r.stdout, xx gpa);
|
||||
proc.assert(!e, "stdout in --json mode must be a single valid JSON object (parse failed / trailing junk)");
|
||||
if !e {
|
||||
o := v.object;
|
||||
proc.assert(o.len == 3, "stub json object carries command/status/stub");
|
||||
proc.assert(o.items[0].key == "command" and o.items[0].val.str == "ci publish",
|
||||
proc.assert(o.items[0].key == "command" and o.items[0].val.str == "release promote",
|
||||
"stub json names the dispatched command");
|
||||
proc.assert(o.items[1].key == "status" and o.items[1].val.str == "ok",
|
||||
"stub json reports status ok");
|
||||
}
|
||||
} else {
|
||||
proc.assert(false, "spawn build/dist ci publish --json failed");
|
||||
proc.assert(false, "spawn build/dist release promote --json failed");
|
||||
}
|
||||
|
||||
// ── 3b. `--json` mode keeps human text on STDERR (not stdout) ──────
|
||||
if r := proc.run("build/dist ci publish --json 2>&1 1>/dev/null") {
|
||||
if r := proc.run("build/dist release promote --json 2>&1 1>/dev/null") {
|
||||
proc.assert(r.stdout.len > 0, "--json mode must still emit human text to stderr");
|
||||
} else {
|
||||
proc.assert(false, "spawn build/dist ci publish --json (stderr) failed");
|
||||
proc.assert(false, "spawn build/dist release promote --json (stderr) failed");
|
||||
}
|
||||
|
||||
// ── 4. `--help` lists the ci / release groups, exits 0 ────────────
|
||||
@@ -97,6 +100,16 @@ main :: () -> s32 {
|
||||
proc.assert(false, "spawn build/dist --help failed");
|
||||
}
|
||||
|
||||
// ── 5. `ci publish` requires --manifest / --local-store ───────────
|
||||
// Missing a required flag is a usage error: EX_USAGE (64), human
|
||||
// diagnostic on stderr (`2>&1 1>/dev/null` captures the stderr text).
|
||||
if r := proc.run("build/dist ci publish --json 2>&1 1>/dev/null") {
|
||||
proc.assert(r.exit_code == 64, "ci publish without required flags must exit EX_USAGE (64)");
|
||||
proc.assert(contains(r.stdout, "missing required flag"), "missing-flag error names the failure on stderr");
|
||||
} else {
|
||||
proc.assert(false, "spawn build/dist ci publish (no flags) failed");
|
||||
}
|
||||
|
||||
print("cli_dispatch: ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user