octwin-cli 0.8.3 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,25 @@ Format: [Keep a Changelog](https://keepachangelog.com/) — newest first, bucket
5
5
  **Added · Changed · Deprecated · Removed · Fixed · Security**. The platform-wide view lives in the
6
6
  repo root [`CHANGELOG.md`](../../CHANGELOG.md); this file is the CLI-only cut that ships with the package.
7
7
 
8
+ ## [0.8.4] - 2026-09-02
9
+
10
+ ### Fixed
11
+ - **A deploy whose seed failed still led with `✓ Deployed`.** The step errors were never
12
+ missing — `readDeployProgress` has collected every `status:'error'` frame into `stepErrors`
13
+ since 0.1.14, printed them, and exited non-zero. They were printed *after* `printDeploySuccess`,
14
+ so the first and largest line said `✓ Deployed` and the ⚠ came underneath. A pack author
15
+ reported their deploy as a clean success while its demo seed had failed; they were reading the
16
+ transcript exactly as written. The count now goes INTO the headline, which reads
17
+ `⚠ Deployed <id>@<v> onto <target> WITH n failure(s) — data may be incomplete`. `octwin seed`
18
+ gets the same treatment. *A signal that arrives after the verdict is not a signal.*
19
+ - **The non-streaming deploy and seed paths had no step-error check at all.** With no SSE frames
20
+ to read, a failed seed printed a clean `✓` on that path even after the streaming one was fixed
21
+ in 0.1.14. Both now read `seed_failed` from the response body (new in the platform alongside
22
+ this release), print each failed kind with its reason, and exit non-zero.
23
+ - **A partial demo seed is now reported as partial.** The platform no longer abandons the rest of
24
+ the seed when one demo row throws, so `Seeded:` gains an `n row(s) FAILED` part — without it a
25
+ partial seed reads as a complete one that simply had fewer records than the author wrote.
26
+
8
27
  ## [0.8.3] - 2026-09-02
9
28
 
10
29
  ### Fixed
package/dist/index.js CHANGED
@@ -1535,8 +1535,22 @@ function printPublicListing(state, note, live, justAsked = false) {
1535
1535
  break;
1536
1536
  }
1537
1537
  }
