@openge/forge-release-vercel 0.1.0-rc.1 → 0.1.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.
Files changed (104) hide show
  1. package/README.md +43 -6
  2. package/dist/cli-arguments.js +1 -1
  3. package/dist/cli-arguments.js.map +1 -1
  4. package/dist/cli-runner.js +2 -2
  5. package/dist/cli-runner.js.map +1 -1
  6. package/dist/contracts.d.ts +58 -6
  7. package/dist/contracts.d.ts.map +1 -1
  8. package/dist/contracts.js +2 -0
  9. package/dist/contracts.js.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/node/config.d.ts.map +1 -1
  13. package/dist/node/config.js +27 -5
  14. package/dist/node/config.js.map +1 -1
  15. package/dist/node/execution.d.ts +4 -1
  16. package/dist/node/execution.d.ts.map +1 -1
  17. package/dist/node/execution.js +48 -10
  18. package/dist/node/execution.js.map +1 -1
  19. package/dist/node/git-context.d.ts +3 -0
  20. package/dist/node/git-context.d.ts.map +1 -0
  21. package/dist/node/git-context.js +9 -0
  22. package/dist/node/git-context.js.map +1 -0
  23. package/dist/node/git-stream.d.ts +5 -0
  24. package/dist/node/git-stream.d.ts.map +1 -0
  25. package/dist/node/git-stream.js +41 -0
  26. package/dist/node/git-stream.js.map +1 -0
  27. package/dist/node/git.js +1 -1
  28. package/dist/node/git.js.map +1 -1
  29. package/dist/node/lock.d.ts +7 -1
  30. package/dist/node/lock.d.ts.map +1 -1
  31. package/dist/node/lock.js +2 -2
  32. package/dist/node/lock.js.map +1 -1
  33. package/dist/node/managed-budget.d.ts +28 -0
  34. package/dist/node/managed-budget.d.ts.map +1 -0
  35. package/dist/node/managed-budget.js +131 -0
  36. package/dist/node/managed-budget.js.map +1 -0
  37. package/dist/node/managed-checkout.d.ts +5 -0
  38. package/dist/node/managed-checkout.d.ts.map +1 -0
  39. package/dist/node/managed-checkout.js +104 -0
  40. package/dist/node/managed-checkout.js.map +1 -0
  41. package/dist/node/managed-closure.d.ts +4 -0
  42. package/dist/node/managed-closure.d.ts.map +1 -0
  43. package/dist/node/managed-closure.js +10 -0
  44. package/dist/node/managed-closure.js.map +1 -0
  45. package/dist/node/managed-io.d.ts +23 -0
  46. package/dist/node/managed-io.d.ts.map +1 -0
  47. package/dist/node/managed-io.js +168 -0
  48. package/dist/node/managed-io.js.map +1 -0
  49. package/dist/node/managed-paths.d.ts +7 -0
  50. package/dist/node/managed-paths.d.ts.map +1 -0
  51. package/dist/node/managed-paths.js +191 -0
  52. package/dist/node/managed-paths.js.map +1 -0
  53. package/dist/node/managed-process.d.ts +3 -0
  54. package/dist/node/managed-process.d.ts.map +1 -0
  55. package/dist/node/managed-process.js +110 -0
  56. package/dist/node/managed-process.js.map +1 -0
  57. package/dist/node/managed-recovery-lock.d.ts +7 -0
  58. package/dist/node/managed-recovery-lock.d.ts.map +1 -0
  59. package/dist/node/managed-recovery-lock.js +61 -0
  60. package/dist/node/managed-recovery-lock.js.map +1 -0
  61. package/dist/node/managed-recovery.d.ts +13 -0
  62. package/dist/node/managed-recovery.d.ts.map +1 -0
  63. package/dist/node/managed-recovery.js +395 -0
  64. package/dist/node/managed-recovery.js.map +1 -0
  65. package/dist/node/managed-release.d.ts +3 -0
  66. package/dist/node/managed-release.d.ts.map +1 -0
  67. package/dist/node/managed-release.js +102 -0
  68. package/dist/node/managed-release.js.map +1 -0
  69. package/dist/node/managed-state.d.ts +7 -0
  70. package/dist/node/managed-state.d.ts.map +1 -0
  71. package/dist/node/managed-state.js +110 -0
  72. package/dist/node/managed-state.js.map +1 -0
  73. package/dist/node/owned-command-runner.d.ts +3 -0
  74. package/dist/node/owned-command-runner.d.ts.map +1 -0
  75. package/dist/node/owned-command-runner.js +10 -0
  76. package/dist/node/owned-command-runner.js.map +1 -0
  77. package/dist/node/process-identities.d.ts +5 -0
  78. package/dist/node/process-identities.d.ts.map +1 -0
  79. package/dist/node/process-identities.js +23 -0
  80. package/dist/node/process-identities.js.map +1 -0
  81. package/dist/node/publication.d.ts +5 -0
  82. package/dist/node/publication.d.ts.map +1 -0
  83. package/dist/node/publication.js +57 -0
  84. package/dist/node/publication.js.map +1 -0
  85. package/dist/node/release-commands.d.ts +4 -0
  86. package/dist/node/release-commands.d.ts.map +1 -0
  87. package/dist/node/release-commands.js +6 -0
  88. package/dist/node/release-commands.js.map +1 -0
  89. package/dist/node/release-context.d.ts +128 -0
  90. package/dist/node/release-context.d.ts.map +1 -0
  91. package/dist/node/release-context.js +2 -0
  92. package/dist/node/release-context.js.map +1 -0
  93. package/dist/node/release.d.ts.map +1 -1
  94. package/dist/node/release.js +20 -139
  95. package/dist/node/release.js.map +1 -1
  96. package/dist/node/source.d.ts +14 -0
  97. package/dist/node/source.d.ts.map +1 -0
  98. package/dist/node/source.js +95 -0
  99. package/dist/node/source.js.map +1 -0
  100. package/dist/node/workspace-release.d.ts +5 -0
  101. package/dist/node/workspace-release.d.ts.map +1 -0
  102. package/dist/node/workspace-release.js +122 -0
  103. package/dist/node/workspace-release.js.map +1 -0
  104. package/package.json +5 -4
