braeburn 1.4.1 → 1.4.2
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/dist/runner.js +51 -1
- package/dist/steps/nvm.js +11 -3
- package/dist/ui/screen.js +15 -1
- package/dist/ui/versionReport.d.ts +1 -0
- package/dist/ui/versionReport.js +3 -0
- package/package.json +1 -1
package/dist/runner.js
CHANGED
|
@@ -1,4 +1,45 @@
|
|
|
1
1
|
import { execa } from "execa";
|
|
2
|
+
const FAILURE_OUTPUT_TAIL_LINE_LIMIT = 20;
|
|
3
|
+
function splitNonEmptyLines(text) {
|
|
4
|
+
if (!text) {
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
return text.split(/\r?\n|\r/).filter(Boolean);
|
|
8
|
+
}
|
|
9
|
+
function buildFailureSummaryLines(shellCommand, error) {
|
|
10
|
+
const defaultMessage = error instanceof Error ? error.message : String(error);
|
|
11
|
+
if (typeof error !== "object" || error === null) {
|
|
12
|
+
return [
|
|
13
|
+
`[braeburn] Command failed: ${shellCommand}`,
|
|
14
|
+
`[braeburn] Error: ${defaultMessage}`,
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
const errorDetails = error;
|
|
18
|
+
const summaryLines = [`[braeburn] Command failed: ${shellCommand}`];
|
|
19
|
+
if (typeof errorDetails.exitCode === "number") {
|
|
20
|
+
summaryLines.push(`[braeburn] Exit code: ${errorDetails.exitCode}`);
|
|
21
|
+
}
|
|
22
|
+
if (typeof errorDetails.signal === "string") {
|
|
23
|
+
summaryLines.push(`[braeburn] Signal: ${errorDetails.signal}`);
|
|
24
|
+
}
|
|
25
|
+
if (typeof errorDetails.shortMessage === "string" && errorDetails.shortMessage.length > 0) {
|
|
26
|
+
summaryLines.push(`[braeburn] ${errorDetails.shortMessage}`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
summaryLines.push(`[braeburn] Error: ${defaultMessage}`);
|
|
30
|
+
}
|
|
31
|
+
const stderrTailLines = splitNonEmptyLines(errorDetails.stderr).slice(-FAILURE_OUTPUT_TAIL_LINE_LIMIT);
|
|
32
|
+
if (stderrTailLines.length > 0) {
|
|
33
|
+
summaryLines.push(`[braeburn] stderr tail (${stderrTailLines.length}):`);
|
|
34
|
+
summaryLines.push(...stderrTailLines.map((line) => ` ${line}`));
|
|
35
|
+
}
|
|
36
|
+
const stdoutTailLines = splitNonEmptyLines(errorDetails.stdout).slice(-FAILURE_OUTPUT_TAIL_LINE_LIMIT);
|
|
37
|
+
if (stdoutTailLines.length > 0) {
|
|
38
|
+
summaryLines.push(`[braeburn] stdout tail (${stdoutTailLines.length}):`);
|
|
39
|
+
summaryLines.push(...stdoutTailLines.map((line) => ` ${line}`));
|
|
40
|
+
}
|
|
41
|
+
return summaryLines;
|
|
42
|
+
}
|
|
2
43
|
export async function runShellCommand(options) {
|
|
3
44
|
const subprocess = execa("bash", ["-c", options.shellCommand], {
|
|
4
45
|
all: true,
|
|
@@ -18,7 +59,16 @@ export async function runShellCommand(options) {
|
|
|
18
59
|
options.logWriter(line);
|
|
19
60
|
}
|
|
20
61
|
});
|
|
21
|
-
|
|
62
|
+
try {
|
|
63
|
+
await subprocess;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const failureSummaryLines = buildFailureSummaryLines(options.shellCommand, error);
|
|
67
|
+
for (const line of failureSummaryLines) {
|
|
68
|
+
await options.logWriter(line);
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
22
72
|
}
|
|
23
73
|
export async function doesShellCommandSucceed(options) {
|
|
24
74
|
const result = await execa("bash", ["-c", options.shellCommand], {
|
package/dist/steps/nvm.js
CHANGED
|
@@ -2,19 +2,27 @@ import { homedir } from "node:os";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { checkPathExists } from "./runtime.js";
|
|
4
4
|
const NVM_DIRECTORY = join(homedir(), ".nvm");
|
|
5
|
+
const NVM_SCRIPT_PATH = join(NVM_DIRECTORY, "nvm.sh");
|
|
5
6
|
// nvm is a shell function sourced from nvm.sh — it cannot be invoked as a
|
|
6
7
|
// standalone binary, so we source it explicitly inside each bash invocation.
|
|
7
|
-
const NVM_SOURCE_PREFIX = `export NVM_DIR="${NVM_DIRECTORY}" && source "$NVM_DIR/nvm.sh"`;
|
|
8
|
+
const NVM_SOURCE_PREFIX = `export NVM_DIR="${NVM_DIRECTORY}" && source "$NVM_DIR/nvm.sh" --no-use`;
|
|
9
|
+
const NVM_INSTALL_COMMAND = `${NVM_SOURCE_PREFIX} && ` +
|
|
10
|
+
`CURRENT_NODE_VERSION="$(nvm current)" && ` +
|
|
11
|
+
`if [ "$CURRENT_NODE_VERSION" = "none" ] || [ "$CURRENT_NODE_VERSION" = "system" ]; then ` +
|
|
12
|
+
`nvm install node; ` +
|
|
13
|
+
`else ` +
|
|
14
|
+
`nvm install node --reinstall-packages-from="$CURRENT_NODE_VERSION"; ` +
|
|
15
|
+
`fi`;
|
|
8
16
|
const nvmStep = {
|
|
9
17
|
id: "nvm",
|
|
10
18
|
name: "Node.js (nvm)",
|
|
11
19
|
stage: "runtime",
|
|
12
20
|
description: "Install the latest Node.js via nvm, migrating packages from the current version",
|
|
13
21
|
async checkIsAvailable() {
|
|
14
|
-
return checkPathExists(
|
|
22
|
+
return checkPathExists(NVM_SCRIPT_PATH);
|
|
15
23
|
},
|
|
16
24
|
async run(context) {
|
|
17
|
-
await context.runStep(
|
|
25
|
+
await context.runStep(NVM_INSTALL_COMMAND);
|
|
18
26
|
},
|
|
19
27
|
};
|
|
20
28
|
export default nvmStep;
|
package/dist/ui/screen.js
CHANGED
|
@@ -2,7 +2,7 @@ import { buildHeaderLines } from "./header.js";
|
|
|
2
2
|
import { buildActiveStepLines } from "./currentStep.js";
|
|
3
3
|
import { buildOutputBoxLines } from "./outputBox.js";
|
|
4
4
|
import { buildPromptLines } from "./prompt.js";
|
|
5
|
-
import { buildVersionReportLines } from "./versionReport.js";
|
|
5
|
+
import { buildFailedStepLogHintLines, buildVersionReportLines } from "./versionReport.js";
|
|
6
6
|
export function createScreenRenderer(output = process.stdout) {
|
|
7
7
|
return (content) => {
|
|
8
8
|
output.write("\x1b[H\x1b[2J");
|
|
@@ -11,6 +11,16 @@ export function createScreenRenderer(output = process.stdout) {
|
|
|
11
11
|
}
|
|
12
12
|
export function buildScreen(state, terminalDimensions) {
|
|
13
13
|
const lines = [];
|
|
14
|
+
const failedStepIds = state.completedStepRecords.flatMap((record, stepIndex) => {
|
|
15
|
+
if (record.phase !== "failed") {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
const failedStep = state.steps[stepIndex];
|
|
19
|
+
if (!failedStep) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
return [failedStep.id];
|
|
23
|
+
});
|
|
14
24
|
lines.push(...buildHeaderLines({
|
|
15
25
|
steps: state.steps,
|
|
16
26
|
version: state.version,
|
|
@@ -26,6 +36,10 @@ export function buildScreen(state, terminalDimensions) {
|
|
|
26
36
|
lines.push("");
|
|
27
37
|
lines.push(...buildVersionReportLines(state.versionReport));
|
|
28
38
|
}
|
|
39
|
+
if (failedStepIds.length > 0) {
|
|
40
|
+
lines.push("");
|
|
41
|
+
lines.push(...buildFailedStepLogHintLines(failedStepIds));
|
|
42
|
+
}
|
|
29
43
|
}
|
|
30
44
|
else {
|
|
31
45
|
const currentStep = state.steps[state.currentStepIndex];
|
package/dist/ui/versionReport.js
CHANGED
|
@@ -7,3 +7,6 @@ export function buildVersionReportLines(versions) {
|
|
|
7
7
|
` ${chalk.green.bold("✓")} ${chalk.bold("All done!")}`,
|
|
8
8
|
];
|
|
9
9
|
}
|
|
10
|
+
export function buildFailedStepLogHintLines(failedStepIds) {
|
|
11
|
+
return failedStepIds.map((stepId) => ` ${chalk.red.bold("✗")} ${chalk.bold(`Step ${stepId} failed.`)} ${chalk.dim(`Please run braeburn log --${stepId} to see what happened.`)}`);
|
|
12
|
+
}
|