@bli-cockpit/cli 0.2.18 → 0.2.20
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/autostart.js +27 -4
- package/dist/commands/public-root.js +1 -1
- package/dist/health-detail.js +30 -7
- package/package.json +1 -1
package/dist/autostart.js
CHANGED
|
@@ -10,6 +10,16 @@ const WINDOWS_AUTOSTART_SCRIPT_NAME = "autostart-sync.ps1";
|
|
|
10
10
|
const WINDOWS_AUTOSTART_REGISTRATION_SCRIPT_NAME = "autostart-register.ps1";
|
|
11
11
|
const UTF8_BOM = "\uFEFF";
|
|
12
12
|
export const DEFAULT_AUTOSTART_INTERVAL_SECONDS = 15 * 60;
|
|
13
|
+
/**
|
|
14
|
+
* macOS rewrites this file on every network transition (join, leave, DNS
|
|
15
|
+
* change), so watching it retries spooled uploads the moment connectivity
|
|
16
|
+
* returns instead of waiting out the StartInterval \u2014 the lid-closed-mid-upload
|
|
17
|
+
* machine hopping caf\u00E9s is where most historical upload failures came from
|
|
18
|
+
* (BLI-2604). The real file, not the /etc/resolv.conf symlink: launchd watches
|
|
19
|
+
* the path it is given, and the symlink itself never changes. Burst fires are
|
|
20
|
+
* cheap \u2014 the collection lock turns overlap into a named no-op.
|
|
21
|
+
*/
|
|
22
|
+
export const DARWIN_NETWORK_CHANGE_SIGNAL = "/private/var/run/resolv.conf";
|
|
13
23
|
const UNSUPPORTED_MESSAGE = "autostart is supported on macOS and Windows only";
|
|
14
24
|
function plistPathFor(homeDir) {
|
|
15
25
|
return path.join(homeDir, "Library", "LaunchAgents", `${AUTOSTART_LABEL}.plist`);
|
|
@@ -49,8 +59,13 @@ export async function installAutostartAgent(options) {
|
|
|
49
59
|
const stderrPath = path.join(paths.state_dir, "sync.err.log");
|
|
50
60
|
// launchd will not reliably watch a path that does not exist at load time, so
|
|
51
61
|
// only feed it the transcript dirs that are present right now. A missing dir
|
|
52
|
-
// is fine — the StartInterval floor still covers it.
|
|
53
|
-
|
|
62
|
+
// is fine — the StartInterval floor still covers it. The network signal is
|
|
63
|
+
// appended unconditionally: it always exists on the Macs this plist targets,
|
|
64
|
+
// and an existence filter would drop it when rendering on another host.
|
|
65
|
+
const watchPaths = [
|
|
66
|
+
...(await existingWatchPaths(homeDir)),
|
|
67
|
+
DARWIN_NETWORK_CHANGE_SIGNAL,
|
|
68
|
+
];
|
|
54
69
|
await mkdir(path.dirname(plistPath), { recursive: true });
|
|
55
70
|
await mkdir(paths.state_dir, { recursive: true });
|
|
56
71
|
await writeFile(plistPath, renderPlist({
|
|
@@ -353,8 +368,16 @@ function renderWindowsRegistrationScript(options) {
|
|
|
353
368
|
`$taskName = ${powershellLiteral(options.taskName)}`,
|
|
354
369
|
`$syncScriptPath = ${powershellLiteral(options.scriptPath)}`,
|
|
355
370
|
"$powershellPath = Join-Path $PSHOME 'powershell.exe'",
|
|
356
|
-
|
|
357
|
-
|
|
371
|
+
// Windows PowerShell 5.1 passes a native argument's embedded quotes to
|
|
372
|
+
// CommandLineToArgvW unescaped, so a /TR value with bare quotes falls out
|
|
373
|
+
// of the quoted region at the first space inside a quoted path:
|
|
374
|
+
// `C:\Users\Brandon Chiem\...` reached schtasks as a stray `Chiem\...`
|
|
375
|
+
// argument and /Create exited 0x80004005 on every CLI version (BLI-2598).
|
|
376
|
+
// Escaping the embedded quotes as \" keeps the whole /TR value one
|
|
377
|
+
// argument; Task Scheduler still normalizes what it stores (BLI-2541),
|
|
378
|
+
// which the read-back validator already compares path-wise.
|
|
379
|
+
"$actionArgs = '-NoProfile -NonInteractive -ExecutionPolicy Bypass -File \\\"' + $syncScriptPath + '\\\"'",
|
|
380
|
+
"$taskCommand = '\\\"' + $powershellPath + '\\\" ' + $actionArgs",
|
|
358
381
|
`& schtasks.exe /Create /TN $taskName /TR $taskCommand /SC MINUTE /MO ${options.intervalMinutes} /IT /RL LIMITED /F | Out-Null`,
|
|
359
382
|
"if ($LASTEXITCODE -ne 0) { throw \"schtasks /Create exited $LASTEXITCODE\" }",
|
|
360
383
|
"$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -MultipleInstances IgnoreNew",
|
|
@@ -15,7 +15,7 @@ export async function runCockpitCli(argv, io) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
if (command === "--version" || command === "-V" || command === "version") {
|
|
18
|
-
writeLine(io?.stdout ?? process.stdout, "0.2.
|
|
18
|
+
writeLine(io?.stdout ?? process.stdout, "0.2.20");
|
|
19
19
|
return 0;
|
|
20
20
|
}
|
|
21
21
|
|
package/dist/health-detail.js
CHANGED
|
@@ -27,9 +27,24 @@ import { redactSecretLikeContent } from "@bli-cockpit/telemetry-core";
|
|
|
27
27
|
export const HEALTH_DETAIL_MAX_CHARS = 600;
|
|
28
28
|
const WINDOWS_ABSOLUTE_PATH = /[A-Za-z]:\\[^\s"';]+/gu;
|
|
29
29
|
const UNC_PATH = /\\\\[^\s"';]+/gu;
|
|
30
|
+
// A quoted Windows path may contain spaces; the quotes bound it, so the whole
|
|
31
|
+
// quoted region is the path. Unquoted, the space-blind pattern above stops at
|
|
32
|
+
// the first space — which is how `C:\Users\Brandon Chiem\...` masked to
|
|
33
|
+
// `[path] Chiem\...` and an operator surname reached the server (BLI-2599).
|
|
34
|
+
const QUOTED_WINDOWS_PATH = /"[A-Za-z]:\\[^"]*"/gu;
|
|
35
|
+
const SINGLE_QUOTED_WINDOWS_PATH = /'[A-Za-z]:\\[^']*'/gu;
|
|
36
|
+
// A backslash-joined fragment of three or more segments is path material even
|
|
37
|
+
// without a drive anchor: schtasks echoes a severed path tail as its own token
|
|
38
|
+
// (`Chiem\.local\state\...`, the BLI-2598 receipt). Over-matching here is the
|
|
39
|
+
// safe direction — this boundary exists to keep local identifiers on the
|
|
40
|
+
// machine, not to keep messages pretty.
|
|
41
|
+
const BACKSLASH_PATH_FRAGMENT = /[^\s"';:,()]+(?:\\[^\s"';:,()]+){2,}/gu;
|
|
30
42
|
// An absolute POSIX path of at least two segments. One segment ("/tmp") carries
|
|
31
43
|
// nothing identifying and masking it would make messages harder to read.
|
|
32
44
|
const POSIX_ABSOLUTE_PATH = /\/[\w.@-]+(?:\/[\w.@ -]+)+/gu;
|
|
45
|
+
// The tail a space split off a masked path: `[path] Chiem\...` collapses back
|
|
46
|
+
// into the placeholder it was severed from.
|
|
47
|
+
const PATH_PLACEHOLDER_RUN = /\[path\](?:\s+\[path\])+/gu;
|
|
33
48
|
export function redactedHealthDetail(message) {
|
|
34
49
|
const collapsed = message.replace(/\s+/gu, " ").trim();
|
|
35
50
|
if (!collapsed)
|
|
@@ -43,20 +58,28 @@ export function redactedHealthDetail(message) {
|
|
|
43
58
|
: masked;
|
|
44
59
|
}
|
|
45
60
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
61
|
+
* Identifiers first, so the account name is caught even when it sits inside a
|
|
62
|
+
* path the path patterns would only partially cover (BLI-2599: the path
|
|
63
|
+
* pattern stopped at the space in `Brandon Chiem` and the surname survived).
|
|
64
|
+
* Then quoted paths before unquoted ones, because the quotes are what bound a
|
|
65
|
+
* space-containing path; then the drive-anchored and fragment patterns; then
|
|
66
|
+
* adjacent placeholders collapse so a severed path reads as one `[path]`.
|
|
48
67
|
*/
|
|
49
68
|
export function maskLocalIdentifiers(value) {
|
|
50
|
-
let text = value
|
|
51
|
-
.replace(UNC_PATH, "[path]")
|
|
52
|
-
.replace(WINDOWS_ABSOLUTE_PATH, "[path]")
|
|
53
|
-
.replace(POSIX_ABSOLUTE_PATH, "[path]");
|
|
69
|
+
let text = value;
|
|
54
70
|
for (const [identifier, placeholder] of localIdentifiers()) {
|
|
55
71
|
if (!identifier)
|
|
56
72
|
continue;
|
|
57
73
|
text = text.replace(literalPattern(identifier), placeholder);
|
|
58
74
|
}
|
|
59
|
-
return text
|
|
75
|
+
return text
|
|
76
|
+
.replace(QUOTED_WINDOWS_PATH, "[path]")
|
|
77
|
+
.replace(SINGLE_QUOTED_WINDOWS_PATH, "[path]")
|
|
78
|
+
.replace(UNC_PATH, "[path]")
|
|
79
|
+
.replace(WINDOWS_ABSOLUTE_PATH, "[path]")
|
|
80
|
+
.replace(BACKSLASH_PATH_FRAGMENT, "[path]")
|
|
81
|
+
.replace(POSIX_ABSOLUTE_PATH, "[path]")
|
|
82
|
+
.replace(PATH_PLACEHOLDER_RUN, "[path]");
|
|
60
83
|
}
|
|
61
84
|
function localIdentifiers() {
|
|
62
85
|
const identifiers = [];
|