@xemahq/xema 0.33.2 → 0.33.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.
@@ -17,7 +17,7 @@ import { join, resolve } from 'node:path';
17
17
 
18
18
  import { isDevelopImageRef } from './develop-image-coordinate.mjs';
19
19
  import { EDITION_CHART_SET_FILE, assertRosteredChartSetLock } from './edition-chart-set.mjs';
20
- import { EditionChannel, EditionLockFile } from './edition-constants.mjs';
20
+ import { EditionLockFile } from './edition-constants.mjs';
21
21
  import { isEntryModule } from './edition-workspace.mjs';
22
22
 
23
23
  /** Throws when `value` (a parsed JSON document) names a develop image repository. `where` names it in the refusal. */
@@ -30,10 +30,9 @@ export function assertReleaseContent(value, where) {
30
30
  'a release lock names release repositories only',
31
31
  );
32
32
  }
33
- // A chart-set lock (one with a roster of publishers) carries release chart
34
- // coordinates only: a develop chart set copied into a release is refused.
33
+ // A chart-set lock (one with a roster of publishers) carries content coordinates only.
35
34
  if (Array.isArray(value.publishers)) {
36
- assertRosteredChartSetLock(value, where, EditionChannel.Release);
35
+ assertRosteredChartSetLock(value, where);
37
36
  }
38
37
  }
39
38
 
@@ -123,7 +123,7 @@ export async function readCommittedEdition(id, root = editionsRoot()) {
123
123
  distributionLock,
124
124
  imageLock: read(EditionLockFile.Images),
125
125
  authorizationLock: read(EditionLockFile.Authorization),
126
- chartSetLock: assertRosteredChartSetLock(read(EditionLockFile.ChartSet), join(dir, EditionLockFile.ChartSet), EditionChannel.Release),
126
+ chartSetLock: assertRosteredChartSetLock(read(EditionLockFile.ChartSet), join(dir, EditionLockFile.ChartSet)),
127
127
  };
128
128
  }
129
129
 
@@ -55,27 +55,21 @@
55
55
  // shape this plane has been bitten by: a claim that outlives its evidence.
56
56
 