@@ -0,0 +1,168 @@
1
+ import { lstat, open, opendir, realpath, rename, statfs, unlink } from 'node:fs/promises';
2
+ import { dirname, isAbsolute, relative, resolve } from 'node:path';
3
+ import { record, ReleaseError } from './errors.js';
4
+ export const within = (root, path) => {
5
+ const value = relative(root, path);
6
+ return value === '' || (!isAbsolute(value) && value !== '..' && !value.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`));
7
+ };
8
+ export const fileIdentity = async (path) => { const stat = await lstat(path, { bigint: true }); return { dev: stat.dev.toString(), ino: stat.ino.toString() }; };
9
+ export const sameIdentity = (a, b) => {
10
+ const canonical = (value) => typeof value === 'bigint' ? value.toString() : typeof value === 'string' && /^\d+$/u.test(value) ? value : undefined;
11
+ const dev = canonical(a.dev), ino = canonical(a.ino);
12
+ return dev !== undefined && ino !== undefined && dev === canonical(b.dev) && ino === canonical(b.ino);
13
+ };
14
+ export async function pathExists(path) {
15
+ try {
16
+ await lstat(path);
17
+ return true;
18
+ }
19
+ catch (error) {
20
+ if (record(error).code === 'ENOENT')
21
+ return false;
22
+ throw error;
23
+ }
24
+ }
25
+ export async function assertPathChain(root, path) {
26
+ if (!within(root, path))
27
+ throw new ReleaseError('SLOT_PATH');
28
+ const parts = relative(root, path).split(/[\\/]/u).filter(Boolean);
29
+ let current = root;
30
+ for (let index = -1; index < parts.length; index++) {
31
+ if (index >= 0)
32
+ current = resolve(current, parts[index] ?? '');
33
+ try {
34
+ const stat = await lstat(current);
35
+ if (stat.isSymbolicLink() || await realpath(current) !== current)
36
+ throw new ReleaseError('SLOT_PATH', { reason: 'LINK_ANCESTOR' });
37
+ if (!stat.isDirectory() && index < parts.length - 1)
38
+ throw new ReleaseError('SLOT_PATH');
39
+ }
40
+ catch (error) {
41
+ if (record(error).code === 'ENOENT')
42
+ return;
43
+ throw error;
44
+ }
45
+ }
46
+ }
47
+ export async function readBoundedJson(path, maxBytes = 1_048_576) {
48
+ let handle;
49
+ try {
50
+ const before = await lstat(path, { bigint: true });
51
+ if (!before.isFile() || before.size > BigInt(maxBytes))
52
+ throw new ReleaseError('SLOT_STATE', { reason: 'FILE_SIZE_OR_TYPE' });
53
+ handle = await open(path, 'r');
54
+ const after = await handle.stat({ bigint: true });
55
+ if (!sameIdentity(before, after))
56
+ throw new ReleaseError('SLOT_STATE', { reason: 'FILE_REPLACED' });
57
+ const bytes = Buffer.alloc(maxBytes + 1);
58
+ let offset = 0;
59
+ while (offset < bytes.length) {
60
+ const result = await handle.read(bytes, offset, bytes.length - offset, null);
61
+ if (result.bytesRead === 0)
62
+ break;
63
+ offset += result.bytesRead;
64
+ }
65
+ if (offset > maxBytes)
66
+ throw new ReleaseError('SLOT_STATE', { reason: 'FILE_SIZE' });
67
+ return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes.subarray(0, offset)));
68
+ }
69
+ catch (error) {
70
+ if (record(error).code === 'ENOENT')
71
+ return undefined;
72
+ if (error instanceof ReleaseError)
73
+ throw error;
74
+ throw new ReleaseError('SLOT_STATE', { reason: 'JSON_READ' });
75
+ }
76
+ finally {
77
+ await handle?.close();
78
+ }
79
+ }
80
+ export async function measureManagedUsageOnce(paths, signal) {
81
+ let bytes = 0, entries = 0;
82
+ const active = () => { if (signal?.aborted)
83
+ throw new ReleaseError('BUDGET_UNKNOWN', { reason: 'OBSERVATION_DEADLINE' }); };
84
+ const visit = async (path) => {
85
+ active();
86
+ if (++entries > 500_000)
87
+ throw new ReleaseError('BUDGET_UNKNOWN', { reason: 'ENTRY_LIMIT' });
88
+ const stat = await lstat(path);
89
+ if (stat.isSymbolicLink()) {
90
+ if (!within(paths.slotRoot, await realpath(path)))
91
+ throw new ReleaseError('BUDGET_UNKNOWN', { reason: 'EXTERNAL_LINK' });
92
+ bytes += stat.size;
93
+ }
94
+ else if (stat.isDirectory()) {
95
+ const directory = await opendir(path);
96
+ if (signal?.aborted) {
97
+ await directory.close();
98
+ active();
99
+ }
100
+ for await (const entry of directory)
101
+ await visit(resolve(path, entry.name));
102
+ }
103
+ else if (stat.isFile())
104
+ bytes += stat.size;
105
+ else
106
+ throw new ReleaseError('BUDGET_UNKNOWN', { reason: 'FILE_TYPE' });
107
+ if (!Number.isSafeInteger(bytes))
108
+ throw new ReleaseError('BUDGET_UNKNOWN', { reason: 'SIZE_OVERFLOW' });
109
+ };
110
+ try {
111
+ await visit(paths.slotRoot);
112
+ if (await pathExists(paths.anchorPath)) {
113
+ const stat = await lstat(paths.anchorPath);
114
+ if (!stat.isFile())
115
+ throw new ReleaseError('BUDGET_UNKNOWN', { reason: 'ANCHOR_TYPE' });
116
+ bytes += stat.size;
117
+ }
118
+ const volume = await statfs(paths.slotRoot, { bigint: true });
119
+ active();
120
+ const available = volume.bavail * volume.bsize;
121
+ if (available < 0n || available > BigInt(Number.MAX_SAFE_INTEGER))
122
+ throw new ReleaseError('BUDGET_UNKNOWN', { reason: 'VOLUME_SIZE' });
123
+ return { bytes, freeBytes: Number(available) };
124
+ }
125
+ catch (error) {
126
+ if (error instanceof ReleaseError)
127
+ throw error;
128
+ throw new ReleaseError('BUDGET_UNKNOWN', { reason: 'IO_OBSERVATION', ioCode: record(error).code,
129
+ entry: typeof record(error).path === 'string' ? relative(paths.slotRoot, String(record(error).path)) : undefined });
130
+ }
131
+ }
132
+ export async function measureManagedUsage(paths, signal, scan = measureManagedUsageOnce) {
133
+ for (let attempt = 0;; attempt++) {
134
+ try {
135
+ return await scan(paths, signal);
136
+ }
137
+ catch (error) {
138
+ // 正常 rename 可令已枚举条目消失;丢弃整次扫描,不能累计部分清单。
139
+ if (attempt >= 2 || !(error instanceof ReleaseError) || error.details.reason !== 'IO_OBSERVATION' || error.details.ioCode !== 'ENOENT')
140
+ throw error;
141
+ }
142
+ }
143
+ }
144
+ export async function atomicJson(path, value, maxBytes, paths, guard, maxTotal, minFree) {
145
+ const bytes = Buffer.from(`${JSON.stringify(value)}\n`, 'utf8');
146
+ if (bytes.length > maxBytes)
147
+ throw new ReleaseError('BUDGET_EXCEEDED', { reason: 'METADATA_LIMIT' });
148
+ await guard();
149
+ const usage = await measureManagedUsage(paths);
150
+ // 原文件与原子替换的临时文件会短暂共存,按写入峰值准入。
151
+ if (usage.bytes + bytes.length > maxTotal || usage.freeBytes - bytes.length < minFree)
152
+ throw new ReleaseError('BUDGET_EXCEEDED', { reason: 'METADATA_ADMISSION' });
153
+ const temporary = resolve(dirname(path), `.${path.slice(dirname(path).length + 1)}.next`);
154
+ const handle = await open(temporary, 'wx');
155
+ try {
156
+ await handle.writeFile(bytes);
157
+ await handle.sync();
158
+ }
159
+ catch (error) {
160
+ await handle.close();
161
+ await unlink(temporary);
162
+ throw error;
163
+ }
164
+ await handle.close();
165
+ await guard();
166
+ await rename(temporary, path);
167
+ }
168
+ //# sourceMappingURL=managed-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-io.js","sourceRoot":"","sources":["../../src/node/managed-io.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { Execution } from './execution.js';
2
+ import type { FrozenSource, ManagedPaths, ManagedSlot } from './release-context.js';
3
+ export declare function assertManagementUntracked(source: FrozenSource, execution: Execution): Promise<void>;
4
+ export declare function resolveManagedPaths(source: FrozenSource, execution: Execution): Promise<ManagedPaths>;
5
+ export declare function assertManagedPaths(paths: ManagedPaths): Promise<void>;
6
+ export declare function openManagedSlot(source: FrozenSource, execution: Execution): Promise<ManagedSlot>;
7
+ //# sourceMappingURL=managed-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-paths.d.ts","sourceRoot":"","sources":["../../src/node/managed-paths.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AASpF,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCzG;AAcD,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAe3G;AACD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAY3E;AACD,wBAAsB,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAkDtG"}
@@ -0,0 +1,191 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { lstat, mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { dirname, relative, resolve } from 'node:path';
4
+ import { Execution } from './execution.js';
5
+ import { record, ReleaseError } from './errors.js';
6
+ import { assertPathChain, fileIdentity, measureManagedUsage, pathExists, readBoundedJson, sameIdentity, within } from './managed-io.js';
7
+ import { gitBlob, gitRecords } from './git-stream.js';
8
+ import { acquireLock } from './lock.js';
9
+ import { createManagedStateStore } from './managed-state.js';
10
+ import { currentCoordinator } from './process-identities.js';
11
+ import { assertNoGitContext } from './git-context.js';
12
+ import { hasVerifiedManagedClosure } from './managed-closure.js';
13
+ export async function assertManagementUntracked(source, execution) {
14
+ assertNoGitContext();
15
+ if (source.config.source.mode !== 'managed-commit')
16
+ throw new ReleaseError('SOURCE_UNSUPPORTED');
17
+ const pathspec = (path) => process.platform === 'win32' ? `:(icase,literal)${path}` : `:(literal)${path}`;
18
+ const managementPaths = [source.config.source.slotPath, '.tmp/forge-vercel-release'], paths = managementPaths.map(pathspec);
19
+ let tracked = false;
20
+ await gitRecords(execution, ['ls-files', '-z', '--', ...paths], () => { tracked = true; });
21
+ // ls-tree 的旧版本不支持 icase magic;逐层核对真实 tree 名称,不遗漏大小写路径。
22
+ const cache = new Map();
23
+ const entries = async (tree) => {
24
+ let values = cache.get(tree);
25
+ if (!values) {
26
+ values = [];
27
+ await gitRecords(execution, ['ls-tree', '-z', tree], record => {
28
+ const match = /^\d{6} (blob|tree|commit) ([a-f0-9]{40})\t([\s\S]+)$/u.exec(record);
29
+ if (!match?.[1] || !match[2] || !match[3])
30
+ throw new ReleaseError('SLOT_PATH', { reason: 'HEAD_TREE' });
31
+ values?.push({ type: match[1], oid: match[2], name: match[3] });
32
+ });
33
+ cache.set(tree, values);
34
+ }
35
+ return values;
36
+ };
37
+ for (const path of managementPaths) {
38
+ let trees = ['HEAD'];
39
+ const parts = path.split('/');
40
+ for (const [index, part] of parts.entries()) {
41
+ const next = [];
42
+ for (const tree of trees)
43
+ for (const entry of await entries(tree)) {
44
+ if ((process.platform === 'win32' ? entry.name.toLowerCase() : entry.name) !== (process.platform === 'win32' ? part.toLowerCase() : part))
45
+ continue;
46
+ if (index === parts.length - 1 || entry.type !== 'tree')
47
+ tracked = true;
48
+ else
49
+ next.push(entry.oid);
50
+ }
51
+ trees = next;
52
+ }
53
+ }
54
+ if (tracked)
55
+ throw new ReleaseError('SLOT_PATH', { reason: 'TRACKED_MANAGEMENT_PATH' });
56
+ }
57
+ async function assertCommittedIgnore(source, execution, path) {
58
+ let output;
59
+ try {
60
+ output = await execution.git(['-c', 'core.quotepath=false', 'check-ignore', '--no-index', '-v', '--', path]);
61
+ }
62
+ catch (error) {
63
+ if (error instanceof ReleaseError && error.details.exitCode === 1)
64
+ throw new ReleaseError('SLOT_PATH', { reason: 'NOT_IGNORED' });
65
+ throw error;
66
+ }
67
+ const fields = /^([^\r\n]+):[1-9]\d*:([^\t\r\n]*)\t[^\r\n]+$/u.exec(output);
68
+ const origin = fields?.[1], pattern = fields?.[2];
69
+ if (!origin || !pattern || pattern.startsWith('!') || !within(source.root, resolve(source.root, origin)) || origin.startsWith('.git/'))
70
+ throw new ReleaseError('SLOT_PATH', { reason: 'NOT_COMMITTED_IGNORED' });
71
+ try {
72
+ const oid = await execution.git(['rev-parse', '--verify', `${source.sha}:${origin.replaceAll('\\', '/')}`]);
73
+ if (!(await readFile(resolve(source.root, origin))).equals(await gitBlob(execution, oid)))
74
+ throw new ReleaseError('SLOT_PATH');
75
+ }
76
+ catch {
77
+ throw new ReleaseError('SLOT_PATH', { reason: 'IGNORE_NOT_COMMITTED' });
78
+ }
79
+ }
80
+ export async function resolveManagedPaths(source, execution) {
81
+ if (source.config.source.mode !== 'managed-commit')
82
+ throw new ReleaseError('SOURCE_UNSUPPORTED');
83
+ const slotRoot = resolve(source.root, source.config.source.slotPath), anchorPath = resolve(source.root, '.tmp/forge-vercel-release/managed.json');
84
+ if (!within(source.root, slotRoot) || slotRoot === source.root || within(slotRoot, anchorPath) || within(dirname(anchorPath), slotRoot))
85
+ throw new ReleaseError('SLOT_PATH');
86
+ await assertPathChain(source.root, slotRoot);
87
+ await assertPathChain(source.root, anchorPath);
88
+ await assertCommittedIgnore(source, execution, `${source.config.source.slotPath}/`);
89
+ await assertCommittedIgnore(source, execution, relative(source.root, anchorPath).replaceAll('\\', '/'));
90
+ let tracked = false;
91
+ await gitRecords(execution, ['ls-tree', '-rz', source.sha, '--', source.config.source.slotPath], () => { tracked = true; });
92
+ if (tracked)
93
+ throw new ReleaseError('SLOT_PATH', { reason: 'TRACKED_SLOT' });
94
+ await assertManagementUntracked(source, execution);
95
+ return { sourceRoot: source.root, slotRoot, checkoutRoot: resolve(slotRoot, 'checkout'), anchorPath,
96
+ ownershipPath: resolve(slotRoot, 'ownership.json'), statePath: resolve(slotRoot, 'state.json'),
97
+ lockPath: resolve(slotRoot, 'run.lock'), recoveryLockPath: resolve(slotRoot, 'recover.lock'),
98
+ sourceIdentity: await fileIdentity(source.root), slotIdentity: await pathExists(slotRoot) ? await fileIdentity(slotRoot) : { dev: '', ino: '' } };
99
+ }
100
+ export async function assertManagedPaths(paths) {
101
+ await assertPathChain(paths.sourceRoot, paths.slotRoot);
102
+ await assertPathChain(paths.sourceRoot, paths.anchorPath);
103
+ if (!sameIdentity(await fileIdentity(paths.sourceRoot), paths.sourceIdentity) || !sameIdentity(await fileIdentity(paths.slotRoot), paths.slotIdentity)
104
+ || paths.sourceIdentity.dev !== paths.slotIdentity.dev)
105
+ throw new ReleaseError('SLOT_PATH', { reason: 'ROOT_REPLACED' });
106
+ if (await pathExists(paths.checkoutRoot)) {
107
+ await assertPathChain(paths.slotRoot, paths.checkoutRoot);
108
+ const gitRoot = resolve(paths.checkoutRoot, '.git');
109
+ if (await pathExists(gitRoot)) {
110
+ await assertPathChain(paths.slotRoot, gitRoot);
111
+ if (!(await lstat(gitRoot)).isDirectory() || await pathExists(resolve(gitRoot, 'commondir')) || await pathExists(resolve(gitRoot, 'objects/info/alternates')))
112
+ throw new ReleaseError('SLOT_PATH', { reason: 'EXTERNAL_GIT' });
113
+ }
114
+ }
115
+ }
116
+ export async function openManagedSlot(source, execution) {
117
+ let paths = await resolveManagedPaths(source, execution);
118
+ const existingAnchor = record(await readBoundedJson(paths.anchorPath, 65_536));
119
+ const anchored = Object.keys(existingAnchor).length > 0;
120
+ if (anchored && (existingAnchor.schemaVersion !== 2 || existingAnchor.sourceRoot !== source.root || existingAnchor.configPath !== source.configPath || existingAnchor.slotPath !== paths.slotRoot)) {
121
+ throw new ReleaseError('SLOT_STATE', { reason: 'MANAGEMENT_REBINDING' });
122
+ }
123
+ if (anchored && !await pathExists(paths.slotRoot))
124
+ throw new ReleaseError('SLOT_FOREIGN', { reason: 'ANCHORED_SLOT_MISSING' });
125
+ const runId = randomUUID(), coordinator = await currentCoordinator(execution.signal);
126
+ await mkdir(dirname(paths.slotRoot), { recursive: true });
127
+ await mkdir(dirname(paths.anchorPath), { recursive: true });
128
+ let created = false;
129
+ try {
130
+ await mkdir(paths.slotRoot);
131
+ created = true;
132
+ }
133
+ catch (error) {
134
+ if (record(error).code !== 'EEXIST')
135
+ throw error;
136
+ }
137
+ paths = { ...paths, slotIdentity: await fileIdentity(paths.slotRoot) };
138
+ let slotId = randomUUID();
139
+ if (!created) {
140
+ let owner;
141
+ try {
142
+ owner = record(await readBoundedJson(paths.ownershipPath, 65_536));
143
+ }
144
+ catch {
145
+ throw new ReleaseError('SLOT_FOREIGN');
146
+ }
147
+ if (owner.schemaVersion !== 2 || typeof owner.slotId !== 'string' || !/^[a-f0-9-]{36}$/u.test(owner.slotId)
148
+ || owner.sourceRoot !== source.root || owner.configPath !== source.configPath || owner.repository !== source.config.git.repository
149
+ || !sameIdentity(record(owner.sourceIdentity), paths.sourceIdentity)
150
+ || !sameIdentity(record(owner.slotIdentity), paths.slotIdentity))
151
+ throw new ReleaseError('SLOT_FOREIGN');
152
+ slotId = owner.slotId;
153
+ if (anchored && existingAnchor.slotId !== slotId)
154
+ throw new ReleaseError('SLOT_STATE', { reason: 'ANCHOR_SLOT_ID' });
155
+ const allowed = ['ownership.json', 'run.lock', 'recover.lock', 'state.json', 'checkout', 'latest-check.json', 'latest-publish.json', 'command-gate.json', 'command-result.json'];
156
+ if ((await readdir(paths.slotRoot)).some(name => !allowed.includes(name)))
157
+ throw new ReleaseError('SLOT_FOREIGN', { reason: 'UNKNOWN_ENTRY' });
158
+ }
159
+ await assertManagedPaths(paths);
160
+ if (await pathExists(paths.recoveryLockPath))
161
+ throw new ReleaseError('LOCKED', { reason: 'RECOVERY_ACTIVE' });
162
+ if (source.config.source.mode !== 'managed-commit')
163
+ throw new ReleaseError('SOURCE_UNSUPPORTED');
164
+ const usage = await measureManagedUsage(paths), budget = source.config.source;
165
+ const ownerJson = JSON.stringify({ schemaVersion: 2, slotId, sourceRoot: source.root,
166
+ configPath: source.configPath, repository: source.config.git.repository, sourceIdentity: paths.sourceIdentity, slotIdentity: paths.slotIdentity });
167
+ const admissionBytes = 1024 + (created ? Buffer.byteLength(ownerJson) : 0);
168
+ if (Buffer.byteLength(ownerJson) > 65_536 || usage.bytes + admissionBytes > budget.maxBytes || usage.freeBytes - admissionBytes < budget.minFreeBytes)
169
+ throw new ReleaseError('BUDGET_EXCEEDED', { reason: 'SLOT_ADMISSION' });
170
+ const rawLock = await acquireLock(paths.lockPath, { runId, identity: coordinator });
171
+ const management = new Execution(source.root, source.config, undefined, []);
172
+ const assertOwned = async () => { await assertManagedPaths(paths); await assertManagementUntracked(source, management); await rawLock.assertOwned(); };
173
+ const lock = { assertOwned, release: async () => { await assertOwned(); await rawLock.release(); } };
174
+ try {
175
+ if (await pathExists(paths.recoveryLockPath))
176
+ throw new ReleaseError('LOCKED', { reason: 'RECOVERY_ACTIVE' });
177
+ if (created)
178
+ await writeFile(paths.ownershipPath, ownerJson, { encoding: 'utf8', flag: 'wx' });
179
+ const guard = async () => { await assertManagedPaths(paths); await lock.assertOwned(); };
180
+ const store = createManagedStateStore(paths, source, slotId, guard);
181
+ const state = await store.read();
182
+ if (state && (state.status !== 'closed' || state.pendingPush || Object.values(state.effects).includes('unknown') || !state.processes.every(hasVerifiedManagedClosure)))
183
+ throw new ReleaseError('RECOVERY_REQUIRED', { runId: state.runId });
184
+ return { paths, source, slotId, lock, store, runId, coordinator };
185
+ }
186
+ catch (error) {
187
+ await lock.release();
188
+ throw error;
189
+ }
190
+ }
191
+ //# sourceMappingURL=managed-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-paths.js","sourceRoot":"","sources":["../../src/node/managed-paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ManagedSession, ManagedSlot } from './release-context.js';
2
+ export declare function createManagedSession(slot: ManagedSlot, command: 'check' | 'publish' | 'verify', signal?: AbortSignal): Promise<ManagedSession>;
3
+ //# sourceMappingURL=managed-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-process.d.ts","sourceRoot":"","sources":["../../src/node/managed-process.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAsC,cAAc,EAAE,WAAW,EAAgB,MAAM,sBAAsB,CAAC;AAmE1H,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,QAAQ,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CASpJ"}
@@ -0,0 +1,110 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { resolve } from 'node:path';
3
+ import { ReleaseError } from './errors.js';
4
+ import { within } from './managed-io.js';
5
+ import { assertManagedPaths } from './managed-paths.js';
6
+ import { BudgetMonitor } from './managed-budget.js';
7
+ import { Execution } from './execution.js';
8
+ import { assertNoGitContext, isolatedGitEnvironment } from './git-context.js';
9
+ import { hasVerifiedManagedClosure } from './managed-closure.js';
10
+ class ManagedProcess {
11
+ slot;
12
+ state;
13
+ budget;
14
+ tail = Promise.resolve();
15
+ constructor(slot, state, budget) {
16
+ this.slot = slot;
17
+ this.state = state;
18
+ this.budget = budget;
19
+ }
20
+ async persist() { await this.slot.store.writeState(this.state); }
21
+ async guard() { assertNoGitContext(); await assertManagedPaths(this.slot.paths); await this.slot.lock.assertOwned(); }
22
+ async assertClosed() {
23
+ if (!this.state.processes.every(hasVerifiedManagedClosure))
24
+ throw new ReleaseError('PROCESS_STATE_UNKNOWN');
25
+ }
26
+ async execute(runner, name, spec, observer) {
27
+ await this.guard();
28
+ await this.assertClosed();
29
+ const command = { id: randomUUID(), name, status: 'intent', descendants: [], observationComplete: false };
30
+ const binding = `${this.state.runId}:${command.id}:${randomUUID()}`;
31
+ this.state.processes.push(command);
32
+ await this.persist();
33
+ return this.budget.run(async (signal) => {
34
+ const failed = new AbortController(), combined = AbortSignal.any([signal, failed.signal]);
35
+ let failure, running;
36
+ const enqueue = (operation) => {
37
+ this.tail = this.tail.then(operation).catch((error) => { failure ??= error; command.observationComplete = false; failed.abort(); });
38
+ };
39
+ try {
40
+ const environment = spec.environment ?? { mode: 'inherit' };
41
+ running = runner.start({ ...spec, signal: combined, ownedScope: { start: 'manual', binding },
42
+ environment: { ...environment, values: { ...environment.values, ...isolatedGitEnvironment(), FORGE_RELEASE_COMMAND: this.state.command, FORGE_RELEASE_SHA: this.slot.source.sha } } }, event => {
43
+ observer?.(event);
44
+ if (event.type === 'spawned')
45
+ enqueue(async () => { command.pid = event.pid; command.status = 'spawned'; await this.persist(); });
46
+ if (event.type === 'scope-ready')
47
+ enqueue(async () => {
48
+ if (event.binding !== binding || !running?.authorizeStart || combined.aborted)
49
+ throw new ReleaseError('PROCESS_STATE_UNKNOWN', { reason: 'SCOPE_BINDING' });
50
+ command.identity = { pid: event.identity.pid, startToken: event.identity.startToken };
51
+ command.scope = { scopeId: event.scopeId, binding };
52
+ command.status = 'identified';
53
+ await this.guard();
54
+ await this.budget.sample();
55
+ await this.persist();
56
+ // 写入、预算和所有权任一步失败都不放行真实 argv。
57
+ await this.guard();
58
+ if (combined.aborted)
59
+ throw new ReleaseError('PROCESS_STATE_UNKNOWN', { reason: 'START_CANCELLED' });
60
+ await running.authorizeStart();
61
+ });
62
+ });
63
+ const result = await running.result;
64
+ await this.tail;
65
+ command.observationComplete = failure === undefined && result.ownedScope?.status === 'closed';
66
+ command.closure = { observedAt: new Date().toISOString(), exitCode: result.exitCode, termination: result.terminationReason,
67
+ ...(result.ownedScope ? { ownedScope: result.ownedScope } : {}) };
68
+ command.status = result.terminationReason === 'exit' && command.observationComplete ? 'closed' : 'unknown';
69
+ if (!hasVerifiedManagedClosure(command)) {
70
+ command.status = 'unknown';
71
+ command.observationComplete = false;
72
+ }
73
+ await this.persist();
74
+ if (failure !== undefined)
75
+ throw failure instanceof ReleaseError ? failure : new ReleaseError('PROCESS_STATE_UNKNOWN', { reason: 'JOURNAL_FAILED', step: name });
76
+ if (command.status !== 'closed')
77
+ throw new ReleaseError('PROCESS_STATE_UNKNOWN', { reason: 'CLOSURE_UNPROVEN', commandId: command.id, step: name,
78
+ termination: result.terminationReason, exitCode: result.exitCode, identified: !!command.identity,
79
+ ...(result.ownedScope ? { scopeReason: result.ownedScope.reason, empty: result.ownedScope.empty } : {}),
80
+ diagnostics: result.diagnostics.map(item => ({ code: item.code, stage: item.details.stage })) });
81
+ return result;
82
+ }
83
+ catch (error) {
84
+ failed.abort();
85
+ await running?.terminate();
86
+ await this.tail;
87
+ command.status = 'unknown';
88
+ command.observationComplete = false;
89
+ try {
90
+ await this.persist();
91
+ }
92
+ catch { /* 最后已持久化的意图仍不是关闭证明,不能释放槽。 */ }
93
+ throw error instanceof ReleaseError ? error : new ReleaseError('PROCESS_STATE_UNKNOWN', { reason: 'PROCESS_LIFECYCLE_FAILED', step: name });
94
+ }
95
+ }, spec.signal);
96
+ }
97
+ }
98
+ export async function createManagedSession(slot, command, signal) {
99
+ if (slot.source.config.source.mode !== 'managed-commit')
100
+ throw new ReleaseError('SOURCE_UNSUPPORTED');
101
+ const state = { schemaVersion: 2, slotId: slot.slotId, runId: slot.runId, source: slot.source, command,
102
+ coordinator: slot.coordinator, stage: 'admission', status: 'running', processes: [], effects: { developmentPush: 'not-attempted', releasePush: 'not-attempted' } };
103
+ const budget = new BudgetMonitor(slot.paths, slot.source.config.source), lifecycle = new ManagedProcess(slot, state, budget), steps = [];
104
+ await lifecycle.persist();
105
+ return { slot, command, state, budget, steps, execution: new Execution(slot.paths.checkoutRoot, slot.source.config, signal, steps, lifecycle),
106
+ persist: () => lifecycle.persist(), assertClosed: () => lifecycle.assertClosed(),
107
+ executionAt: cwd => { if (!within(slot.paths.slotRoot, resolve(cwd)))
108
+ throw new ReleaseError('SLOT_PATH'); return new Execution(cwd, slot.source.config, signal, steps, lifecycle); } };
109
+ }
110
+ //# sourceMappingURL=managed-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-process.js","sourceRoot":"","sources":["../../src/node/managed-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ManagedPaths, ManagedState } from './release-context.js';
2
+ import { type OwnedLock } from './lock.js';
3
+ export declare function claimManagedRecovery(paths: ManagedPaths, state: ManagedState, signal?: AbortSignal): Promise<{
4
+ readonly claim: OwnedLock;
5
+ readonly oldLock?: OwnedLock;
6
+ }>;
7
+ //# sourceMappingURL=managed-recovery-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-recovery-lock.d.ts","sourceRoot":"","sources":["../../src/node/managed-recovery-lock.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAQxD,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC,CAmC/K"}
@@ -0,0 +1,61 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { unlink } from 'node:fs/promises';
3
+ import { acquireLock } from './lock.js';
4
+ import { record, ReleaseError } from './errors.js';
5
+ import { assertManagedPaths, assertManagementUntracked } from './managed-paths.js';
6
+ import { fileIdentity, measureManagedUsage, pathExists, readBoundedJson, sameIdentity } from './managed-io.js';
7
+ import { currentCoordinator } from './process-identities.js';
8
+ import { parseManagedState } from './managed-state.js';
9
+ import { Execution } from './execution.js';
10
+ export async function claimManagedRecovery(paths, state, signal) {
11
+ await assertManagedPaths(paths);
12
+ const management = new Execution(state.source.root, state.source.config, signal, []);
13
+ await assertManagementUntracked(state.source, management);
14
+ const config = state.source.config.source;
15
+ if (config.mode !== 'managed-commit')
16
+ throw new ReleaseError('SOURCE_UNSUPPORTED');
17
+ const usage = await measureManagedUsage(paths);
18
+ if (usage.bytes + 1024 > config.maxBytes || usage.freeBytes - 1024 < config.minFreeBytes)
19
+ throw new ReleaseError('BUDGET_EXCEEDED', { reason: 'RECOVERY_ADMISSION' });
20
+ const coordinator = await currentCoordinator(signal), rawClaim = await acquireLock(paths.recoveryLockPath, { runId: randomUUID(), identity: coordinator });
21
+ const assertClaim = async () => { await assertManagedPaths(paths); await assertManagementUntracked(state.source, management); await rawClaim.assertOwned(); };
22
+ const claim = { assertOwned: assertClaim, release: async () => { await assertClaim(); await rawClaim.release(); } };
23
+ try {
24
+ const current = parseManagedState(await readBoundedJson(paths.statePath), state.source, state.slotId);
25
+ if (JSON.stringify(current) !== JSON.stringify(state))
26
+ throw new ReleaseError('RECOVERY_REQUIRED', { reason: 'RUN_CHANGED' });
27
+ if (!await pathExists(paths.lockPath)) {
28
+ if (state.status !== 'closed' || state.pendingPush || Object.values(state.effects).includes('unknown'))
29
+ throw new ReleaseError('LOCK_OWNERSHIP', { reason: 'RUN_LOCK_MISSING' });
30
+ return { claim };
31
+ }
32
+ const before = await fileIdentity(paths.lockPath), value = record(await readBoundedJson(paths.lockPath, 65_536));
33
+ const identity = record(value.identity), expected = JSON.stringify(value);
34
+ if (value.pid !== state.coordinator.pid || value.runId !== state.runId || identity.pid !== state.coordinator.pid || identity.startToken !== state.coordinator.startToken
35
+ || typeof value.token !== 'string' || !/^[a-f0-9-]{36}$/u.test(value.token))
36
+ throw new ReleaseError('LOCK_OWNERSHIP', { reason: 'RUN_LOCK_BINDING' });
37
+ const assertOwned = async () => {
38
+ await assertManagedPaths(paths);
39
+ await claim.assertOwned();
40
+ try {
41
+ if (!sameIdentity(await fileIdentity(paths.lockPath), before) || JSON.stringify(await readBoundedJson(paths.lockPath, 65_536)) !== expected)
42
+ throw new ReleaseError('LOCK_OWNERSHIP');
43
+ }
44
+ catch {
45
+ throw new ReleaseError('LOCK_OWNERSHIP', { reason: 'RUN_LOCK_REPLACED_OR_UNREADABLE' });
46
+ }
47
+ };
48
+ await assertOwned();
49
+ return { claim, oldLock: { assertOwned, release: async () => { await assertOwned(); await unlink(paths.lockPath); } } };
50
+ }
51
+ catch (error) {
52
+ try {
53
+ await claim.release();
54
+ }
55
+ catch {
56
+ throw new ReleaseError('LOCK_OWNERSHIP', { reason: 'RECOVERY_CLAIM_LOST', priorCode: error instanceof ReleaseError ? error.code : 'IO_FAILED' });
57
+ }
58
+ throw error;
59
+ }
60
+ }
61
+ //# sourceMappingURL=managed-recovery-lock.js.map