@zgeoff/atc 3.2.0 → 3.3.1
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/README.md +6 -0
- package/package.json +4 -3
- package/src/build-own-daemon-process.ts +16 -0
- package/src/build-restart-failure.ts +24 -0
- package/src/cli.ts +96 -0
- package/src/client/boot-daemon.ts +5 -32
- package/src/collect-restart-env.ts +18 -0
- package/src/collect-restart-plan.ts +157 -0
- package/src/daemon/daemon.ts +7 -3
- package/src/daemon-process.ts +12 -0
- package/src/find-restart-unit.ts +45 -0
- package/src/format-restart-preflight.ts +74 -0
- package/src/format-restart-report.ts +45 -0
- package/src/is-daemon-command-line.ts +33 -0
- package/src/is-daemon-process.ts +33 -0
- package/src/parse-daemon-flags.ts +33 -0
- package/src/parse-mismatch-build.ts +19 -0
- package/src/parse-restart-result.ts +65 -0
- package/src/parse-systemd-unit.ts +25 -0
- package/src/read-daemon-process.ts +50 -0
- package/src/read-fleet-snapshot.ts +37 -0
- package/src/read-restart-result.ts +17 -0
- package/src/read-stored-fleet-file.ts +74 -0
- package/src/read-stored-rows.ts +36 -0
- package/src/remove-restart-result.ts +11 -0
- package/src/restart-daemon.ts +149 -0
- package/src/restart-plan.ts +33 -0
- package/src/run-daemon-restart-worker.ts +77 -0
- package/src/run-daemon-restart.ts +228 -0
- package/src/run-systemctl.ts +33 -0
- package/src/shared/build-atc-command.ts +13 -0
- package/src/shared/config.ts +5 -0
- package/src/shared/find-pid-file-pid.ts +15 -0
- package/src/shared/get-build.ts +4 -3
- package/src/shared/is-process-alive.ts +21 -0
- package/src/shared/spawn-atc-detached.ts +34 -0
- package/src/start-replacement-daemon.ts +31 -0
- package/src/stop-daemon-process.ts +46 -0
- package/src/store/state-store.ts +2 -2
- package/src/test-utils/can-bind-addresses.ts +19 -0
- package/src/test-utils/create-migrated-state-db.ts +38 -0
- package/src/test-utils/env-originals.ts +6 -0
- package/src/test-utils/fixture-dir-provider.ts +131 -0
- package/src/test-utils/fixture-imp-port.ts +1692 -0
- package/src/test-utils/get-agent-entry.ts +17 -0
- package/src/test-utils/get-gateway-config.ts +18 -0
- package/src/test-utils/isolate-home.ts +60 -0
- package/src/test-utils/read-json-record.ts +20 -0
- package/src/test-utils/remove-env-overrides.ts +18 -0
- package/src/test-utils/run-legacy-daemon.ts +38 -0
- package/src/test-utils/run-listener-daemon.ts +51 -0
- package/src/test-utils/run-mcp-authorization.ts +118 -0
- package/src/test-utils/run-source-daemon.ts +110 -0
- package/src/test-utils/setup-fake-systemd.ts +125 -0
- package/src/test-utils/setup-mcp-http.ts +126 -0
- package/src/test-utils/setup-temp-dir.ts +33 -0
- package/src/test-utils/spawn-named-session.ts +27 -0
- package/src/test-utils/start-cut-proxy.ts +175 -0
- package/src/test-utils/start-git-http-server.ts +102 -0
- package/src/test-utils/start-legacy-daemon.ts +111 -0
- package/src/test-utils/subscribe-to-socket-lines.ts +60 -0
- package/src/test-utils/update-env.ts +19 -0
- package/src/test-utils/wait-for.ts +38 -0
- package/src/verify-restored-fleet.ts +191 -0
- package/src/wait-for-replacement.ts +112 -0
- package/src/write-restart-result.ts +17 -0
- /package/src/{daemon → shared}/claim-daemon-lock.ts +0 -0
- /package/src/{daemon → shared}/load-listener-tokens.ts +0 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { mkdir } from 'node:fs/promises';
|
|
2
|
+
import type {
|
|
3
|
+
CommandResult,
|
|
4
|
+
CommandSpec,
|
|
5
|
+
ExecutionCapabilities,
|
|
6
|
+
ExecutionCapability,
|
|
7
|
+
ExecutionProvider,
|
|
8
|
+
HarnessHandle,
|
|
9
|
+
HarnessSpec,
|
|
10
|
+
} from '../daemon/execution-provider';
|
|
11
|
+
import { LocalPTYProvider } from '../daemon/local-pty-provider';
|
|
12
|
+
|
|
13
|
+
// One provider operation, in the order the daemon called it.
|
|
14
|
+
type FixtureCall =
|
|
15
|
+
| { readonly op: 'transfer'; readonly dir: string; readonly bytes: number }
|
|
16
|
+
| { readonly op: 'run'; readonly argv: readonly string[]; readonly cwd: string };
|
|
17
|
+
|
|
18
|
+
interface FixtureDirOptions {
|
|
19
|
+
// Capabilities the provider declares as missing.
|
|
20
|
+
readonly lacking?: readonly ExecutionCapability[];
|
|
21
|
+
|
|
22
|
+
// Runs once an archive is unpacked, before the transfer resolves, so a
|
|
23
|
+
// test can change what landed on the host or hold the transfer open.
|
|
24
|
+
readonly afterTransfer?: (dir: string) => Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* An execution provider for tests whose host is a directory tree the test
|
|
29
|
+
* owns: a transfer unpacks the archive with tar into the directory it is
|
|
30
|
+
* given, and a command runs as a child process in its working directory.
|
|
31
|
+
* Paths pass through unchanged, so a test points them into its own temp
|
|
32
|
+
* tree. Every transfer and command is recorded in `calls`. Harnesses start
|
|
33
|
+
* on a local pseudo-terminal, and each one's spec is recorded in
|
|
34
|
+
* `harnesses`.
|
|
35
|
+
*/
|
|
36
|
+
export class FixtureDirProvider implements ExecutionProvider {
|
|
37
|
+
readonly kind = 'fixture-dir';
|
|
38
|
+
|
|
39
|
+
readonly remote = false;
|
|
40
|
+
|
|
41
|
+
readonly capabilities: ExecutionCapabilities;
|
|
42
|
+
|
|
43
|
+
readonly calls: FixtureCall[] = [];
|
|
44
|
+
|
|
45
|
+
// Every harness the provider started, as the daemon specified it.
|
|
46
|
+
readonly harnesses: HarnessSpec[] = [];
|
|
47
|
+
|
|
48
|
+
private readonly afterTransfer: ((dir: string) => Promise<void>) | undefined;
|
|
49
|
+
|
|
50
|
+
private readonly terminals = new LocalPTYProvider();
|
|
51
|
+
|
|
52
|
+
constructor(options: FixtureDirOptions = {}) {
|
|
53
|
+
const lacking = new Set(options.lacking);
|
|
54
|
+
|
|
55
|
+
this.capabilities = {
|
|
56
|
+
spawn: !lacking.has('spawn'),
|
|
57
|
+
attach: !lacking.has('attach'),
|
|
58
|
+
input: !lacking.has('input'),
|
|
59
|
+
resize: !lacking.has('resize'),
|
|
60
|
+
kill: !lacking.has('kill'),
|
|
61
|
+
transfer: !lacking.has('transfer'),
|
|
62
|
+
run: !lacking.has('run'),
|
|
63
|
+
headless: false,
|
|
64
|
+
suspend: false,
|
|
65
|
+
destroy: false,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
this.afterTransfer = options.afterTransfer;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
readonly prepareHost = (): Promise<void> => Promise.resolve();
|
|
72
|
+
|
|
73
|
+
readonly spawnHarness = (spec: HarnessSpec): HarnessHandle => {
|
|
74
|
+
this.harnesses.push(spec);
|
|
75
|
+
|
|
76
|
+
return this.terminals.spawnHarness(spec);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// oxlint-disable-next-line prefer-readonly-parameter-types -- archive bytes have no readonly form
|
|
80
|
+
readonly transferArchive = async (archive: Uint8Array, dir: string): Promise<void> => {
|
|
81
|
+
this.calls.push({ op: 'transfer', dir, bytes: archive.byteLength });
|
|
82
|
+
|
|
83
|
+
await mkdir(dir, { recursive: true });
|
|
84
|
+
|
|
85
|
+
const proc = Bun.spawn(['tar', '-x', '-f', '-', '-C', dir], {
|
|
86
|
+
stdin: archive,
|
|
87
|
+
stdout: 'ignore',
|
|
88
|
+
stderr: 'pipe',
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const [stderr, exitCode] = await Promise.all([new Response(proc.stderr).text(), proc.exited]);
|
|
92
|
+
|
|
93
|
+
if (exitCode !== 0) {
|
|
94
|
+
throw new Error(`tar exited ${exitCode} unpacking into ${dir}: ${stderr}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
await this.afterTransfer?.(dir);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
readonly runCommand = async (spec: CommandSpec): Promise<CommandResult> => {
|
|
101
|
+
this.calls.push({ op: 'run', argv: spec.argv, cwd: spec.cwd });
|
|
102
|
+
|
|
103
|
+
// The command inherits the daemon's environment as it stands now, which
|
|
104
|
+
// a spawn without an env option would take only from process start.
|
|
105
|
+
const proc = Bun.spawn([...spec.argv], {
|
|
106
|
+
cwd: spec.cwd,
|
|
107
|
+
env: process.env,
|
|
108
|
+
stdin: 'ignore',
|
|
109
|
+
stdout: 'pipe',
|
|
110
|
+
stderr: 'pipe',
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
114
|
+
new Response(proc.stdout).text(),
|
|
115
|
+
new Response(proc.stderr).text(),
|
|
116
|
+
proc.exited,
|
|
117
|
+
]);
|
|
118
|
+
|
|
119
|
+
return { exitCode, stdout, stderr };
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// The host is the test's own directory tree, which neither sleeps nor
|
|
123
|
+
// goes away.
|
|
124
|
+
readonly suspendHost = (host: string): Promise<void> =>
|
|
125
|
+
Promise.reject(new Error(`the fixture-dir provider cannot suspend host ${host}`));
|
|
126
|
+
|
|
127
|
+
readonly destroyHost = (host: string): Promise<void> =>
|
|
128
|
+
Promise.reject(new Error(`the fixture-dir provider cannot destroy host ${host}`));
|
|
129
|
+
|
|
130
|
+
readonly dispose = (): void => {};
|
|
131
|
+
}
|