@platforma-sdk/block-tools 2.14.5 → 2.15.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/block-tools",
3
- "version": "2.14.5",
3
+ "version": "2.15.0",
4
4
  "description": "Utility to manipulate Platforma Blocks and Block Registry",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {
@@ -36,12 +36,12 @@
36
36
  "zod": "~3.25.76",
37
37
  "@milaboratories/pl-http": "1.2.4",
38
38
  "@milaboratories/pl-model-common": "1.48.0",
39
- "@milaboratories/pl-model-middle-layer": "1.32.0",
40
39
  "@milaboratories/ts-helpers": "1.8.6",
41
- "@platforma-sdk/package-builder-lib": "1.3.0",
40
+ "@milaboratories/pl-model-middle-layer": "1.32.0",
42
41
  "@milaboratories/resolve-helper": "1.1.3",
42
+ "@milaboratories/pl-model-backend": "1.4.23",
43
43
  "@platforma-sdk/blocks-deps-updater": "2.2.0",
44
- "@milaboratories/pl-model-backend": "1.4.22"
44
+ "@platforma-sdk/package-builder-lib": "1.4.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@rollup/plugin-node-resolve": "^16.0.1",
@@ -22,6 +22,9 @@ function fakeBuilder() {
22
22
  publishDockerImages: vi.fn(rec("publishDockerImages")),
23
23
  publishPackages: vi.fn(async () => void calls.push("publishPackages")),
24
24
  buildSwJsonFiles: vi.fn(rec("buildSwJsonFiles")),
25
+ // A guard, not a build step: kept out of `calls` so the order assertions stay
26
+ // about what the pass actually builds and pushes.
27
+ assertDockerCoverage: vi.fn(),
25
28
  };
26
29
  return { core: core as unknown as Builder, calls, spies: core };
27
30
  }
@@ -127,6 +130,47 @@ describe("runBuild orchestration", () => {
127
130
  ]);
128
131
  });
129
132
 
133
+ it("checks docker coverage up front, so a doomed build fails before it builds", async () => {
134
+ const b = await run({ channel: "release", location: "remote" });
135
+ expect(b.spies.assertDockerCoverage).toHaveBeenCalled();
136
+ expect(b.spies.assertDockerCoverage.mock.invocationCallOrder[0]).toBeLessThan(
137
+ b.spies.buildDockerImages.mock.invocationCallOrder[0],
138
+ );
139
+ });
140
+
141
+ it("skips the coverage check when the scenario describes no software at all", async () => {
142
+ const b = await run({ variant: "none" });
143
+ expect(b.spies.assertDockerCoverage).not.toHaveBeenCalled();
144
+ expect(b.spies.buildSwJsonFiles).toHaveBeenCalledWith(
145
+ expect.objectContaining({ skipDockerCoverage: true }),
146
+ );
147
+ });
148
+
149
+ // `build:dev-binary-existing` builds nothing: the descriptor points at an artifact whose
150
+ // coverage was settled when it was released, so this run answers for none of it.
151
+ it("skips the coverage check when pointing at an already-published binary", async () => {
152
+ const b = await run({ usePublished: true });
153
+ expect(b.spies.assertDockerCoverage).not.toHaveBeenCalled();
154
+ expect(b.spies.buildSwJsonFiles).toHaveBeenCalledWith(
155
+ expect.objectContaining({ skipDockerCoverage: true }),
156
+ );
157
+ });
158
+
159
+ it("keeps the coverage check on the scenarios that do build software", async () => {
160
+ for (const knobs of [
161
+ { channel: "release", location: "remote" },
162
+ { channel: "dev", location: "remote" },
163
+ { channel: "dev", location: "local" },
164
+ {},
165
+ ] as const) {
166
+ const b = await run(knobs);
167
+ expect(b.spies.assertDockerCoverage).toHaveBeenCalled();
168
+ expect(b.spies.buildSwJsonFiles).toHaveBeenCalledWith(
169
+ expect.objectContaining({ skipDockerCoverage: false }),
170
+ );
171
+ }
172
+ });
173
+
130
174
  it("dev docker build targets the built-in dev registry; release the production registry", async () => {
131
175
  const dev = await run({ channel: "dev", variant: "docker", location: "remote" });
132
176
  expect(dev.spies.buildDockerImages).toHaveBeenCalledWith(
@@ -36,6 +36,15 @@ export async function runBuild(params: {
36
36
  const ids = opts.ids;
37
37
  core.buildMode = buildModeForScenario(scenario);
38
38
 
39
+ // Software with no docker variant cannot run on a k8s install, and the answer comes
40
+ // from package.json alone — so a CI run that cannot produce a runnable release says
41
+ // so before building anything. Two scenarios build no software and therefore answer
42
+ // for none: `no-software` describes none at all, and `binary-existing` points the
43
+ // descriptor at an artifact whose coverage was settled when it was released. The
44
+ // engine also skips dev-local builds, whose descriptors never reach a cluster;
45
+ // buildSwJsonFiles re-checks whatever the remaining scenarios end up writing.
46
+ if (!buildsNoSoftware(scenario)) core.assertDockerCoverage();
47
+
39
48
  const buildBinary = () =>
40
49
  core.buildSoftwareArchives({
41
50
  ids,
@@ -109,7 +118,16 @@ export async function runBuild(params: {
109
118
  }
110
119
 
111
120
  // DESCRIPTOR LAST — only after build + push have succeeded.
112
- core.buildSwJsonFiles({ packageIds: ids, noSoftware: scenario.kind === "no-software" });
121
+ core.buildSwJsonFiles({
122
+ packageIds: ids,
123
+ noSoftware: scenario.kind === "no-software",
124
+ skipDockerCoverage: buildsNoSoftware(scenario),
125
+ });
126
+ }
127
+
128
+ // Scenarios that build no software of their own, so they answer for no docker coverage.
129
+ function buildsNoSoftware(scenario: Scenario): boolean {
130
+ return scenario.kind === "no-software" || scenario.kind === "binary-existing";
113
131
  }
114
132
 
115
133
  function buildModeForScenario(scenario: Scenario): util.BuildMode {