redkite 0.1.11 → 0.1.12
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 +69 -1
- package/dist/build.d.ts +3 -2
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +14 -7
- package/dist/build.js.map +1 -1
- package/dist/cli/crash.d.ts +46 -0
- package/dist/cli/crash.d.ts.map +1 -0
- package/dist/cli/crash.js +202 -0
- package/dist/cli/crash.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +33 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/log.d.ts +1 -0
- package/dist/cli/log.d.ts.map +1 -1
- package/dist/cli/log.js +1 -1
- package/dist/cli/log.js.map +1 -1
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +68 -5
- package/dist/deploy.js.map +1 -1
- package/dist/docker.d.ts +1 -0
- package/dist/docker.d.ts.map +1 -1
- package/dist/docker.js +5 -0
- package/dist/docker.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/build.ts +23 -11
- package/src/cli/crash.ts +286 -0
- package/src/cli/index.ts +38 -8
- package/src/cli/log.ts +1 -1
- package/src/deploy.ts +84 -5
- package/src/docker.ts +6 -0
- package/src/types.ts +9 -0
package/README.md
CHANGED
|
@@ -357,6 +357,21 @@ failure says which kind was missing: *"acme/backend has no tag v9"*.
|
|
|
357
357
|
An environment can only say `branch`. A tag or a commit is a claim about one
|
|
358
358
|
repository, and an environment spans every app in the deployment.
|
|
359
359
|
|
|
360
|
+
Each app is cloned as a step of its own, ahead of its build. It says the
|
|
361
|
+
repository and the branch, tag or commit as it starts, and says them again with
|
|
362
|
+
the commit it landed on when it ends, so the row keeps them after the step's
|
|
363
|
+
progress has moved on:
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
✔ Cloning backend: git@github.com:acme/backend.git, branch staging at 64ae9f1 (2s)
|
|
367
|
+
✔ Building backend: 64ae9f1 (1m12s)
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
A repository that cannot be reached, or a branch it does not have, fails that
|
|
371
|
+
step rather than the build, and gets a file of its own in the crash log. An app
|
|
372
|
+
built from a directory is read where it is rather than cloned, so it has no
|
|
373
|
+
such step.
|
|
374
|
+
|
|
360
375
|
### Building from a directory
|
|
361
376
|
|
|
362
377
|
An app names either a repository to clone or a directory already on this
|
|
@@ -1172,6 +1187,58 @@ the CPU and disk it is using. Nothing will clean up after it but you.
|
|
|
1172
1187
|
|
|
1173
1188
|
The sixth press leaves.
|
|
1174
1189
|
|
|
1190
|
+
### When a run fails
|
|
1191
|
+
|
|
1192
|
+
A run that throws, or a deploy that reverts, leaves everything it said on disk:
|
|
1193
|
+
|
|
1194
|
+
```
|
|
1195
|
+
/tmp/<project>/<environment>/crash-2026-09-14T10-22-05.123Z/
|
|
1196
|
+
run.log
|
|
1197
|
+
01-reading-the-bitwarden-vault.log
|
|
1198
|
+
02-setup.log
|
|
1199
|
+
03-building-frontend.log
|
|
1200
|
+
04-building-backend.log
|
|
1201
|
+
05-swap-before-migrate-backend.log
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
`run.log` holds what happened around the steps: the command, the version, the
|
|
1205
|
+
whole error chain with every stack in it, an index of the step files with how
|
|
1206
|
+
each ended, and every message and host command in the order they came. Host
|
|
1207
|
+
commands are kept whether or not `--verbose` showed them, since they are what a
|
|
1208
|
+
crash log is read for.
|
|
1209
|
+
|
|
1210
|
+
Each step is a file of its own, numbered in the order the steps started, with
|
|
1211
|
+
what it was doing as it went and every line its commands printed. Every app
|
|
1212
|
+
builds as its own step, so one app's output is never read through another's.
|
|
1213
|
+
The view keeps only each step's tail and the terminal gets only the end of the
|
|
1214
|
+
error; these keep all of it. Every line is stamped from the start of the run,
|
|
1215
|
+
the same clock in every file.
|
|
1216
|
+
|
|
1217
|
+
A health check that fails adds a step for each app, `Logs of <app>`, holding the
|
|
1218
|
+
last 200 lines its new container printed, both streams, with docker's own
|
|
1219
|
+
timestamps. They are read before the revert, because the revert gives the live
|
|
1220
|
+
name back to the previous release and anything asked after it would be that
|
|
1221
|
+
release's output. Every new container is read rather than only the one that
|
|
1222
|
+
failed, since a backend that never came up is often explained by what another
|
|
1223
|
+
app says it could not reach. The one that failed its check is marked failed,
|
|
1224
|
+
which puts its last lines on the screen when the run ends, and each has a file
|
|
1225
|
+
of its own here.
|
|
1226
|
+
|
|
1227
|
+
The path is `/tmp` itself rather than `TMPDIR`, so it is where a person is told
|
|
1228
|
+
to look. The directories are `700` and the files `600`, because `/tmp` is shared
|
|
1229
|
+
and a build's output can say more than it meant to. A run somebody stopped is
|
|
1230
|
+
not a crash and writes nothing.
|
|
1231
|
+
|
|
1232
|
+
A deployment that wants none of it says so:
|
|
1233
|
+
|
|
1234
|
+
```ts
|
|
1235
|
+
export default defineDeployment({
|
|
1236
|
+
project: "acme",
|
|
1237
|
+
options: { crashLog: false },
|
|
1238
|
+
// ...
|
|
1239
|
+
});
|
|
1240
|
+
```
|
|
1241
|
+
|
|
1175
1242
|
## GitHub Actions
|
|
1176
1243
|
|
|
1177
1244
|
There is a composite action in this repository. `verify` on a pull request,
|
|
@@ -1271,7 +1338,8 @@ with the agent forwarded.
|
|
|
1271
1338
|
6. **Swap.** The running container moves to the retired address without being
|
|
1272
1339
|
stopped and is renamed, and only then does the live address belong to the new
|
|
1273
1340
|
one. Nginx keeps the retired container as a backup upstream.
|
|
1274
|
-
7. **Check.** Each app is probed on itself. One failure reverts all of them
|
|
1341
|
+
7. **Check.** Each app is probed on itself. One failure reverts all of them,
|
|
1342
|
+
after writing out the last 200 lines every new container printed.
|
|
1275
1343
|
8. **Cleanup.** Retired containers removed, superseded images reclaimed.
|
|
1276
1344
|
|
|
1277
1345
|
A `verify` run walks the same list without steps 5 to 7. In their place it runs
|
package/dist/build.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Docker } from "./docker.js";
|
|
2
|
-
import type { Ref } from "./source.js";
|
|
2
|
+
import type { Ref, Source } from "./source.js";
|
|
3
3
|
import type { Host } from "./host.js";
|
|
4
4
|
import type { AppTopology } from "./topology.js";
|
|
5
5
|
import type { AppSpec } from "./types.js";
|
|
@@ -26,5 +26,6 @@ export type BuildResult = {
|
|
|
26
26
|
cached: boolean;
|
|
27
27
|
};
|
|
28
28
|
export declare function refOf(app: AppSpec, branch: string): Ref;
|
|
29
|
-
export declare function
|
|
29
|
+
export declare function sourceOf(app: AppSpec, topology: AppTopology, context: Pick<BuildContext, "host" | "branch" | "detail" | "output">): Promise<Source>;
|
|
30
|
+
export declare function build(app: AppSpec, topology: AppTopology, context: BuildContext, checkedOut?: Source): Promise<BuildResult>;
|
|
30
31
|
//# sourceMappingURL=build.d.ts.map
|
package/dist/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAM1C,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IAGf,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAEzC,GAAG,EAAE,MAAM,CAAC;IAEZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IAGpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,CAAC;AAOF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAEhB,WAAW,EAAE,MAAM,CAAC;IAEpB,GAAG,EAAE,MAAM,CAAC;IAIZ,UAAU,EAAE,MAAM,CAAC;IAEnB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAKF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,CAKvD;AAID,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC,GACnE,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAsB,KAAK,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,YAAY,EAErB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,CAAC,CA+EtB"}
|
package/dist/build.js
CHANGED
|
@@ -16,11 +16,10 @@ export function refOf(app, branch) {
|
|
|
16
16
|
return { kind: "commit", name: app.commit };
|
|
17
17
|
return { kind: "branch", name: app.branch ?? branch };
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const source = await prepareSource(host, {
|
|
19
|
+
// Where the app's source comes from, cloned or read. Its own call, so a run can
|
|
20
|
+
// make the clone a step of its own ahead of the build that reads it
|
|
21
|
+
export async function sourceOf(app, topology, context) {
|
|
22
|
+
return await prepareSource(context.host, {
|
|
24
23
|
name: topology.container,
|
|
25
24
|
repo: app.repo,
|
|
26
25
|
// Already absolute when the CLI loaded the config, because a path is read
|
|
@@ -29,9 +28,17 @@ export async function build(app, topology, context) {
|
|
|
29
28
|
include: app.include,
|
|
30
29
|
ref: refOf(app, context.branch),
|
|
31
30
|
output: context.output,
|
|
32
|
-
submodules:
|
|
33
|
-
detail,
|
|
31
|
+
submodules: app.build.submodules,
|
|
32
|
+
detail: context.detail,
|
|
34
33
|
});
|
|
34
|
+
}
|
|
35
|
+
export async function build(app, topology, context,
|
|
36
|
+
// Already checked out by a step of its own. Absent, the build fetches it
|
|
37
|
+
checkedOut) {
|
|
38
|
+
const { host, docker } = context;
|
|
39
|
+
const spec = app.build;
|
|
40
|
+
const detail = context.detail ?? (() => { });
|
|
41
|
+
const source = checkedOut ?? (await sourceOf(app, topology, { ...context, detail }));
|
|
35
42
|
const release = source.release;
|
|
36
43
|
const fingerprint = fingerprintOf(app, context, release);
|
|
37
44
|
const tag = `${topology.container}:${release}-${fingerprint}`;
|
package/dist/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGtF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA4B5C,8EAA8E;AAC9E,+EAA+E;AAC/E,6DAA6D;AAC7D,MAAM,QAAQ,GAAG,GAAG,CAAC;AAgBrB,6EAA6E;AAC7E,8EAA8E;AAC9E,0DAA0D;AAC1D,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,MAAc;IAChD,IAAI,GAAG,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;IACnD,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;IAE5D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Deployment } from "../types.js";
|
|
2
|
+
import type { Viewer } from "./viewer.js";
|
|
3
|
+
type Kind = "info" | "warn" | "fail" | "done" | "plan" | "step" | "command";
|
|
4
|
+
type Entry = {
|
|
5
|
+
at: number;
|
|
6
|
+
kind: Kind;
|
|
7
|
+
text: string;
|
|
8
|
+
};
|
|
9
|
+
type Said = {
|
|
10
|
+
at: number;
|
|
11
|
+
kind: "detail" | "line";
|
|
12
|
+
text: string;
|
|
13
|
+
};
|
|
14
|
+
type StepRecord = {
|
|
15
|
+
label: string;
|
|
16
|
+
started: number;
|
|
17
|
+
ended?: number;
|
|
18
|
+
state: "running" | "done" | "failed";
|
|
19
|
+
note?: string;
|
|
20
|
+
said: Said[];
|
|
21
|
+
};
|
|
22
|
+
export type Transcript = {
|
|
23
|
+
started: number;
|
|
24
|
+
entries: Entry[];
|
|
25
|
+
steps: StepRecord[];
|
|
26
|
+
};
|
|
27
|
+
export type Crash = {
|
|
28
|
+
project: string;
|
|
29
|
+
environment: string;
|
|
30
|
+
command: string;
|
|
31
|
+
version: string;
|
|
32
|
+
argv: string[];
|
|
33
|
+
outcome: string;
|
|
34
|
+
at: number;
|
|
35
|
+
error?: unknown;
|
|
36
|
+
};
|
|
37
|
+
export declare function recording(log: Viewer, now?: () => number): {
|
|
38
|
+
log: Viewer;
|
|
39
|
+
transcript: Transcript;
|
|
40
|
+
command: (text: string) => number;
|
|
41
|
+
};
|
|
42
|
+
export declare function crashDirectory(project: string, environment: string, at: Date, root?: string): string;
|
|
43
|
+
export declare function crashFiles(transcript: Transcript, crash: Crash): Record<string, string>;
|
|
44
|
+
export declare function dumpCrash(config: Deployment, transcript: Transcript, crash: Crash, root?: string): Promise<string | undefined>;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=crash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crash.d.ts","sourceRoot":"","sources":["../../src/cli/crash.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAU1C,KAAK,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5E,KAAK,KAAK,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,KAAK,IAAI,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,IAAI,EAAE,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,KAAK,EAAE,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAIF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,MAAiB;;;oBAqE1C,MAAM;EAG9B;AAID,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,SAAO,UAGzF;AAMD,wBAAgB,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAcvF;AAKD,wBAAsB,SAAS,CAC7B,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,KAAK,EACZ,IAAI,SAAO,+BAgBZ"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { elapsed } from "./screen.js";
|
|
4
|
+
import { causes } from "./log.js";
|
|
5
|
+
// What a failed run said, kept whole. The view trims a step to its last lines
|
|
6
|
+
// and the alternate screen takes the rest with it, so the only complete record
|
|
7
|
+
// of a run that went wrong is one written down while it happened.
|
|
8
|
+
// Named rather than read from TMPDIR: the path is the one a person is told to
|
|
9
|
+
// look in, and a runner that points TMPDIR somewhere else would hide it
|
|
10
|
+
const ROOT = "/tmp";
|
|
11
|
+
// Every call reaches the wrapped log unchanged, so the view behaves as it did.
|
|
12
|
+
// The transcript is a copy kept beside it, never a replacement for it
|
|
13
|
+
export function recording(log, now = Date.now) {
|
|
14
|
+
const transcript = { started: now(), entries: [], steps: [] };
|
|
15
|
+
const note = (kind, text) => transcript.entries.push({ at: now(), kind, text });
|
|
16
|
+
const step = (label) => {
|
|
17
|
+
const record = { label, started: now(), state: "running", said: [] };
|
|
18
|
+
const task = log.step(label);
|
|
19
|
+
transcript.steps.push(record);
|
|
20
|
+
note("step", `${label} started`);
|
|
21
|
+
const settle = (state, message) => {
|
|
22
|
+
record.state = state;
|
|
23
|
+
record.ended = now();
|
|
24
|
+
record.note = message;
|
|
25
|
+
const said = message ? `: ${message}` : "";
|
|
26
|
+
note("step", `${label} ${state}${said} (${elapsed(record.ended, record.started)})`);
|
|
27
|
+
};
|
|
28
|
+
return {
|
|
29
|
+
detail: (message) => {
|
|
30
|
+
record.said.push({ at: now(), kind: "detail", text: message });
|
|
31
|
+
task.detail(message);
|
|
32
|
+
},
|
|
33
|
+
line: (message) => {
|
|
34
|
+
record.said.push({ at: now(), kind: "line", text: message });
|
|
35
|
+
task.line(message);
|
|
36
|
+
},
|
|
37
|
+
done: (message) => {
|
|
38
|
+
settle("done", message);
|
|
39
|
+
task.done(message);
|
|
40
|
+
},
|
|
41
|
+
fail: (message) => {
|
|
42
|
+
settle("failed", message);
|
|
43
|
+
task.fail(message);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
const recorded = Object.assign((message) => {
|
|
48
|
+
note("info", message);
|
|
49
|
+
log(message);
|
|
50
|
+
}, {
|
|
51
|
+
plan: (points) => {
|
|
52
|
+
note("plan", points.join(", "));
|
|
53
|
+
log.plan?.(points);
|
|
54
|
+
},
|
|
55
|
+
warn: (message) => {
|
|
56
|
+
note("warn", message);
|
|
57
|
+
log.warn(message);
|
|
58
|
+
},
|
|
59
|
+
fail: (message) => {
|
|
60
|
+
note("fail", message);
|
|
61
|
+
log.fail(message);
|
|
62
|
+
},
|
|
63
|
+
done: (message) => {
|
|
64
|
+
note("done", message);
|
|
65
|
+
log.done(message);
|
|
66
|
+
},
|
|
67
|
+
step,
|
|
68
|
+
close: () => log.close(),
|
|
69
|
+
});
|
|
70
|
+
// A host command is only shown with --verbose, and is exactly what a crash log
|
|
71
|
+
// is read for, so it is kept whether it was shown or not
|
|
72
|
+
const command = (text) => note("command", text);
|
|
73
|
+
return { log: recorded, transcript, command };
|
|
74
|
+
}
|
|
75
|
+
// One directory per failed run, under the environment it failed in. Named from
|
|
76
|
+
// the command line, so both segments are made safe to be a path first
|
|
77
|
+
export function crashDirectory(project, environment, at, root = ROOT) {
|
|
78
|
+
const moment = at.toISOString().replaceAll(":", "-");
|
|
79
|
+
return join(root, slug(project), slug(environment), `crash-${moment}`);
|
|
80
|
+
}
|
|
81
|
+
// The run's own log, and one file per step. A build's thousands of lines would
|
|
82
|
+
// bury everything else in a single file, and a step's file is what gets opened
|
|
83
|
+
// first. Numbered in the order they started, which also keeps two steps that
|
|
84
|
+
// share a label from sharing a file
|
|
85
|
+
export function crashFiles(transcript, crash) {
|
|
86
|
+
const width = Math.max(2, String(transcript.steps.length).length);
|
|
87
|
+
const named = transcript.steps.map((step, index) => ({
|
|
88
|
+
step,
|
|
89
|
+
file: `${pad(index + 1, width)}-${slug(step.label)}.log`,
|
|
90
|
+
}));
|
|
91
|
+
return {
|
|
92
|
+
"run.log": runLog(transcript, crash, named),
|
|
93
|
+
...Object.fromEntries(named.map(({ step, file }) => [file, stepLog(transcript, crash, step)])),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// Nothing is written for a deployment that turned it off. Otherwise private to
|
|
97
|
+
// whoever ran it: /tmp is shared by everyone on the machine, and a build's output
|
|
98
|
+
// can say more than it meant to
|
|
99
|
+
export async function dumpCrash(config, transcript, crash, root = ROOT) {
|
|
100
|
+
if (config.options?.crashLog === false)
|
|
101
|
+
return undefined;
|
|
102
|
+
const directory = crashDirectory(config.project, crash.environment, new Date(crash.at), root);
|
|
103
|
+
await mkdir(dirname(directory), { recursive: true, mode: 0o700 });
|
|
104
|
+
// Not recursive: a directory already there belongs to another run, and nothing
|
|
105
|
+
// of this one is written into it
|
|
106
|
+
await mkdir(directory, { mode: 0o700 });
|
|
107
|
+
for (const [name, contents] of Object.entries(crashFiles(transcript, crash))) {
|
|
108
|
+
await writeFile(join(directory, name), contents, { mode: 0o600, flag: "wx" });
|
|
109
|
+
}
|
|
110
|
+
return directory;
|
|
111
|
+
}
|
|
112
|
+
const MARK = {
|
|
113
|
+
info: "",
|
|
114
|
+
warn: "warn ",
|
|
115
|
+
fail: "fail ",
|
|
116
|
+
done: "done ",
|
|
117
|
+
plan: "plan ",
|
|
118
|
+
step: "step ",
|
|
119
|
+
command: "",
|
|
120
|
+
};
|
|
121
|
+
function runLog(transcript, crash, named) {
|
|
122
|
+
const since = sinceStart(transcript);
|
|
123
|
+
const index = named.map(({ step, file }) => {
|
|
124
|
+
const took = elapsed(step.ended ?? crash.at, step.started);
|
|
125
|
+
return `${file.padEnd(40)} ${step.state.padEnd(8)} ${took}`;
|
|
126
|
+
});
|
|
127
|
+
return lines([
|
|
128
|
+
"redkite crash log",
|
|
129
|
+
"",
|
|
130
|
+
`project ${crash.project}`,
|
|
131
|
+
`environment ${crash.environment}`,
|
|
132
|
+
`command ${crash.command}`,
|
|
133
|
+
`outcome ${crash.outcome}`,
|
|
134
|
+
`version ${crash.version}`,
|
|
135
|
+
`argv ${crash.argv.join(" ")}`,
|
|
136
|
+
`started ${new Date(transcript.started).toISOString()}`,
|
|
137
|
+
`ended ${new Date(crash.at).toISOString()}`,
|
|
138
|
+
"",
|
|
139
|
+
"== error",
|
|
140
|
+
...errorLines(crash.error),
|
|
141
|
+
"",
|
|
142
|
+
"== steps, each in its own file beside this one",
|
|
143
|
+
...(index.length > 0 ? index : ["none started"]),
|
|
144
|
+
"",
|
|
145
|
+
"== log",
|
|
146
|
+
...transcript.entries.map((entry) => `${since(entry.at)} ${MARK[entry.kind]}${indent(entry.text)}`),
|
|
147
|
+
]);
|
|
148
|
+
}
|
|
149
|
+
// Stamped from the start of the run, the same as run.log, so a line here can be
|
|
150
|
+
// found among what the run said around it
|
|
151
|
+
function stepLog(transcript, crash, step) {
|
|
152
|
+
const since = sinceStart(transcript);
|
|
153
|
+
const note = step.note ? `: ${step.note}` : "";
|
|
154
|
+
return lines([
|
|
155
|
+
`step ${step.label}`,
|
|
156
|
+
`state ${step.state}${indent(note)}`,
|
|
157
|
+
`started ${new Date(step.started).toISOString()}`,
|
|
158
|
+
`ended ${step.ended ? new Date(step.ended).toISOString() : "still running when the run ended"}`,
|
|
159
|
+
`took ${elapsed(step.ended ?? crash.at, step.started)}`,
|
|
160
|
+
"",
|
|
161
|
+
...step.said.map((said) => `${since(said.at)} ${said.kind === "detail" ? "· " : "| "}${indent(said.text)}`),
|
|
162
|
+
]);
|
|
163
|
+
}
|
|
164
|
+
// Whole, where the terminal gets the tail: the stack of every error in the
|
|
165
|
+
// chain, since the step that threw is usually two causes down
|
|
166
|
+
function errorLines(error) {
|
|
167
|
+
if (error === undefined)
|
|
168
|
+
return ["none thrown"];
|
|
169
|
+
if (!(error instanceof Error))
|
|
170
|
+
return [String(error)];
|
|
171
|
+
return causes(error).flatMap((link, index) => [
|
|
172
|
+
...(index > 0 ? ["", "caused by"] : []),
|
|
173
|
+
link.stack ?? link.message,
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
176
|
+
function sinceStart(transcript) {
|
|
177
|
+
return (at) => `+${clock(at - transcript.started)}`;
|
|
178
|
+
}
|
|
179
|
+
function lines(rows) {
|
|
180
|
+
return `${rows.join("\n")}\n`;
|
|
181
|
+
}
|
|
182
|
+
// Continuation lines line up under the text rather than under the timestamp
|
|
183
|
+
function indent(text) {
|
|
184
|
+
return text.replaceAll("\n", "\n ");
|
|
185
|
+
}
|
|
186
|
+
function slug(text) {
|
|
187
|
+
const slugged = text
|
|
188
|
+
.toLowerCase()
|
|
189
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
190
|
+
.replace(/^-+|-+$/g, "");
|
|
191
|
+
return slugged || "unnamed";
|
|
192
|
+
}
|
|
193
|
+
function clock(ms) {
|
|
194
|
+
const minutes = Math.floor(ms / 60_000);
|
|
195
|
+
const seconds = Math.floor(ms / 1000) % 60;
|
|
196
|
+
const millis = ms % 1000;
|
|
197
|
+
return `${pad(minutes, 2)}:${pad(seconds, 2)}.${pad(millis, 3)}`;
|
|
198
|
+
}
|
|
199
|
+
function pad(value, width) {
|
|
200
|
+
return String(value).padStart(width, "0");
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=crash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crash.js","sourceRoot":"","sources":["../../src/cli/crash.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAgG1D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,YAgBxC;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,2BASxC;AA4QD,wBAAgB,OAAO,CAAC,EAAE,EAAE;IAC1B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACxC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,cAwBA;AAkCD,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CAehF"}
|
package/dist/cli/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { topologyFor } from "../topology.js";
|
|
|
14
14
|
import { needsAgent, requireAgent } from "./agent.js";
|
|
15
15
|
import { loadConfig, projectRoot } from "./config.js";
|
|
16
16
|
import { loadDotenv } from "./dotenv.js";
|
|
17
|
+
import { dumpCrash, recording } from "./crash.js";
|
|
17
18
|
import { createLog, describeFailure } from "./log.js";
|
|
18
19
|
// One command that reads the config and does everything under it: the agent,
|
|
19
20
|
// the vault, the checkout, the build, the swap and the cleanup.
|
|
@@ -36,7 +37,7 @@ of the project, and everything below it is derived.
|
|
|
36
37
|
`;
|
|
37
38
|
// Wraps a host rather than living inside one, so both implementations are
|
|
38
39
|
// measured the same way and neither knows it is being timed
|
|
39
|
-
function measured(host,
|
|
40
|
+
function measured(host, say) {
|
|
40
41
|
const totals = { commands: 0, commandMs: 0, files: 0 };
|
|
41
42
|
const wrapped = {
|
|
42
43
|
directory: host.directory,
|
|
@@ -51,7 +52,7 @@ function measured(host, log) {
|
|
|
51
52
|
totals.commandMs += Date.now() - started;
|
|
52
53
|
// The exit code matters: several of these are allowed to fail, and a
|
|
53
54
|
// deploy reading verbose output is one where somebody wants to know which
|
|
54
|
-
|
|
55
|
+
say?.(` $ ${command} ${Date.now() - started}ms exit ${result.code}`);
|
|
55
56
|
return result;
|
|
56
57
|
},
|
|
57
58
|
write: async (name, contents) => {
|
|
@@ -438,10 +439,34 @@ async function run(kind, environment, configPath, options) {
|
|
|
438
439
|
// Whatever is in flight is killed, the pipeline unwinds through its own
|
|
439
440
|
// failure path, and the finally below removes the scratch directory
|
|
440
441
|
const stopping = new AbortController();
|
|
441
|
-
|
|
442
|
+
// Everything the run says still reaches the view. The recording is what a
|
|
443
|
+
// crash log is written from, since the view keeps only each step's tail
|
|
444
|
+
const recorder = recording(createLog({
|
|
442
445
|
...options,
|
|
443
446
|
onQuit: () => stop(),
|
|
444
|
-
});
|
|
447
|
+
}));
|
|
448
|
+
const log = recorder.log;
|
|
449
|
+
// Before the view closes, so where the log went is among what it writes out.
|
|
450
|
+
// A log that cannot be written must not replace the failure it was recording
|
|
451
|
+
const dumped = async (outcome, error) => {
|
|
452
|
+
try {
|
|
453
|
+
const path = await dumpCrash(config, recorder.transcript, {
|
|
454
|
+
project: config.project,
|
|
455
|
+
environment,
|
|
456
|
+
command: kind,
|
|
457
|
+
version: await version(),
|
|
458
|
+
argv: process.argv.slice(2),
|
|
459
|
+
outcome,
|
|
460
|
+
at: Date.now(),
|
|
461
|
+
error,
|
|
462
|
+
});
|
|
463
|
+
if (path)
|
|
464
|
+
log.warn(`Crash logs written to ${path}`);
|
|
465
|
+
}
|
|
466
|
+
catch (failure) {
|
|
467
|
+
log.warn(`Could not write the crash log: ${describeFailure(failure).split("\n")[0]}`);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
445
470
|
// Read by the wait below, so a press during it hardens what that is sending
|
|
446
471
|
let hardest = "TERM";
|
|
447
472
|
const stop = stopper({
|
|
@@ -464,7 +489,7 @@ async function run(kind, environment, configPath, options) {
|
|
|
464
489
|
process.on("SIGINT", stop);
|
|
465
490
|
let host;
|
|
466
491
|
try {
|
|
467
|
-
const meter = measured(await hostFor(deployHost, log, stopping.signal), options.verbose ? log :
|
|
492
|
+
const meter = measured(await hostFor(deployHost, log, stopping.signal), options.verbose ? log : recorder.command);
|
|
468
493
|
host = meter.host;
|
|
469
494
|
const start = kind === "verify" ? verify : deploy;
|
|
470
495
|
const result = await start({
|
|
@@ -487,10 +512,11 @@ async function run(kind, environment, configPath, options) {
|
|
|
487
512
|
}
|
|
488
513
|
log.fail(`Reverted ${result.reverted.join(", ")}`);
|
|
489
514
|
process.exitCode = 1;
|
|
515
|
+
await dumped("reverted");
|
|
490
516
|
}
|
|
491
517
|
catch (error) {
|
|
492
518
|
// Whatever the command in flight said about being killed is noise: what
|
|
493
|
-
// happened is that somebody asked for it to stop
|
|
519
|
+
// happened is that somebody asked for it to stop, which is not a crash
|
|
494
520
|
if (stopping.signal.aborted) {
|
|
495
521
|
log.fail("Stopped");
|
|
496
522
|
process.exitCode = 130;
|
|
@@ -498,6 +524,7 @@ async function run(kind, environment, configPath, options) {
|
|
|
498
524
|
else {
|
|
499
525
|
log.fail(describeFailure(error));
|
|
500
526
|
process.exitCode = 1;
|
|
527
|
+
await dumped("failed", error);
|
|
501
528
|
}
|
|
502
529
|
}
|
|
503
530
|
finally {
|