c8ctl-plugin-nano 1.35.5 → 1.35.6
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/c8ctl-plugin.js +65 -8
- package/package.json +8 -8
package/c8ctl-plugin.js
CHANGED
|
@@ -2799,6 +2799,52 @@ function runGit(args, { cwd, env, timeoutMs = 120_000 } = {}) {
|
|
|
2799
2799
|
}
|
|
2800
2800
|
}
|
|
2801
2801
|
|
|
2802
|
+
// Bound a git output string without decapitating it: a hard `.slice(0, max)`
|
|
2803
|
+
// drops the tail, but the real reason can live at either end of a long
|
|
2804
|
+
// multiline git error (the `fatal:` up top, wrapping/hint detail below). Keep a
|
|
2805
|
+
// head+tail window joined by an elision marker so both survive.
|
|
2806
|
+
function boundGitOutput(text, max = 500) {
|
|
2807
|
+
const s = String(text ?? '').trim();
|
|
2808
|
+
if (s.length <= max) return s;
|
|
2809
|
+
const marker = ' […] ';
|
|
2810
|
+
// When max is too small to fit even the elision marker the head+tail budget
|
|
2811
|
+
// goes negative, making the slices behave unexpectedly and return MORE than
|
|
2812
|
+
// max — so hard-cap to max (never below zero) in that degenerate case.
|
|
2813
|
+
if (max <= marker.length) return s.slice(0, Math.max(0, max));
|
|
2814
|
+
const budget = max - marker.length;
|
|
2815
|
+
const head = Math.ceil(budget * 0.6);
|
|
2816
|
+
const tail = budget - head;
|
|
2817
|
+
return `${s.slice(0, head)}${marker}${s.slice(s.length - tail)}`;
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
// Build an informative, token-redacted failure reason from a runGit result.
|
|
2821
|
+
// Two things the old `stderr || stdout`.slice(0,500) message threw away:
|
|
2822
|
+
// 1. On a timeout Node SIGTERM-kills git (status→128, signal='SIGTERM') — say
|
|
2823
|
+
// so, and after how long, instead of surfacing only git's flushed
|
|
2824
|
+
// "Cloning into '…'..." progress line as if it were the failure.
|
|
2825
|
+
// 2. `stderr || stdout` let a non-empty-but-useless stderr mask a real reason
|
|
2826
|
+
// on stdout — capture BOTH streams (stderr then stdout) so either survives.
|
|
2827
|
+
function describeGitFailure(action, result, { token, timeoutMs } = {}) {
|
|
2828
|
+
const combined = boundGitOutput(
|
|
2829
|
+
redactToken([result && result.stderr, result && result.stdout].filter(Boolean).join('\n'), token),
|
|
2830
|
+
);
|
|
2831
|
+
// spawnSync's timeout kill lands as SIGTERM (its default killSignal); runGit
|
|
2832
|
+
// maps the null status to 128. Only SIGTERM means "timed out" — any OTHER
|
|
2833
|
+
// signal (e.g. SIGKILL from an OOM kill) is a distinct termination that we
|
|
2834
|
+
// must not misreport as a timeout.
|
|
2835
|
+
const signal = result && result.signal;
|
|
2836
|
+
if (signal === 'SIGTERM') {
|
|
2837
|
+
const secs = timeoutMs ? Math.round(timeoutMs / 1000) : null;
|
|
2838
|
+
const dur = secs ? ` after ${secs}s` : '';
|
|
2839
|
+
return `${action} timed out${dur} (SIGTERM)${combined ? `; last output: ${combined}` : ''}`;
|
|
2840
|
+
}
|
|
2841
|
+
if (signal) {
|
|
2842
|
+
return `${action} terminated by signal ${signal}${combined ? `: ${combined}` : ''}`;
|
|
2843
|
+
}
|
|
2844
|
+
const exit = result && result.status != null ? result.status : '?';
|
|
2845
|
+
return `${action} failed (exit ${exit})${combined ? `: ${combined}` : ''}`;
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2802
2848
|
// Write a GIT_ASKPASS helper that echoes $GIT_TOKEN, so the token reaches git
|
|
2803
2849
|
// via the child's ENV — never on argv or in the remote URL. Uses a Node helper
|
|
2804
2850
|
// (askpass.js reads GIT_TOKEN and writes it verbatim), launched by a per-OS
|
|
@@ -3082,17 +3128,25 @@ function provisionRepo({ envelope, token, runDir, timeoutMs = 120_000 }) {
|
|
|
3082
3128
|
|
|
3083
3129
|
const clone = runGit(cloneArgs, { env: gitEnv, timeoutMs });
|
|
3084
3130
|
if (clone.status !== 0) {
|
|
3085
|
-
throw new ProvisionError(
|
|
3131
|
+
throw new ProvisionError(describeGitFailure('git clone', clone, { token, timeoutMs }));
|
|
3086
3132
|
}
|
|
3087
3133
|
|
|
3088
3134
|
if (isSha) {
|
|
3089
3135
|
// The SHA may not be present under a shallow clone of the default branch —
|
|
3090
3136
|
// fetch it explicitly (best effort), then check it out (detached HEAD).
|
|
3091
3137
|
const fetch = runGit([...credArgs(), 'fetch', '--no-tags', 'origin', target], { cwd: workspaceDir, env: gitEnv, timeoutMs });
|
|
3092
|
-
const co = runGit(['checkout', '--detach', target], { cwd: workspaceDir, env: gitEnv });
|
|
3138
|
+
const co = runGit(['checkout', '--detach', target], { cwd: workspaceDir, env: gitEnv, timeoutMs });
|
|
3093
3139
|
if (co.status !== 0) {
|
|
3094
|
-
|
|
3095
|
-
|
|
3140
|
+
// Prefer the failing checkout's own output, but fall back to the fetch's
|
|
3141
|
+
// (a timeout/fatal there is the real cause the checkout can't recover from)
|
|
3142
|
+
// ONLY when fetch actually failed — a succeeded fetch (status 0) is not the
|
|
3143
|
+
// cause, and reporting it would yield a misleading "exit 0" message.
|
|
3144
|
+
const useCheckout = !!(co.stderr || co.stdout || fetch.status === 0);
|
|
3145
|
+
const source = useCheckout ? co : fetch;
|
|
3146
|
+
// Label the failure with the action whose output we actually report, so a
|
|
3147
|
+
// fetch timeout/fatal isn't misreported as a checkout failure.
|
|
3148
|
+
const action = useCheckout ? `git checkout ${target}` : `git fetch origin ${target}`;
|
|
3149
|
+
throw new ProvisionError(describeGitFailure(action, source, { token, timeoutMs }));
|
|
3096
3150
|
}
|
|
3097
3151
|
}
|
|
3098
3152
|
|
|
@@ -3127,8 +3181,8 @@ function provisionRepo({ envelope, token, runDir, timeoutMs = 120_000 }) {
|
|
|
3127
3181
|
// finalizeGit skips the push/PR reconcile instead of pushing a bogus ref.
|
|
3128
3182
|
let workingBranch = null;
|
|
3129
3183
|
if (envelope.branch?.create) {
|
|
3130
|
-
const cb = runGit(['checkout', '-B', envelope.branch.create], { cwd: workspaceDir, env: gitEnv });
|
|
3131
|
-
if (cb.status !== 0) throw new ProvisionError(`git checkout -B ${envelope.branch.create}
|
|
3184
|
+
const cb = runGit(['checkout', '-B', envelope.branch.create], { cwd: workspaceDir, env: gitEnv, timeoutMs });
|
|
3185
|
+
if (cb.status !== 0) throw new ProvisionError(describeGitFailure(`git checkout -B ${envelope.branch.create}`, cb, { token, timeoutMs }));
|
|
3132
3186
|
workingBranch = envelope.branch.create;
|
|
3133
3187
|
} else {
|
|
3134
3188
|
const head = runGit(['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: workspaceDir, env: gitEnv });
|
|
@@ -3278,9 +3332,10 @@ function finalizeGit({ workspaceDir, gitEnv, startSha, workingBranch, envelope,
|
|
|
3278
3332
|
if (!workingBranch) {
|
|
3279
3333
|
out.detached = true; // clone landed on a tag/sha ⇒ no branch to push
|
|
3280
3334
|
} else if (coerceBool(envelope.branch?.push, true) && out.commits.length > 0) {
|
|
3281
|
-
const
|
|
3335
|
+
const pushTimeoutMs = 120_000; // matches runGit's default; surfaced in a timeout reason
|
|
3336
|
+
const push = runGit([...credArgs(), 'push', '--set-upstream', 'origin', workingBranch], { cwd: workspaceDir, env: gitEnv, timeoutMs: pushTimeoutMs });
|
|
3282
3337
|
if (push.status === 0) out.pushed = true;
|
|
3283
|
-
else out.pushError =
|
|
3338
|
+
else out.pushError = describeGitFailure('git push', push, { token, timeoutMs: pushTimeoutMs });
|
|
3284
3339
|
}
|
|
3285
3340
|
|
|
3286
3341
|
if (workingBranch && envelope.task?.allowPr) {
|
|
@@ -8388,6 +8443,8 @@ export {
|
|
|
8388
8443
|
startLockExtender,
|
|
8389
8444
|
provisionRepo,
|
|
8390
8445
|
finalizeGit,
|
|
8446
|
+
describeGitFailure,
|
|
8447
|
+
boundGitOutput,
|
|
8391
8448
|
reconcileAgentPr,
|
|
8392
8449
|
resolveCommitterIdentity,
|
|
8393
8450
|
isPlaceholderEmail,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c8ctl-plugin-nano",
|
|
3
|
-
"version": "1.35.
|
|
3
|
+
"version": "1.35.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "c8ctl plugin to start, inspect, and stop a local Nano BPM (nanobpmn) cluster",
|
|
6
6
|
"main": "c8ctl-plugin.js",
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
},
|
|
58
58
|
"optionalDependencies": {
|
|
59
59
|
"node-pty": "^1.0.0",
|
|
60
|
-
"@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.35.
|
|
61
|
-
"@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.35.
|
|
62
|
-
"@nanobpm/c8ctl-plugin-nano-linux-x64": "1.35.
|
|
63
|
-
"@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.35.
|
|
64
|
-
"@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.35.
|
|
65
|
-
"@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.35.
|
|
66
|
-
"@nanobpm/c8ctl-plugin-nano-win32-x64": "1.35.
|
|
60
|
+
"@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.35.6",
|
|
61
|
+
"@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.35.6",
|
|
62
|
+
"@nanobpm/c8ctl-plugin-nano-linux-x64": "1.35.6",
|
|
63
|
+
"@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.35.6",
|
|
64
|
+
"@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.35.6",
|
|
65
|
+
"@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.35.6",
|
|
66
|
+
"@nanobpm/c8ctl-plugin-nano-win32-x64": "1.35.6"
|
|
67
67
|
}
|
|
68
68
|
}
|