@omnitron-dev/omnitron 0.3.3 → 0.3.5
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/bin/pnpmfile-sdk.mjs +6 -1
- package/bin/sdk.mjs +6 -2
- package/dist/BUILD.json +2 -2
- package/dist/cli/omnitron.js +54 -14
- package/dist/cli/omnitron.js.map +1 -1
- package/dist/commands/infra.d.ts +8 -2
- package/dist/commands/infra.d.ts.map +1 -1
- package/dist/commands/infra.js +52 -59
- package/dist/commands/infra.js.map +1 -1
- package/dist/commands/node.d.ts.map +1 -1
- package/dist/commands/node.js +8 -1
- package/dist/commands/node.js.map +1 -1
- package/dist/commands/release-store.d.ts.map +1 -1
- package/dist/commands/release-store.js +6 -9
- package/dist/commands/release-store.js.map +1 -1
- package/dist/commands/release.d.ts +4 -1
- package/dist/commands/release.d.ts.map +1 -1
- package/dist/commands/release.js +125 -5
- package/dist/commands/release.js.map +1 -1
- package/dist/commands/stack.d.ts +1 -1
- package/dist/commands/stack.d.ts.map +1 -1
- package/dist/commands/stack.js +19 -9
- package/dist/commands/stack.js.map +1 -1
- package/dist/config/saved.d.ts +3 -0
- package/dist/config/saved.d.ts.map +1 -1
- package/dist/config/saved.js +1 -0
- package/dist/config/saved.js.map +1 -1
- package/dist/config/types.d.ts +4 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/daemon/daemon.d.ts.map +1 -1
- package/dist/daemon/daemon.js +30 -6
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/daemon/daemon.rpc-service.d.ts +0 -26
- package/dist/daemon/daemon.rpc-service.d.ts.map +1 -1
- package/dist/daemon/daemon.rpc-service.js +23 -114
- package/dist/daemon/daemon.rpc-service.js.map +1 -1
- package/dist/daemon/execution-client.d.ts +1 -1
- package/dist/daemon/execution-client.d.ts.map +1 -1
- package/dist/daemon/execution-client.js +17 -13
- package/dist/daemon/execution-client.js.map +1 -1
- package/dist/daemon/startup-config.d.ts +1 -0
- package/dist/daemon/startup-config.d.ts.map +1 -1
- package/dist/infrastructure/container-runtime.d.ts +8 -0
- package/dist/infrastructure/container-runtime.d.ts.map +1 -1
- package/dist/infrastructure/container-runtime.js +5 -0
- package/dist/infrastructure/container-runtime.js.map +1 -1
- package/dist/infrastructure/infrastructure.service.d.ts +5 -0
- package/dist/infrastructure/infrastructure.service.d.ts.map +1 -1
- package/dist/infrastructure/infrastructure.service.js +18 -8
- package/dist/infrastructure/infrastructure.service.js.map +1 -1
- package/dist/infrastructure/presets/postgres.js +1 -1
- package/dist/infrastructure/presets/postgres.js.map +1 -1
- package/dist/infrastructure/presets/registry.d.ts.map +1 -1
- package/dist/infrastructure/presets/registry.js +11 -19
- package/dist/infrastructure/presets/registry.js.map +1 -1
- package/dist/infrastructure/stack-infra-manager.d.ts +4 -0
- package/dist/infrastructure/stack-infra-manager.d.ts.map +1 -1
- package/dist/infrastructure/stack-infra-manager.js +38 -4
- package/dist/infrastructure/stack-infra-manager.js.map +1 -1
- package/dist/mcp/tool-groups/infra.tools.d.ts.map +1 -1
- package/dist/mcp/tool-groups/infra.tools.js +4 -1
- package/dist/mcp/tool-groups/infra.tools.js.map +1 -1
- package/dist/orchestrator/app-name.d.ts +33 -0
- package/dist/orchestrator/app-name.d.ts.map +1 -0
- package/dist/orchestrator/app-name.js +68 -0
- package/dist/orchestrator/app-name.js.map +1 -0
- package/dist/orchestrator/orchestrator.service.d.ts +1 -26
- package/dist/orchestrator/orchestrator.service.d.ts.map +1 -1
- package/dist/orchestrator/orchestrator.service.js +10 -89
- package/dist/orchestrator/orchestrator.service.js.map +1 -1
- package/dist/project/stack-diagnosis.d.ts.map +1 -1
- package/dist/project/stack-diagnosis.js +2 -3
- package/dist/project/stack-diagnosis.js.map +1 -1
- package/dist/release/artifact-store.d.ts +42 -7
- package/dist/release/artifact-store.d.ts.map +1 -1
- package/dist/release/artifact-store.js +176 -62
- package/dist/release/artifact-store.js.map +1 -1
- package/dist/release/configured-store.d.ts +6 -0
- package/dist/release/configured-store.d.ts.map +1 -0
- package/dist/release/configured-store.js +54 -0
- package/dist/release/configured-store.js.map +1 -0
- package/dist/release/load.d.ts +3 -0
- package/dist/release/load.d.ts.map +1 -1
- package/dist/release/load.js +8 -2
- package/dist/release/load.js.map +1 -1
- package/dist/services/infrastructure.rpc-service.d.ts +6 -2
- package/dist/services/infrastructure.rpc-service.d.ts.map +1 -1
- package/dist/services/infrastructure.rpc-service.js +43 -12
- package/dist/services/infrastructure.rpc-service.js.map +1 -1
- package/dist/services/node-deploy-lease.d.ts +4 -1
- package/dist/services/node-deploy-lease.d.ts.map +1 -1
- package/dist/services/node-deploy-lease.js +29 -4
- package/dist/services/node-deploy-lease.js.map +1 -1
- package/dist/services/node-manager.service.d.ts +5 -25
- package/dist/services/node-manager.service.d.ts.map +1 -1
- package/dist/services/node-manager.service.js +150 -139
- package/dist/services/node-manager.service.js.map +1 -1
- package/dist/services/project.service.d.ts +6 -0
- package/dist/services/project.service.d.ts.map +1 -1
- package/dist/services/project.service.js +89 -9
- package/dist/services/project.service.js.map +1 -1
- package/dist/services/release.rpc-service.d.ts +2 -1
- package/dist/services/release.rpc-service.d.ts.map +1 -1
- package/dist/services/release.rpc-service.js +19 -3
- package/dist/services/release.rpc-service.js.map +1 -1
- package/dist/services/release.service.d.ts +24 -11
- package/dist/services/release.service.d.ts.map +1 -1
- package/dist/services/release.service.js +162 -39
- package/dist/services/release.service.js.map +1 -1
- package/dist/services/remote-deployer.service.d.ts +1 -1
- package/dist/services/remote-deployer.service.d.ts.map +1 -1
- package/dist/services/remote-deployer.service.js.map +1 -1
- package/dist/services/secrets.service.d.ts +6 -0
- package/dist/services/secrets.service.d.ts.map +1 -1
- package/dist/services/secrets.service.js +95 -51
- package/dist/services/secrets.service.js.map +1 -1
- package/dist/shared/dto/nodes.d.ts +2 -0
- package/dist/shared/dto/nodes.d.ts.map +1 -1
- package/dist/shared/dto/project.d.ts +1 -1
- package/dist/shared/dto/project.d.ts.map +1 -1
- package/dist/shared/dto/releases.d.ts +8 -1
- package/dist/shared/dto/releases.d.ts.map +1 -1
- package/dist/shared/dto/services.d.ts +18 -1
- package/dist/shared/dto/services.d.ts.map +1 -1
- package/dist/shared/dto/services.js.map +1 -1
- package/dist/shared/release-reading.d.ts +6 -0
- package/dist/shared/release-reading.d.ts.map +1 -1
- package/dist/shared/release-reading.js +42 -0
- package/dist/shared/release-reading.js.map +1 -1
- package/package.json +16 -16
- package/webapp/dist/BUILD.json +2 -2
- package/webapp/dist/assets/{access-48hkC2-P.js → access-BvKK9dEv.js} +1 -1
- package/webapp/dist/assets/{access-jWkHxGc7.js → access-DUjabwNX.js} +1 -1
- package/webapp/dist/assets/{alerts-CuPQ9YQJ.js → alerts-CzN6OqX5.js} +1 -1
- package/webapp/dist/assets/{apps-Drio028B.js → apps-G_Lm6m4F.js} +1 -1
- package/webapp/dist/assets/{audit-npSFJECe.js → audit-CLMpdBzG.js} +1 -1
- package/webapp/dist/assets/{containers-Bl8gAyZX.js → containers-BsFwprq4.js} +1 -1
- package/webapp/dist/assets/{dashboard-UHlet3H9.js → dashboard-BN7rKE5n.js} +1 -1
- package/webapp/dist/assets/{dashboard-builder-67PZFqhE.js → dashboard-builder-BXFxWjXP.js} +1 -1
- package/webapp/dist/assets/deploy-progress-CUUwlYtQ.js +1 -0
- package/webapp/dist/assets/deploy-release-dialog-58lGZDNk.js +1 -0
- package/webapp/dist/assets/deployments-DEzjHerg.js +1 -0
- package/webapp/dist/assets/detail-CBn9pjJU.js +2 -0
- package/webapp/dist/assets/{detail-CYS81K6Y.js → detail-Dj3gxaH0.js} +1 -1
- package/webapp/dist/assets/{detail-B4TiBfxU.js → detail-pXPk4O0E.js} +1 -1
- package/webapp/dist/assets/index-Bo9An3pJ.js +1 -0
- package/webapp/dist/assets/{logs-BqHOufk8.js → logs-DrsBbLfb.js} +1 -1
- package/webapp/dist/assets/{metrics-QIQaF7iS.js → metrics-D5cDZTEo.js} +1 -1
- package/webapp/dist/assets/{mui-y44PQOfG.js → mui-59N0OVRa.js} +1 -1
- package/webapp/dist/assets/{mui-C_hromOc.js → mui-D5m7fDCh.js} +1 -1
- package/webapp/dist/assets/{mui-BIz4LSVs.js → mui-Db5J-QUd.js} +1 -1
- package/webapp/dist/assets/{mui-B1jrje6Z.js → mui-dLCwWoMw.js} +1 -1
- package/webapp/dist/assets/{nodes-BJPk02vv.js → nodes-CwwZZuu4.js} +1 -1
- package/webapp/dist/assets/{pipelines-T6Ch9LTw.js → pipelines-BrfTjf6Y.js} +1 -1
- package/webapp/dist/assets/project.store-DuCgv6Eq.js +1 -0
- package/webapp/dist/assets/{projects-YoBzcQ24.js → projects-TBAdpCeX.js} +1 -1
- package/webapp/dist/assets/{realtime.store-CBDO4Abj.js → realtime.store-hfxZD2DU.js} +1 -1
- package/webapp/dist/assets/release-bits-BJ6i23y0.js +1 -0
- package/webapp/dist/assets/release-build-panel-BNXkwNE1.js +1 -0
- package/webapp/dist/assets/release-deployment-state-gN8ZT3aq.js +1 -0
- package/webapp/dist/assets/releases-CXXKUh-v.js +2 -0
- package/webapp/dist/assets/{stack-start-notice-BVnMOwRQ.js → stack-start-notice-D-AH_bzn.js} +1 -1
- package/webapp/dist/assets/{stacks-IZ1mfizi.js → stacks-WY_ynkON.js} +1 -1
- package/webapp/dist/assets/{system-info-BFKNM-hf.js → system-info-DXMwo6gl.js} +1 -1
- package/webapp/dist/assets/{topology-CPey5dP6.js → topology-C_Qp1RqW.js} +1 -1
- package/webapp/dist/assets/{use-stack-context-UkBsF-l7.js → use-stack-context-8yaHaN8L.js} +1 -1
- package/webapp/dist/assets/{webapp-D-UhjFhS.js → webapp-BO_WoB_z.js} +3 -3
- package/webapp/dist/console-version.json +1 -1
- package/webapp/dist/index.html +12 -12
- package/webapp/dist/assets/deploy-release-dialog-BOXcD5Wo.js +0 -1
- package/webapp/dist/assets/deployments-qV20Ak0P.js +0 -1
- package/webapp/dist/assets/detail-B85-Wees.js +0 -2
- package/webapp/dist/assets/index-uq8Dkk4c.js +0 -1
- package/webapp/dist/assets/project.store--G5pIF-J.js +0 -1
- package/webapp/dist/assets/release-bits-B2a_wbft.js +0 -1
- package/webapp/dist/assets/release-build-panel-BQmIdKW9.js +0 -1
- package/webapp/dist/assets/release-deployment-state-DRrEI2pP.js +0 -1
- package/webapp/dist/assets/release-wire-f2VuBoBF.js +0 -1
- package/webapp/dist/assets/releases-Bp3CDgmo.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stack-diagnosis.js","sourceRoot":"","sources":["../../src/project/stack-diagnosis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,EAAwB,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"stack-diagnosis.js","sourceRoot":"","sources":["../../src/project/stack-diagnosis.ts"],"names":[],"mappings":"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"}
|
|
@@ -99,6 +99,7 @@
|
|
|
99
99
|
* today is 8.3 MB.
|
|
100
100
|
*/
|
|
101
101
|
import type { SecretRef } from '../infrastructure/types.js';
|
|
102
|
+
export { isReleaseId } from './load.js';
|
|
102
103
|
/** `releaseStore` in `~/.omnitron/config.json`, as an operator writes it. */
|
|
103
104
|
export interface ReleaseStoreConfig {
|
|
104
105
|
/** `https://s3.<provider>` — or `http://127.0.0.1:9000`: plain http is taken on loopback only. */
|
|
@@ -114,9 +115,29 @@ export interface ReleaseStoreConfig {
|
|
|
114
115
|
readonly forcePathStyle?: boolean;
|
|
115
116
|
/** Where in the bucket releases live, for a bucket that holds other things too. */
|
|
116
117
|
readonly prefix?: string;
|
|
118
|
+
readonly ssh?: StoreSshConfig;
|
|
117
119
|
readonly accessKey: SecretRef;
|
|
118
120
|
readonly secretKey: SecretRef;
|
|
119
121
|
}
|
|
122
|
+
export interface StoreSshConfig {
|
|
123
|
+
readonly host: string;
|
|
124
|
+
readonly port: number;
|
|
125
|
+
readonly username: string;
|
|
126
|
+
readonly hostFingerprint: string;
|
|
127
|
+
readonly privateKey: SecretRef;
|
|
128
|
+
readonly passphrase?: SecretRef;
|
|
129
|
+
}
|
|
130
|
+
export declare function releaseStoreLocation(config: {
|
|
131
|
+
endpoint: string | URL;
|
|
132
|
+
bucket: string;
|
|
133
|
+
prefix?: string;
|
|
134
|
+
ssh?: StoreSshConfig;
|
|
135
|
+
}): string;
|
|
136
|
+
export interface StoreConnection {
|
|
137
|
+
readonly port: number;
|
|
138
|
+
readonly closed: Promise<void>;
|
|
139
|
+
close(): Promise<void>;
|
|
140
|
+
}
|
|
120
141
|
export interface StoreCredentials {
|
|
121
142
|
readonly accessKeyId: string;
|
|
122
143
|
readonly secretAccessKey: string;
|
|
@@ -130,6 +151,7 @@ export interface ResolvedStore {
|
|
|
130
151
|
/** Without leading or trailing slashes; empty for the bucket's root. */
|
|
131
152
|
readonly prefix: string;
|
|
132
153
|
readonly credentials: StoreCredentials;
|
|
154
|
+
readonly ssh?: StoreSshConfig;
|
|
133
155
|
/** Which vault keys the pair came from — what a refusal names instead of the values. */
|
|
134
156
|
readonly credentialKeys: {
|
|
135
157
|
readonly accessKey: string;
|
|
@@ -203,7 +225,9 @@ export interface ObjectSum {
|
|
|
203
225
|
export interface ObjectStore {
|
|
204
226
|
readonly location: string;
|
|
205
227
|
/** Write `source` — a file, or bytes — whose sum is already known. */
|
|
206
|
-
put(key: string, source: string | Buffer, sum: ObjectSum
|
|
228
|
+
put(key: string, source: string | Buffer, sum: ObjectSum, condition?: {
|
|
229
|
+
etag: string | null;
|
|
230
|
+
}): Promise<void>;
|
|
207
231
|
/**
|
|
208
232
|
* Stream an object into `into`, hashing it on the way; null when there is
|
|
209
233
|
* no such object. Stops, and refuses, past `recordedBytes`: what the index
|
|
@@ -212,6 +236,10 @@ export interface ObjectStore {
|
|
|
212
236
|
get(key: string, into: string, recordedBytes: number): Promise<ObjectSum | null>;
|
|
213
237
|
/** A small object whole, or null when there is none. */
|
|
214
238
|
read(key: string, limitBytes: number): Promise<Buffer | null>;
|
|
239
|
+
readVersion(key: string, limitBytes: number): Promise<{
|
|
240
|
+
body: Buffer;
|
|
241
|
+
etag: string;
|
|
242
|
+
} | null>;
|
|
215
243
|
}
|
|
216
244
|
/**
|
|
217
245
|
* An S3-compatible bucket, reached with `node:http(s)` and SigV4.
|
|
@@ -226,12 +254,19 @@ export declare class S3ObjectStore implements ObjectStore {
|
|
|
226
254
|
constructor(store: ResolvedStore, options?: {
|
|
227
255
|
idleTimeoutMs?: number;
|
|
228
256
|
sockets?: number;
|
|
257
|
+
route?: StoreConnection;
|
|
229
258
|
});
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
259
|
+
close(): Promise<void>;
|
|
260
|
+
put(key: string, source: string | Buffer, sum: ObjectSum, condition?: {
|
|
261
|
+
etag: string | null;
|
|
262
|
+
}): Promise<void>;
|
|
233
263
|
get(key: string, into: string, recordedBytes: number): Promise<ObjectSum | null>;
|
|
234
264
|
read(key: string, limitBytes: number): Promise<Buffer | null>;
|
|
265
|
+
readVersion(key: string, limitBytes: number): Promise<{
|
|
266
|
+
body: Buffer;
|
|
267
|
+
etag: string;
|
|
268
|
+
} | null>;
|
|
269
|
+
private readObject;
|
|
235
270
|
/**
|
|
236
271
|
* One signed request; resolves with the response once its headers arrive.
|
|
237
272
|
*
|
|
@@ -240,6 +275,7 @@ export declare class S3ObjectStore implements ObjectStore {
|
|
|
240
275
|
* reaches the response too, so a stream being read does not wait forever.
|
|
241
276
|
*/
|
|
242
277
|
private send;
|
|
278
|
+
private request;
|
|
243
279
|
/** A refusal in the store's own words, and what it usually means here. */
|
|
244
280
|
private failure;
|
|
245
281
|
}
|
|
@@ -256,13 +292,12 @@ export interface IndexEntry {
|
|
|
256
292
|
readonly at?: string;
|
|
257
293
|
}
|
|
258
294
|
export interface StoreIndex {
|
|
259
|
-
readonly format: 1;
|
|
295
|
+
readonly format: 1 | 2;
|
|
260
296
|
readonly release: string;
|
|
261
297
|
readonly pushedAt: string;
|
|
262
298
|
readonly pushedBy: string;
|
|
263
299
|
readonly files: readonly IndexEntry[];
|
|
264
300
|
}
|
|
265
|
-
export declare function isReleaseId(id: string): boolean;
|
|
266
301
|
/**
|
|
267
302
|
* Why a path may not be a file of a release — or null.
|
|
268
303
|
*
|
|
@@ -293,6 +328,7 @@ export interface KeptAttestation {
|
|
|
293
328
|
readonly offered: string | null;
|
|
294
329
|
}
|
|
295
330
|
export interface TransferOptions {
|
|
331
|
+
readonly signal?: AbortSignal;
|
|
296
332
|
/** Where releases live on this machine. Default `~/.omnitron/releases`. */
|
|
297
333
|
readonly root?: string;
|
|
298
334
|
/** Objects in flight at once. Default 8: 548 statics files one by one is a minute on a remote store. */
|
|
@@ -356,5 +392,4 @@ export declare function pushRelease(id: string, store: ObjectStore, options?: Tr
|
|
|
356
392
|
* and only an attestation that measured later is taken.
|
|
357
393
|
*/
|
|
358
394
|
export declare function pullRelease(id: string, store: ObjectStore, options?: TransferOptions): Promise<PullResult>;
|
|
359
|
-
export {};
|
|
360
395
|
//# sourceMappingURL=artifact-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-store.d.ts","sourceRoot":"","sources":["../../src/release/artifact-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmGG;
|
|
1
|
+
{"version":3,"file":"artifact-store.d.ts","sourceRoot":"","sources":["../../src/release/artifact-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmGG;AAaH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAOxC,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+FAA+F;IAC/F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,mFAAmF;IACnF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC;CACjC;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,cAAc,CAAA;CAAE,GAAG,MAAM,CAMtI;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;IACvC,QAAQ,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC;IAC9B,wFAAwF;IACxF,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACrF;AAID,+FAA+F;AAC/F,eAAO,MAAM,oBAAoB,QASrB,CAAC;AAOb;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAoHjF;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,EAC1B,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GACjD,OAAO,CAAC,aAAa,CAAC,CA+BxB;AAYD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,yFAAyF;IACzF,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,2FAA2F;IAC3F,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CA2C/F;AAED,sDAAsD;AACtD,wBAAgB,aAAa,CAC3B,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,QAAQ,GAAG,gBAAgB,GAAG,QAAQ,CAAC,EAC/E,GAAG,EAAE,MAAM,GACV;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAiB7H;AAMD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9G;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACjF,wDAAwD;IACxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9D,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CAC9F;AAsCD;;;;;;GAMG;AACH,qBAAa,aAAc,YAAW,WAAW;;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAS1B,YAAY,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,eAAe,CAAA;KAAO,EAUpH;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAIrB;IAEK,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAUlH;IAEK,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA4BrF;IAEK,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElE;IAEK,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAKjG;YAEa,UAAU;IAoBxB;;;;;;OAMG;YACW,IAAI;IAalB,OAAO,CAAC,OAAO;IAsDf,0EAA0E;IAC1E,OAAO,CAAC,OAAO;CAqBhB;AASD,QAAA,MAAM,eAAe,YAAI,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,CAAU,CAAC;AAErF,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,MAAM,WAAW,UAAU;IACzB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAc1D;AAkFD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CA2ClF;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAmGD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAqFD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,wGAAwG;IACxG,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACnE;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;IACzD,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,0FAA0F;IAC1F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,qFAAqF;IACrF,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,CAAA;KAAE,CAAC;CACtF;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAuFxH;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CAgHpH"}
|
|
@@ -103,12 +103,22 @@ import fs from 'node:fs';
|
|
|
103
103
|
import http from 'node:http';
|
|
104
104
|
import https from 'node:https';
|
|
105
105
|
import os from 'node:os';
|
|
106
|
+
import { isIP } from 'node:net';
|
|
106
107
|
import path from 'node:path';
|
|
107
108
|
import { Transform } from 'node:stream';
|
|
108
109
|
import { pipeline } from 'node:stream/promises';
|
|
110
|
+
import { isSshHostFingerprint } from '../services/node-host-key.js';
|
|
109
111
|
import { resolveSecretRefs } from '../project/config-resolver.js';
|
|
110
|
-
import { loadRelease, releasesRoot } from './load.js';
|
|
111
|
-
|
|
112
|
+
import { isReleaseId, loadRelease, releasesRoot } from './load.js';
|
|
113
|
+
export { isReleaseId } from './load.js';
|
|
114
|
+
export function releaseStoreLocation(config) {
|
|
115
|
+
const url = new URL(config.endpoint);
|
|
116
|
+
const prefix = (config.prefix ?? '').replace(/^\/+|\/+$/g, '');
|
|
117
|
+
const base = url.origin + url.pathname.replace(/\/+$/, '');
|
|
118
|
+
return 's3://' + config.bucket + (prefix ? '/' + prefix : '') + ' at ' + base +
|
|
119
|
+
(config.ssh ? ' via SSH ' + config.ssh.host + ':' + config.ssh.port : '');
|
|
120
|
+
}
|
|
121
|
+
const CONFIG_FIELDS = new Set(['endpoint', 'bucket', 'region', 'forcePathStyle', 'prefix', 'accessKey', 'secretKey', 'ssh']);
|
|
112
122
|
/** What a store looks like in the config, for a refusal to show — references, never values. */
|
|
113
123
|
export const STORE_CONFIG_EXAMPLE = [
|
|
114
124
|
'"releaseStore": {',
|
|
@@ -144,8 +154,7 @@ export function parseStoreConfig(raw, source) {
|
|
|
144
154
|
if (unknown.length > 0) {
|
|
145
155
|
throw new Error(`'releaseStore' in ${source} has ${unknown.map((k) => `'${k}'`).join(', ')}, which it does not read — it reads ${[...CONFIG_FIELDS].join(', ')}`);
|
|
146
156
|
}
|
|
147
|
-
const reference = (field) => {
|
|
148
|
-
const value = o[field];
|
|
157
|
+
const reference = (field, value = o[field]) => {
|
|
149
158
|
if (typeof value === 'string') {
|
|
150
159
|
throw new Error(`'releaseStore.${field}' in ${source} is a literal credential. The key lives in the daemon's vault and the config names it: ` +
|
|
151
160
|
`"${field}": { "secret": "<vault key>" }`);
|
|
@@ -208,9 +217,31 @@ export function parseStoreConfig(raw, source) {
|
|
|
208
217
|
throw new Error(`'releaseStore.prefix' in ${source} must be a path inside the bucket, of A-Z, a-z, 0-9, '.', '_' and '-'`);
|
|
209
218
|
}
|
|
210
219
|
}
|
|
220
|
+
let ssh;
|
|
221
|
+
if (o['ssh'] !== undefined) {
|
|
222
|
+
const route = o['ssh'];
|
|
223
|
+
if (!route || typeof route !== 'object' || Array.isArray(route) ||
|
|
224
|
+
Object.keys(route).some(key => !['host', 'port', 'username', 'hostFingerprint', 'privateKey', 'passphrase'].includes(key)))
|
|
225
|
+
throw new Error('Invalid releaseStore.ssh configuration in ' + source);
|
|
226
|
+
if (url.protocol !== 'http:' || !['127.0.0.1', '[::1]'].includes(url.hostname) || forcePathStyle === false)
|
|
227
|
+
throw new Error('releaseStore.ssh requires an HTTP endpoint on numeric loopback and path-style addressing');
|
|
228
|
+
const { host, username, hostFingerprint } = route;
|
|
229
|
+
const port = route['port'] ?? 22;
|
|
230
|
+
if (typeof host !== 'string' || (!isIP(host) && !(host.length <= 253 && host.split('.').every(label => /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i.test(label)))))
|
|
231
|
+
throw new Error('Invalid releaseStore.ssh.host in ' + source);
|
|
232
|
+
if (typeof port !== 'number' || !Number.isInteger(port) || port < 1 || port > 65535)
|
|
233
|
+
throw new Error('Invalid releaseStore.ssh.port in ' + source);
|
|
234
|
+
if (typeof username !== 'string' || !/^[a-z_][a-z0-9_.-]{0,63}$/i.test(username))
|
|
235
|
+
throw new Error('Invalid releaseStore.ssh.username in ' + source);
|
|
236
|
+
if (!isSshHostFingerprint(hostFingerprint))
|
|
237
|
+
throw new Error('releaseStore.ssh requires an independently verified SHA256 host fingerprint');
|
|
238
|
+
ssh = { host, port, username, hostFingerprint, privateKey: reference('ssh.privateKey', route['privateKey']),
|
|
239
|
+
...(route['passphrase'] !== undefined && { passphrase: reference('ssh.passphrase', route['passphrase']) }) };
|
|
240
|
+
}
|
|
211
241
|
return {
|
|
212
242
|
endpoint,
|
|
213
243
|
bucket,
|
|
244
|
+
...(ssh && { ssh }),
|
|
214
245
|
...(typeof region === 'string' ? { region } : {}),
|
|
215
246
|
...(typeof forcePathStyle === 'boolean' ? { forcePathStyle } : {}),
|
|
216
247
|
...(typeof prefix === 'string' ? { prefix } : {}),
|
|
@@ -246,6 +277,7 @@ export async function resolveStore(config, getSecret) {
|
|
|
246
277
|
}
|
|
247
278
|
return {
|
|
248
279
|
endpoint: new URL(config.endpoint),
|
|
280
|
+
...(config.ssh && { ssh: config.ssh }),
|
|
249
281
|
bucket: config.bucket,
|
|
250
282
|
region: config.region ?? 'us-east-1',
|
|
251
283
|
forcePathStyle: config.forcePathStyle ?? true,
|
|
@@ -336,6 +368,8 @@ export function objectAddress(store, key) {
|
|
|
336
368
|
path: `${basePath}/${encoded}`,
|
|
337
369
|
};
|
|
338
370
|
}
|
|
371
|
+
class StoreConflict extends Error {
|
|
372
|
+
}
|
|
339
373
|
/** S3 refuses a single PUT above this; a multipart upload is the way past it. */
|
|
340
374
|
const SINGLE_PUT_LIMIT = 5 * 1024 ** 3;
|
|
341
375
|
/** An S3 error document is a few hundred bytes; this is how much of one is read. */
|
|
@@ -383,25 +417,35 @@ export class S3ObjectStore {
|
|
|
383
417
|
#store;
|
|
384
418
|
#agent;
|
|
385
419
|
#idleMs;
|
|
420
|
+
#closed = false;
|
|
421
|
+
#closing;
|
|
422
|
+
#route;
|
|
386
423
|
constructor(store, options = {}) {
|
|
424
|
+
if (Boolean(store.ssh) !== Boolean(options.route))
|
|
425
|
+
throw new Error('The configured S3 transport is unavailable');
|
|
426
|
+
this.#route = options.route;
|
|
387
427
|
this.#store = store;
|
|
388
428
|
this.#credentials = store.credentials;
|
|
389
429
|
this.#idleMs = options.idleTimeoutMs ?? 60_000;
|
|
390
430
|
const agentOptions = { keepAlive: true, maxSockets: options.sockets ?? 8 };
|
|
391
431
|
this.#agent = store.endpoint.protocol === 'https:' ? new https.Agent(agentOptions) : new http.Agent(agentOptions);
|
|
392
|
-
|
|
393
|
-
this.
|
|
432
|
+
this.location = releaseStoreLocation(store);
|
|
433
|
+
void this.#route?.closed.then(() => { this.#closed = true; this.#agent.destroy(); });
|
|
394
434
|
}
|
|
395
|
-
/** Keep-alive sockets hold the process open; a command closes the store when it is done. */
|
|
396
435
|
close() {
|
|
436
|
+
this.#closed = true;
|
|
397
437
|
this.#agent.destroy();
|
|
438
|
+
return this.#closing ??= this.#route?.close() ?? Promise.resolve();
|
|
398
439
|
}
|
|
399
|
-
async put(key, source, sum) {
|
|
440
|
+
async put(key, source, sum, condition) {
|
|
400
441
|
if (sum.bytes > SINGLE_PUT_LIMIT) {
|
|
401
442
|
throw new Error(`${key} is ${sum.bytes} bytes; one PUT carries at most ${SINGLE_PUT_LIMIT}, and this store does not split uploads`);
|
|
402
443
|
}
|
|
403
|
-
const
|
|
444
|
+
const precondition = condition ? condition.etag === null ? { 'if-none-match': '*' } : { 'if-match': condition.etag } : undefined;
|
|
445
|
+
const res = await this.send('PUT', key, { source, sum }, precondition);
|
|
404
446
|
const body = await readCapped(res, ERROR_BODY_LIMIT);
|
|
447
|
+
if (condition && (res.statusCode === 412 || (res.statusCode === 409 && xmlField(body.toString('utf8'), 'Code') === 'ConditionalRequestConflict')))
|
|
448
|
+
throw new StoreConflict('A concurrent publisher changed the store index for ' + key);
|
|
405
449
|
if (res.statusCode !== 200)
|
|
406
450
|
throw this.failure('PUT', key, res.statusCode ?? 0, body.toString('utf8'));
|
|
407
451
|
}
|
|
@@ -436,6 +480,17 @@ export class S3ObjectStore {
|
|
|
436
480
|
return { sha256: hash.digest('hex'), bytes };
|
|
437
481
|
}
|
|
438
482
|
async read(key, limitBytes) {
|
|
483
|
+
return (await this.readObject(key, limitBytes))?.body ?? null;
|
|
484
|
+
}
|
|
485
|
+
async readVersion(key, limitBytes) {
|
|
486
|
+
const object = await this.readObject(key, limitBytes);
|
|
487
|
+
if (!object)
|
|
488
|
+
return null;
|
|
489
|
+
if (!object.etag || !/^"[^"\r\n]+"$/.test(object.etag))
|
|
490
|
+
throw new Error('The release store did not supply a strong ETag for ' + key);
|
|
491
|
+
return { body: object.body, etag: object.etag };
|
|
492
|
+
}
|
|
493
|
+
async readObject(key, limitBytes) {
|
|
439
494
|
const res = await this.send('GET', key, null);
|
|
440
495
|
if (res.statusCode !== 200) {
|
|
441
496
|
const body = (await readCapped(res, ERROR_BODY_LIMIT)).toString('utf8');
|
|
@@ -453,7 +508,7 @@ export class S3ObjectStore {
|
|
|
453
508
|
}
|
|
454
509
|
chunks.push(chunk);
|
|
455
510
|
}
|
|
456
|
-
return Buffer.concat(chunks);
|
|
511
|
+
return { body: Buffer.concat(chunks), etag: res.headers.etag };
|
|
457
512
|
}
|
|
458
513
|
/**
|
|
459
514
|
* One signed request; resolves with the response once its headers arrive.
|
|
@@ -462,25 +517,39 @@ export class S3ObjectStore {
|
|
|
462
517
|
* is never cut, one that has said nothing for a minute is — and the error
|
|
463
518
|
* reaches the response too, so a stream being read does not wait forever.
|
|
464
519
|
*/
|
|
465
|
-
send(method, key, body) {
|
|
520
|
+
async send(method, key, body, precondition) {
|
|
521
|
+
const request = () => this.request(method, key, body, precondition);
|
|
522
|
+
try {
|
|
523
|
+
return await request();
|
|
524
|
+
}
|
|
525
|
+
catch (error) {
|
|
526
|
+
// Reopen the upload stream and keep the original index precondition if the reply was lost.
|
|
527
|
+
if (this.#closed || !['ECONNRESET', 'EPIPE'].includes(error.code ?? ''))
|
|
528
|
+
throw error;
|
|
529
|
+
return request();
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
request(method, key, body, precondition) {
|
|
533
|
+
if (this.#closed)
|
|
534
|
+
throw new Error('The release store connection was closed');
|
|
466
535
|
const address = objectAddress(this.#store, key);
|
|
467
536
|
const signed = signV4({
|
|
468
537
|
method,
|
|
469
538
|
canonicalUri: address.path,
|
|
470
|
-
headers: { host: address.host },
|
|
539
|
+
headers: { host: address.host, ...precondition },
|
|
471
540
|
payloadSha256: body ? body.sum.sha256 : EMPTY_SHA256,
|
|
472
541
|
region: this.#store.region,
|
|
473
542
|
credentials: this.#credentials,
|
|
474
543
|
now: new Date(),
|
|
475
544
|
});
|
|
476
|
-
const headers = { host: address.host, ...signed.headers };
|
|
545
|
+
const headers = { host: address.host, ...precondition, ...signed.headers };
|
|
477
546
|
if (body)
|
|
478
547
|
headers['content-length'] = String(body.sum.bytes);
|
|
479
548
|
return new Promise((resolve, reject) => {
|
|
480
549
|
let response = null;
|
|
481
550
|
const req = (address.https ? https : http).request({
|
|
482
|
-
hostname: address.hostname,
|
|
483
|
-
|
|
551
|
+
hostname: this.#route ? '127.0.0.1' : address.hostname,
|
|
552
|
+
port: this.#route?.port ?? (address.port ? Number(address.port) : undefined),
|
|
484
553
|
path: address.path,
|
|
485
554
|
method,
|
|
486
555
|
headers,
|
|
@@ -535,11 +604,6 @@ const INDEX_NAME = 'index.json';
|
|
|
535
604
|
/** The 555 objects of sample-202609221654-8d2f51e0-225cde48 make a 95 536-byte index; this is a bound, not an estimate. */
|
|
536
605
|
const INDEX_LIMIT = 16 * 1024 * 1024;
|
|
537
606
|
const DIRECTORY_PARTS = ['artifacts', 'statics', 'scripts', 'attestations'];
|
|
538
|
-
/** The same rule `loadRelease` applies — the court holds the two to one answer. */
|
|
539
|
-
const RELEASE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
540
|
-
export function isReleaseId(id) {
|
|
541
|
-
return RELEASE_ID.test(id) && !id.includes('..');
|
|
542
|
-
}
|
|
543
607
|
/**
|
|
544
608
|
* Why a path may not be a file of a release — or null.
|
|
545
609
|
*
|
|
@@ -671,8 +735,8 @@ export function parseIndex(bytes, id, location) {
|
|
|
671
735
|
const o = raw;
|
|
672
736
|
if (!o || typeof o !== 'object')
|
|
673
737
|
throw new Error(`${where} is not an object`);
|
|
674
|
-
if (o.format !== 1)
|
|
675
|
-
throw new Error(`${where}
|
|
738
|
+
if (o.format !== 1 && o.format !== 2)
|
|
739
|
+
throw new Error(`${where} uses unsupported release index format ${String(o.format)}`);
|
|
676
740
|
if (o.release !== id)
|
|
677
741
|
throw new Error(`${where} describes release '${String(o.release)}', not '${id}'`);
|
|
678
742
|
if (!Array.isArray(o.files))
|
|
@@ -703,7 +767,7 @@ export function parseIndex(bytes, id, location) {
|
|
|
703
767
|
if (!seen.has('manifest.json'))
|
|
704
768
|
throw new Error(`${where} has no manifest.json`);
|
|
705
769
|
return {
|
|
706
|
-
format:
|
|
770
|
+
format: o.format,
|
|
707
771
|
release: id,
|
|
708
772
|
pushedAt: typeof o.pushedAt === 'string' ? o.pushedAt : '',
|
|
709
773
|
pushedBy: typeof o.pushedBy === 'string' ? o.pushedBy : '',
|
|
@@ -842,10 +906,13 @@ function placeOf(dir, rel) {
|
|
|
842
906
|
* as against «a different file», and a twelve-character prefix is not what
|
|
843
907
|
* an operator can paste into `grep`.
|
|
844
908
|
*/
|
|
845
|
-
|
|
909
|
+
function payloadKey(id, entry, format) {
|
|
910
|
+
return format === 1 ? `${id}/${entry.path}` : `${id}/objects/${entry.sha256}`;
|
|
911
|
+
}
|
|
912
|
+
async function fetchVerified(store, id, entry, file, consequence, format) {
|
|
846
913
|
let got;
|
|
847
914
|
try {
|
|
848
|
-
got = await store.get(
|
|
915
|
+
got = await store.get(payloadKey(id, entry, format), file, entry.bytes);
|
|
849
916
|
}
|
|
850
917
|
catch (err) {
|
|
851
918
|
throw new Error(`Release ${id}: ${err.message}. ${consequence}`, { cause: err });
|
|
@@ -879,43 +946,90 @@ export async function pushRelease(id, store, options = {}) {
|
|
|
879
946
|
const local = await walkRelease(loaded.root);
|
|
880
947
|
checkAgainstManifest(id, loaded.manifest, local, 'on this disk');
|
|
881
948
|
const indexKey = `${id}/${INDEX_NAME}`;
|
|
882
|
-
const
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
949
|
+
const uploaded = new Set();
|
|
950
|
+
let moved = { files: 0, bytes: 0 };
|
|
951
|
+
return publishIndex(0);
|
|
952
|
+
async function publishIndex(attempt) {
|
|
953
|
+
options.signal?.throwIfAborted();
|
|
954
|
+
const version = await store.readVersion(indexKey, INDEX_LIMIT);
|
|
955
|
+
const existing = version?.body;
|
|
956
|
+
const remote = existing ? parseIndex(existing, id, store.location) : null;
|
|
957
|
+
let send = local;
|
|
958
|
+
let files = local;
|
|
959
|
+
let keptNewer = [];
|
|
960
|
+
if (remote) {
|
|
961
|
+
const differences = compareBuilds(local, remote.files);
|
|
962
|
+
if (differences.length > 0)
|
|
963
|
+
throw new Error(differentBuild(id, differences, 'this machine', store.location));
|
|
964
|
+
const plan = planAttestations(local.filter(isAttestation), remote.files.filter(isAttestation));
|
|
965
|
+
const kept = new Set(plan.kept.map((k) => k.path));
|
|
966
|
+
send = options.repair ? local.filter((e) => !kept.has(e.path)) : plan.copy;
|
|
967
|
+
keptNewer = plan.kept;
|
|
968
|
+
files = [...remote.files.filter((e) => !isAttestation(e)), ...plan.merged].sort(byPath);
|
|
969
|
+
if (send.length === 0) {
|
|
970
|
+
return { id, location: store.location, parts: tallyParts(remote.files), moved, indexSha256: sha256Hex(existing), keptNewer };
|
|
971
|
+
}
|
|
898
972
|
}
|
|
973
|
+
// When extending a legacy index, copy its complete verified snapshot before switching the pointer.
|
|
974
|
+
// Immutable objects keep both competing publishers' snapshots readable until the index chooses one.
|
|
975
|
+
if (remote?.format === 1)
|
|
976
|
+
send = files;
|
|
977
|
+
const localByPath = new Map(local.map(entry => [entry.path, entry]));
|
|
978
|
+
const total = tally(send);
|
|
979
|
+
let done = { files: 0, bytes: 0 };
|
|
980
|
+
await eachLimited(send, options.concurrency ?? 8, async (entry) => {
|
|
981
|
+
options.signal?.throwIfAborted();
|
|
982
|
+
let source = placeOf(loaded.root, entry.path);
|
|
983
|
+
if (localByPath.get(entry.path)?.sha256 !== entry.sha256) {
|
|
984
|
+
if (remote?.format !== 1 || !isAttestation(entry) || entry.bytes > INDEX_LIMIT)
|
|
985
|
+
throw Error('Cannot migrate release object ' + entry.path);
|
|
986
|
+
const data = await store.read(payloadKey(id, entry, 1), entry.bytes);
|
|
987
|
+
if (!data || data.length !== entry.bytes || sha256Hex(data) !== entry.sha256)
|
|
988
|
+
throw Error('Legacy attestation failed verification: ' + entry.path);
|
|
989
|
+
source = data;
|
|
990
|
+
}
|
|
991
|
+
if (!uploaded.has(entry.sha256)) {
|
|
992
|
+
await store.put(payloadKey(id, entry, 2), source, entry);
|
|
993
|
+
uploaded.add(entry.sha256);
|
|
994
|
+
moved = { bytes: moved.bytes + entry.bytes, files: moved.files + 1 };
|
|
995
|
+
}
|
|
996
|
+
done = { files: done.files + 1, bytes: done.bytes + entry.bytes };
|
|
997
|
+
options.onProgress?.(done, total);
|
|
998
|
+
});
|
|
999
|
+
// Last, and only now: the index is what makes the release exist in the store.
|
|
1000
|
+
const index = {
|
|
1001
|
+
format: 2,
|
|
1002
|
+
release: id,
|
|
1003
|
+
pushedAt: new Date().toISOString(),
|
|
1004
|
+
pushedBy: `${os.userInfo().username}@${os.hostname()}`,
|
|
1005
|
+
files,
|
|
1006
|
+
};
|
|
1007
|
+
const body = Buffer.from(`${JSON.stringify(index, null, 2)}\n`);
|
|
1008
|
+
const indexSha256 = sha256Hex(body);
|
|
1009
|
+
options.signal?.throwIfAborted();
|
|
1010
|
+
try {
|
|
1011
|
+
await store.put(indexKey, body, { sha256: indexSha256, bytes: body.length }, { etag: version?.etag ?? null });
|
|
1012
|
+
}
|
|
1013
|
+
catch (error) {
|
|
1014
|
+
if (!(error instanceof StoreConflict))
|
|
1015
|
+
throw error;
|
|
1016
|
+
const winner = await store.read(indexKey, INDEX_LIMIT);
|
|
1017
|
+
if (!winner)
|
|
1018
|
+
throw error;
|
|
1019
|
+
const committed = parseIndex(winner, id, store.location);
|
|
1020
|
+
const differences = compareBuilds(local, committed.files);
|
|
1021
|
+
if (differences.length)
|
|
1022
|
+
throw new Error(differentBuild(id, differences, 'this machine', store.location), { cause: error });
|
|
1023
|
+
const plan = planAttestations(local.filter(isAttestation), committed.files.filter(isAttestation));
|
|
1024
|
+
if (plan.copy.length) {
|
|
1025
|
+
if (attempt >= 4)
|
|
1026
|
+
throw new Error(`Release ${id} changed during five publication attempts. Repeat release push to merge the outstanding measurements.`, { cause: error });
|
|
1027
|
+
return publishIndex(attempt + 1);
|
|
1028
|
+
}
|
|
1029
|
+
return { id, location: store.location, parts: tallyParts(committed.files), moved, indexSha256: sha256Hex(winner), keptNewer: plan.kept };
|
|
1030
|
+
}
|
|
1031
|
+
return { id, location: store.location, parts: tallyParts(files), moved, indexSha256, keptNewer };
|
|
899
1032
|
}
|
|
900
|
-
const total = tally(send);
|
|
901
|
-
let done = { files: 0, bytes: 0 };
|
|
902
|
-
await eachLimited(send, options.concurrency ?? 8, async (entry) => {
|
|
903
|
-
await store.put(`${id}/${entry.path}`, placeOf(loaded.root, entry.path), entry);
|
|
904
|
-
done = { files: done.files + 1, bytes: done.bytes + entry.bytes };
|
|
905
|
-
options.onProgress?.(done, total);
|
|
906
|
-
});
|
|
907
|
-
// Last, and only now: the index is what makes the release exist in the store.
|
|
908
|
-
const index = {
|
|
909
|
-
format: 1,
|
|
910
|
-
release: id,
|
|
911
|
-
pushedAt: new Date().toISOString(),
|
|
912
|
-
pushedBy: `${os.userInfo().username}@${os.hostname()}`,
|
|
913
|
-
files,
|
|
914
|
-
};
|
|
915
|
-
const body = Buffer.from(`${JSON.stringify(index, null, 2)}\n`);
|
|
916
|
-
const indexSha256 = sha256Hex(body);
|
|
917
|
-
await store.put(indexKey, body, { sha256: indexSha256, bytes: body.length });
|
|
918
|
-
return { id, location: store.location, parts: tallyParts(files), moved: total, indexSha256, keptNewer };
|
|
919
1033
|
}
|
|
920
1034
|
/**
|
|
921
1035
|
* Take a release out of the store onto this machine.
|
|
@@ -954,7 +1068,7 @@ export async function pullRelease(id, store, options = {}) {
|
|
|
954
1068
|
// `*.json`, so a half-written one is never read as evidence.
|
|
955
1069
|
const partial = `${file}.pull-${process.pid}`;
|
|
956
1070
|
try {
|
|
957
|
-
await fetchVerified(store, id, entry, partial, `${file} was left as it was
|
|
1071
|
+
await fetchVerified(store, id, entry, partial, `${file} was left as it was.`, index.format);
|
|
958
1072
|
fs.renameSync(partial, file);
|
|
959
1073
|
}
|
|
960
1074
|
finally {
|
|
@@ -985,7 +1099,7 @@ export async function pullRelease(id, store, options = {}) {
|
|
|
985
1099
|
await eachLimited(index.files, options.concurrency ?? 8, async (entry) => {
|
|
986
1100
|
const file = placeOf(staged, entry.path);
|
|
987
1101
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
988
|
-
await fetchVerified(store, id, entry, file, consequence);
|
|
1102
|
+
await fetchVerified(store, id, entry, file, consequence, index.format);
|
|
989
1103
|
done = { files: done.files + 1, bytes: done.bytes + entry.bytes };
|
|
990
1104
|
options.onProgress?.(done, total);
|
|
991
1105
|
});
|