57
57
  import { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
58
- import { basename, join } from 'node:path';
58
+ import { join } from 'node:path';
59
59
 
60
- import { EditionChannel } from './edition-channel.mjs';
61
60
  import {
62
61
  EDITION_CHART_SET_FILE,
63
62
  CHART_SET_LOCK_SCHEMA_VERSION,
64
- DEVELOP_CHART_VERSION_PREFIX,
65
63
  EditionChartSetCheck,
66
64
  OCI_DIGEST_PATTERN,
67
65
  assertRosteredChartSetLock,
68
66
  checkEditionChartSet,
69
- DEVELOP_CHART_SHA_LENGTH,
70
- hasDevelopChartVersionPrefix,
71
- isDevelopChartVersion,
72
67
  writeEditionChartSet,
73
68
  } from './edition-chart-set.mjs';
74
69
  import { vendorChartSetConfig } from './edition-config.mjs';
75
70
  import { WorkspaceRoot, configureEditionWorkspaceFromProcess, dataRoot, editionsRoot, isEntryModule } from './edition-workspace.mjs';
76
71
  import { serializeJson } from './lib.mjs';
77
72
  import { OrasRegistry } from './oras.mjs';
78
- import { deployPinKey } from './pin-source.mjs';
79
73
  import {
80
74
  loadRegistryCredentialDeclarations,
81
75
  resolveRegistryCredential,
@@ -129,11 +123,8 @@ export function isVersionTag(tag) {
129
123
  * last: guessing an order for a coordinate whose age is unknown is how a stale
130
124
  * set gets pinned as current.
131
125
  */
132
- export function selectNewestIndex(allCandidates) {
133
- if (!Array.isArray(allCandidates)) {return null;}
134
- // Anything with the develop prefix (`0.0.0-dev.`) is a frozen xema-deploy
135
- // snapshot or a malformed develop version, never a release index: it is not a candidate for the release pin.
136
- const candidates = allCandidates.filter((c) => !hasDevelopChartVersionPrefix(c.tag));
126
+ export function selectNewestIndex(candidates) {
127
+ if (!Array.isArray(candidates)) {return null;}
137
128
  if (candidates.length === 0) {return null;}
138
129
  const undated = candidates.filter((c) => !c.createdAt);
139
130
  if (undated.length > 0) {
@@ -155,8 +146,7 @@ export const INDEX_ROSTER_ANNOTATION = 'xema.dev/chart-set-charts';
155
146
 
156
147
  /**
157
148
  * The lock for `publishers`: each publisher's index version, the manifest digest
158
- * the registry served for that index (`indexDigestsByIndex`, null for a develop
159
- * snapshot, which has no index chart), and its sealed roster.
149
+ * the registry served for that index (`indexDigestsByIndex`), and its sealed roster.
160
150
  */
161
151
  export function buildLock(versionsByIndex, rostersByIndex, indexDigestsByIndex, publishers = chartSetPublishers()) {
162
152
  // Every publisher's VERSION first: a pin that resolved nothing for one half is
@@ -193,9 +183,8 @@ export function buildLock(versionsByIndex, rostersByIndex, indexDigestsByIndex,
193
183
  }
194
184
  // The digest the registry served for the index manifest the roster was read from.
195
185
  const indexDigest = indexDigestsByIndex?.[publisher.index];
196
- const wellFormed = isDevelopChartVersion(version) ? indexDigest === null : DIGEST_PATTERN.test(String(indexDigest));
197
- if (!wellFormed) {
198
- throw new Error(`no index manifest digest was read for '${publisher.index}@${version}' (got ${JSON.stringify(indexDigest ?? null)}; a release index needs sha256:<64 hex>, a develop snapshot null)`);
186
+ if (!DIGEST_PATTERN.test(String(indexDigest))) {
187
+ throw new Error(`no index manifest digest was read for '${publisher.index}@${version}' (got ${JSON.stringify(indexDigest ?? null)}; a release index needs sha256:<64 hex>)`);
199
188
  }
200
189
  return { ...publisher, version, indexDigest, charts };
201
190
  }),
@@ -277,63 +266,12 @@ function editionDirs() {
277
266
  .sort();
278
267
  }
279
268
 
280
- const SHA_PATTERN = /^[0-9a-f]{40}$/;
281
-
282
- /** The develop chart version xema-deploy publishes for a frozen SHA: `0.0.0-dev.<sha12>`, also the OCI tag. */
283
- export const developChartVersion = (sha) => `${DEVELOP_CHART_VERSION_PREFIX}${sha.slice(0, DEVELOP_CHART_SHA_LENGTH)}`;
284
-
285
- /** Every chart (a directory with a Chart.yaml, library charts included) of an xema-deploy checkout, sorted. */
286
- function deployChartNames(xemaDeployDir) {
287
- const chartsDir = join(xemaDeployDir, 'charts');
288
- if (!existsSync(chartsDir)) {throw new Error(`${xemaDeployDir} has no charts/ directory`);}
289
- return readdirSync(chartsDir, { withFileTypes: true })
290
- .filter((entry) => entry.isDirectory() && existsSync(join(chartsDir, entry.name, 'Chart.yaml')))
291
- .map((entry) => entry.name)
292
- .sort();
293
- }
294
-
295
269
  /** The registry client for the chart registry, with the data root's declared credential. */
296
270
  export function chartRegistryClient() {
297
271
  const credential = resolveRegistryCredential({ authority: registryAuthority(), declarations: loadRegistryCredentialDeclarations() });
298
272
  return new OrasRegistry({ credential });
299
273
  }
300
274
 
301
- /** The manifest digest the chart registry serves for `<chart>:<version>`. */
302
- const registryManifestDigest = (client) => async (name, version) =>
303
- (await client.getManifestByTag(registryRepository(name), version)).digest;
304
-
305
- /**
306
- * The develop chart-set lock: the SAME rostered lock a release pins, over the
307
- * charts xema-deploy publishes for the frozen SHA. The deploy publisher (the
308
- * workspace publisher whose repository is the deploy pin role's) publishes every
309
- * chart directory of its tree at `0.0.0-dev.<sha12>`; the roster records each
310
- * chart's registry manifest digest, so a consumer pulls by digest exactly as it
311
- * does for a release. A chart the registry does not serve is refused by name.
312
- * `lookup(name, version)` defaults to the chart registry and returns the digest.
313
- */
314
- export async function resolveDevelopChartSet({ xemaDeployDir, xemaDeploySha, lookup }) {
315
- if (!SHA_PATTERN.test(xemaDeploySha ?? '')) {
316
- throw new Error(`the deploy checkout SHA is not a 40-hex commit: ${JSON.stringify(xemaDeploySha)}`);
317
- }
318
- const names = deployChartNames(xemaDeployDir);
319
- if (names.length === 0) {throw new Error(`the deploy checkout at ${xemaDeploySha} has no chart (charts/<name>/Chart.yaml)`);}
320
- const deployRepo = basename(deployPinKey());
321
- const publishers = chartSetPublishers().filter((publisher) => basename(publisher.repo) === deployRepo);
322
- if (publishers.length !== 1) {
323
- throw new Error(
324
- `${publishers.length} chart publishers have repository ${deployRepo} (the deploy pin role); exactly one must, ` +
325
- 'since it is the publisher whose develop charts this lock pins',
326
- );
327
- }
328
- const version = developChartVersion(xemaDeploySha);
329
- const digestOf = lookup ?? registryManifestDigest(chartRegistryClient());
330
- const roster = Object.fromEntries(names.map((name) => [name, { version }]));
331
- const sealed = await sealRoster(roster, digestOf, `${publishers[0].index}@${version}`);
332
- // A develop snapshot has no index chart: its roster is the deploy checkout's chart directories.
333
- const lock = buildLock({ [publishers[0].index]: version }, { [publishers[0].index]: sealed }, { [publishers[0].index]: null }, publishers);
334
- return assertRosteredChartSetLock(lock, EDITION_CHART_SET_FILE, EditionChannel.Develop);
335
- }
336
-
337
275
  export function readLock(path = chartSetLockPath()) {
338
276
  try {
339
277
  return JSON.parse(readFileSync(path, 'utf8'));
@@ -395,7 +333,7 @@ async function main(argv) {
395
333
  const check = argv.includes('--check');
396
334
  const { versionsByIndex, rostersByIndex, indexDigestsByIndex } = await resolveFromRegistry();
397
335
  const next = buildLock(versionsByIndex, rostersByIndex, indexDigestsByIndex);
398
- assertRosteredChartSetLock(next, CHART_SET_LOCK_FILE, EditionChannel.Release);
336
+ assertRosteredChartSetLock(next, CHART_SET_LOCK_FILE);
399
337
  const pinText = serializeJson(next);
400
338
  const current = readLock();
401
339
  // The pin AND every edition's copy of it: one writer, one run, so the N copies
@@ -326,7 +326,7 @@ export async function resolveCustomerEdition(request) {
326
326
  const imageLock = await resolveCustomerImages({ id, catalogue, lock, composed, schemas, inputs, sealOwn: request.sealOwn });
327
327
  // The chart-set is copied whole, so it carries the coordinates of the channel it was published on:
328
328
  // the edition being written states its channel, and a chart-set of the other one is refused here.
329
- const chartSetLock = assertRosteredChartSetLock(catalogue.chartSet, `the catalogue's chart-set of "${catalogue.offeringId}"`, request.channel);
329
+ const chartSetLock = assertRosteredChartSetLock(catalogue.chartSet, `the catalogue's chart-set of "${catalogue.offeringId}"`);
330
330
  return { id, distributionLock: lock, imageLock, authorizationLock, chartSetLock };
331
331
  }
332
332
 
@@ -38,6 +38,7 @@ import { join, relative, sep } from 'node:path';
38
38
 
39
39
  import { assertBuildLedgerComplete } from './build-ledger-completeness.mjs';
40
40
  import { BUILD_LEDGER_FILE, readBuildLedger } from './build-ledger.mjs';
41
+ import { CROSS_REPO_BUILD_INPUTS_PATH, crossRepoInputKey, resolveCrossRepoVendoredInputs } from './cross-repo-build-inputs.mjs';
41
42
  import { resolveDispatchedRuntimeComponents } from './dispatched-runtime-components.mjs';
42
43
  import {
43
44
  assertCanonicalDistributionId,
@@ -53,15 +54,12 @@ import {
53
54
  } from './external-source-walk.mjs';
54
55
  import { assertDeclaredSourceId, firstPartySourceId } from './first-party-source-ids.mjs';
55
56
  import {
56
- CROSS_REPO_BUILD_INPUTS_PATH,
57
57
  compareStrings,
58
- crossRepoInputKey,
59
58
  hashImageBuildInputs,
60
59
  imageInputSourceHashAlgorithm,
61
60
  loadKernelDistributionSchemas,
62
61
  parseResolvedDistributionLock,
63
62
  readGitJsonAtCommit,
64
- resolveCrossRepoVendoredInputs,
65
63
  serializeJson,
66
64
  sha256Hex,
67
65
  validateImmutableDistributionLock,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/xema",
3
- "version": "0.33.2",
3
+ "version": "0.33.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/xema-dev/xema-cli.git",
@@ -92,6 +92,6 @@
92
92
  "typecheck": "tsc --noEmit"
93
93
  },
94
94
  "xemaRelease": {
95
- "sourceDigest": "sha256:de506f4bb207dcf31fb135d585486f8fa5bf4fc11d0d1841506d8773393fa423"
95
+ "sourceDigest": "sha256:a8780b8b95054688b280033f5aec97bbdb0d4bc211513d09a992a3c025af653e"
96
96
  }
97
97
  }