1538
- function printDeploySuccess(id, version, t, r, listing) {
1539
- console.log(`✓ Deployed ${id}@${version} and installed onto ${targetLabel(t)}`);
1538
+ /**
1539
+ * THE HEADLINE MUST BE HONEST, because it is the line people actually read.
1540
+ *
1541
+ * The step errors were never missing — `readDeployProgress` has collected them since
1542
+ * 0.1.14, and the caller prints them and exits non-zero. But it printed them AFTER this
1543
+ * function, so the first and largest line said `✓ Deployed` and the ⚠ came underneath.
1544
+ * A pack author reported the deploy as a clean success while its demo seed had failed;
1545
+ * they were reading the transcript exactly as it was written.
1546
+ *
1547
+ * So `problems` is passed IN rather than handled by the caller afterwards: a signal that
1548
+ * arrives after the verdict is not a signal.
1549
+ */
1550
+ function printDeploySuccess(id, version, t, r, listing, problems = 0) {
1551
+ console.log(problems > 0
1552
+ ? `⚠ Deployed ${id}@${version} onto ${targetLabel(t)} WITH ${problems} failure(s) — data may be incomplete`
1553
+ : `✓ Deployed ${id}@${version} and installed onto ${targetLabel(t)}`);
1540
1554
  if (r?.warning)
1541
1555
  console.log(` ⚠ ${r.warning}`);
1542
1556
  const s = r?.summary;
@@ -1550,6 +1564,11 @@ function printDeploySuccess(id, version, t, r, listing) {
1550
1564
  parts.push(`${s.images} image(s) generated`);
1551
1565
  if (s.rules)
1552
1566
  parts.push(`${s.rules} availability rule(s)`);
1567
+ // A count of rows that threw. The seed keeps going past a bad row now, so a
1568
+ // partial seed is a real outcome and has to be said out loud — the alternative
1569
+ // reads as a complete one with fewer records than the author wrote.
1570
+ if (s.failed)
1571
+ parts.push(`${s.failed} row(s) FAILED`);
1553
1572
  if (parts.length)
1554
1573
  console.log(` Seeded: ${parts.join(', ')}`);
1555
1574
  }
@@ -1596,8 +1615,9 @@ async function cmdSeed(flags) {
1596
1615
  const { terminal: final, stepErrors } = await readDeployProgress(res.body);
1597
1616
  if (!final || final.stage === 'error')
1598
1617
  die(`seed failed${final?.message ? `: ${final.message}` : ' (stream ended early)'}`);
1599
- console.log(`
1600
- ${final.message ?? 'seed complete'}`);
1618
+ // Same rule as `printDeploySuccess`: the verdict leads. A ✓ above the failures
1619
+ // is the line that gets read and quoted.
1620
+ console.log(`\n${stepErrors.length ? '⚠' : '✓'} ${final.message ?? 'seed complete'}`);
1601
1621
  printSeedCounts(final.result?.seeded);
1602
1622
  if (stepErrors.length) {
1603
1623
  // A kind failed but the rest ran — the reconcile softens each step. Say which,
@@ -1623,8 +1643,15 @@ async function cmdSeed(flags) {
1623
1643
  printAuthHint(res.status, url);
1624
1644
  exitNow(1);
1625
1645
  }
1626
- console.log('✓ seed complete');
1646
+ // No frames on this path — `seed_failed` in the body is the only evidence a kind threw.
1647
+ const failedKinds = Object.entries((json?.seed_failed ?? {}));
1648
+ console.log(failedKinds.length ? `⚠ seed INCOMPLETE — ${failedKinds.length} kind(s) failed` : '✓ seed complete');
1627
1649
  printSeedCounts(json?.seeded);
1650
+ if (failedKinds.length) {
1651
+ for (const [kind, why] of failedKinds)
1652
+ console.error(` • ${kind}: ${why}`);
1653
+ exitNow(1);
1654
+ }
1628
1655
  }
1629
1656
  /** Per-kind counts, one line each. Prints nothing when the pack declared nothing. */
1630
1657
  function printSeedCounts(seeded) {
@@ -1658,12 +1685,14 @@ async function cmdDeploy(flags) {
1658
1685
  const { terminal: final, stepErrors } = await readDeployProgress(res.body);
1659
1686
  if (!final || final.stage === 'error')
1660
1687
  die(`deploy failed${final?.message ? `: ${final.message}` : ' (stream ended early)'}`);
1661
- printDeploySuccess(id, version, t, final, { intent: listing, packDir });
1688
+ // The count goes IN, so the headline itself carries the verdict. It used to be
1689
+ // printed underneath a `✓ Deployed` line, which is what a reporting author read.
1690
+ printDeploySuccess(id, version, t, final, { intent: listing, packDir }, stepErrors.length);
1662
1691
  if (stepErrors.length) {
1663
- // The pack IS installed, but a step (e.g. the demo seed) failed — say so
1664
- // plainly and exit non-zero so CI / a `deploy && chat` chain doesn't treat
1665
- // an incomplete install as a clean success.
1666
- console.error(`\n⚠ Deployed with ${stepErrors.length} warning${stepErrors.length === 1 ? '' : 's'} — data may be incomplete:`);
1692
+ // The pack IS installed, but a step (e.g. the demo seed) failed — list what,
1693
+ // and exit non-zero so CI / a `deploy && chat` chain doesn't treat an
1694
+ // incomplete install as a clean success.
1695
+ console.error(`\nFailures:`);
1667
1696
  for (const e of stepErrors)
1668
1697
  console.error(` • ${e}`);
1669
1698
  exitNow(1);
@@ -1686,7 +1715,17 @@ async function cmdDeploy(flags) {
1686
1715
  console.error(typeof json === 'string' ? json : JSON.stringify(json, null, 2));
1687
1716
  exitNow(1);
1688
1717
  }
1689
- printDeploySuccess(id, version, t, json, { intent: listing, packDir });
1718
+ // This path had NO step-error check at all. With no SSE frames to read, the only
1719
+ // evidence a seed kind threw is `seed_failed` in the body — so a broken seed printed
1720
+ // a clean `✓ Deployed` here even after the streaming path was fixed in 0.1.14.
1721
+ const failedKinds = Object.entries((json?.seed_failed ?? {}));
1722
+ printDeploySuccess(id, version, t, json, { intent: listing, packDir }, failedKinds.length);
1723
+ if (failedKinds.length) {
1724
+ console.error(`\nFailures:`);
1725
+ for (const [kind, why] of failedKinds)
1726
+ console.error(` • ${kind}: ${why}`);
1727
+ exitNow(1);
1728
+ }
1690
1729
  }
1691
1730
  /**
1692
1731
  * The QUALIFIED pack id (`<owner>.<name>`) for a manifest's bare name.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "octwin-cli",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "description": "Octwin external-pack developer CLI (by CEQUENS) — scaffold, validate, deploy, and check pure-YAML packs on your tenant.",
5
5
  "type": "module",
6
6
  "bin": {