querysub 0.656.0 → 0.658.0
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "querysub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.658.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
|
|
@@ -79,8 +79,8 @@
|
|
|
79
79
|
"node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
|
|
80
80
|
"pako": "^2.1.0",
|
|
81
81
|
"peggy": "^5.0.6",
|
|
82
|
-
"sliftutils": "^1.7.
|
|
83
|
-
"socket-function": "^1.2.
|
|
82
|
+
"sliftutils": "^1.7.130",
|
|
83
|
+
"socket-function": "^1.2.35",
|
|
84
84
|
"terser": "^5.31.0",
|
|
85
85
|
"typenode": "^6.6.1",
|
|
86
86
|
"typesafecss": "^0.32.0",
|
|
@@ -80,12 +80,12 @@ function extractChangedLines(diff: string): string {
|
|
|
80
80
|
const rowButtonStyle = css.pad2(12, 8).button.bord2(0, 0, 20).fontWeight("bold");
|
|
81
81
|
|
|
82
82
|
export class CommitModal extends qreact.Component<{
|
|
83
|
-
/** True
|
|
84
|
-
|
|
83
|
+
/** True when the commit also publishes querysub, so the diff covers both repos and the labels say so. */
|
|
84
|
+
includeQuerysub?: boolean;
|
|
85
85
|
/** The `git status --porcelain` lines, shown as a file list. */
|
|
86
86
|
changes: string[];
|
|
87
|
-
/** Performs the actual commit + push (and publish, for querysub). */
|
|
88
|
-
onCommit: (message: string) => Promise<void>;
|
|
87
|
+
/** Performs the actual commit + push (and publish, for querysub). Calls setStep as it moves through its steps, which is shown on the commit button. */
|
|
88
|
+
onCommit: (message: string, setStep: (step: string) => void) => Promise<void>;
|
|
89
89
|
}> {
|
|
90
90
|
state = t.state({
|
|
91
91
|
message: t.string,
|
|
@@ -96,6 +96,7 @@ export class CommitModal extends qreact.Component<{
|
|
|
96
96
|
diffLoading: t.boolean(true),
|
|
97
97
|
summarizing: t.boolean(false),
|
|
98
98
|
committing: t.boolean(false),
|
|
99
|
+
step: t.string,
|
|
99
100
|
error: t.string,
|
|
100
101
|
lastCost: t.number,
|
|
101
102
|
});
|
|
@@ -108,9 +109,13 @@ export class CommitModal extends qreact.Component<{
|
|
|
108
109
|
|
|
109
110
|
private async loadDiff() {
|
|
110
111
|
try {
|
|
111
|
-
let
|
|
112
|
+
let includeQuerysub = Querysub.localRead(() => this.props.includeQuerysub);
|
|
112
113
|
let controller = MachineServiceController(SocketFunction.browserNodeId());
|
|
113
|
-
let
|
|
114
|
+
let diffs = await Promise.all([
|
|
115
|
+
includeQuerysub && controller.getGitDiff.promise({ useQuerysub: true }) || "",
|
|
116
|
+
controller.getGitDiff.promise({ useQuerysub: false }),
|
|
117
|
+
]);
|
|
118
|
+
let diff = diffs.filter(x => x).join("\n");
|
|
114
119
|
console.log("Received commit diff, changed lines:\n" + extractChangedLines(diff));
|
|
115
120
|
Querysub.localCommit(() => {
|
|
116
121
|
this.state.diff = diff;
|
|
@@ -172,22 +177,28 @@ export class CommitModal extends qreact.Component<{
|
|
|
172
177
|
}
|
|
173
178
|
Querysub.localCommit(() => {
|
|
174
179
|
this.state.committing = true;
|
|
180
|
+
this.state.step = "";
|
|
175
181
|
this.state.error = "";
|
|
176
182
|
});
|
|
177
183
|
try {
|
|
178
|
-
await this.props.onCommit(message
|
|
184
|
+
await this.props.onCommit(message, step => {
|
|
185
|
+
Querysub.localCommit(() => {
|
|
186
|
+
this.state.step = step;
|
|
187
|
+
});
|
|
188
|
+
});
|
|
179
189
|
closeAllModals();
|
|
180
190
|
} catch (e: any) {
|
|
181
191
|
Querysub.localCommit(() => {
|
|
182
192
|
this.state.error = `Commit failed: ${e.stack ?? e}`;
|
|
183
193
|
this.state.committing = false;
|
|
194
|
+
this.state.step = "";
|
|
184
195
|
});
|
|
185
196
|
}
|
|
186
197
|
}
|
|
187
198
|
|
|
188
199
|
render() {
|
|
189
200
|
let { diff, diffLoading, summarizing, committing } = this.state;
|
|
190
|
-
let commitLabel = this.props.
|
|
201
|
+
let commitLabel = this.props.includeQuerysub && "Publish Querysub & Commit & Push" || "Commit & Push";
|
|
191
202
|
|
|
192
203
|
let summarizeLabel: string;
|
|
193
204
|
if (diffLoading) {
|
|
@@ -274,7 +285,7 @@ export class CommitModal extends qreact.Component<{
|
|
|
274
285
|
disabled={committing}
|
|
275
286
|
onClick={() => void this.doCommit()}
|
|
276
287
|
>
|
|
277
|
-
{committing
|
|
288
|
+
{committing && `⏳ ${this.state.step || `Running ${commitLabel}…`}` || `⬆️ ${commitLabel}`}
|
|
278
289
|
</button>
|
|
279
290
|
</div>
|
|
280
291
|
|
|
@@ -145,46 +145,45 @@ export class UpdateButtons extends qreact.Component<{
|
|
|
145
145
|
});
|
|
146
146
|
let outdatedRefs = unique(outdatedServices.map(service => service.parameters.gitRef));
|
|
147
147
|
|
|
148
|
+
let querysubChanges = gitInfo?.querysubUncommitted ?? [];
|
|
149
|
+
let serviceChanges = gitInfo?.uncommitted ?? [];
|
|
150
|
+
let allChanges = [
|
|
151
|
+
...querysubChanges.map(change => `querysub: ${change}`),
|
|
152
|
+
...serviceChanges,
|
|
153
|
+
];
|
|
154
|
+
let includeQuerysub = !!querysubChanges.length;
|
|
155
|
+
|
|
148
156
|
return <>
|
|
149
|
-
{!!
|
|
157
|
+
{!!allChanges.length && gitInfo && <button
|
|
150
158
|
className={buttonStyle.hsl(260, 60, 90)}
|
|
151
|
-
title={
|
|
159
|
+
title={allChanges.join("\n")}
|
|
152
160
|
onClick={() => {
|
|
153
161
|
showFullscreenModal({
|
|
154
162
|
content: <CommitModal
|
|
155
|
-
|
|
156
|
-
changes={
|
|
157
|
-
onCommit={async message => {
|
|
158
|
-
|
|
163
|
+
includeQuerysub={includeQuerysub}
|
|
164
|
+
changes={allChanges}
|
|
165
|
+
onCommit={async (message, setStep) => {
|
|
166
|
+
if (includeQuerysub) {
|
|
167
|
+
setStep("Step 1/2: Publishing querysub (version bump, npm publish, commit & push, package.json update)…");
|
|
168
|
+
await controller.commitPushAndPublishQuerysub.promise(message);
|
|
169
|
+
setStep("Step 2/2: Committing & pushing the service repo…");
|
|
170
|
+
} else {
|
|
171
|
+
setStep("Committing & pushing the service repo…");
|
|
172
|
+
}
|
|
173
|
+
await controller.commitPushService.promise(message);
|
|
159
174
|
}}
|
|
160
175
|
/>
|
|
161
176
|
});
|
|
162
177
|
}}
|
|
163
178
|
>
|
|
164
179
|
<div>
|
|
165
|
-
{bigEmoji("📚", -5)}
|
|
166
|
-
Publish & Commit & Push
|
|
180
|
+
{bigEmoji(includeQuerysub && "📚" || "⬆️", -5)}
|
|
181
|
+
{includeQuerysub && "Publish Querysub & " || ""}Commit & Push All ({includeQuerysub && `${querysubChanges.length} querysub + ` || ""}{serviceChanges.length} Files Changed)
|
|
167
182
|
</div>
|
|
168
|
-
<div className={css.hbox(5)}>
|
|
183
|
+
{includeQuerysub && <div className={css.hbox(5)}>
|
|
169
184
|
<b>Current</b>
|
|
170
185
|
<RenderGitRefInfo gitRef={gitInfo.querysubRef} isQuerysub />
|
|
171
|
-
</div>
|
|
172
|
-
</button>}
|
|
173
|
-
{!!gitInfo?.uncommitted.length && <button
|
|
174
|
-
className={buttonStyle.hsl(210, 40, 90)}
|
|
175
|
-
title={gitInfo?.uncommitted.join("\n")}
|
|
176
|
-
onClick={() => {
|
|
177
|
-
showFullscreenModal({
|
|
178
|
-
content: <CommitModal
|
|
179
|
-
changes={gitInfo?.uncommitted ?? []}
|
|
180
|
-
onCommit={async message => {
|
|
181
|
-
await controller.commitPushService.promise(message);
|
|
182
|
-
}}
|
|
183
|
-
/>
|
|
184
|
-
});
|
|
185
|
-
}}
|
|
186
|
-
>
|
|
187
|
-
{bigEmoji("⬆️")} <span>Commit & Push ({gitInfo?.uncommitted.length} Files Changed)</span>
|
|
186
|
+
</div>}
|
|
188
187
|
</button>}
|
|
189
188
|
|
|
190
189
|
{outdatedServices.length > 0 && gitInfo && <>
|
|
@@ -114,6 +114,12 @@ async function writeRemoteFile(sshRemote: string, remotePath: string, content: s
|
|
|
114
114
|
await runPromise(`ssh ${sshRemote} "echo ${encoded} | base64 -d | ${write}"`);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/** Reads one value off the remote: the last line of the command's output, since banners and connection chatter come before it. */
|
|
118
|
+
async function sshValue(sshRemote: string, command: string, config?: { nothrow?: boolean }): Promise<string> {
|
|
119
|
+
let output = await runPromise(`ssh ${sshRemote} "${command}"`, { nothrow: config?.nothrow });
|
|
120
|
+
return (output.trim().split("\n").at(-1) || "").trim();
|
|
121
|
+
}
|
|
122
|
+
|
|
117
123
|
function getGitHubKeyCachePath(repoUrl: string): string {
|
|
118
124
|
let repoOwner = "";
|
|
119
125
|
let repoName = "";
|
|
@@ -433,6 +439,17 @@ async function main() {
|
|
|
433
439
|
console.log("✅ Build tools installed");
|
|
434
440
|
}
|
|
435
441
|
|
|
442
|
+
// The daemon runs everything in tmux screens, so setup cannot get by without it
|
|
443
|
+
console.log("Ensuring tmux is installed...");
|
|
444
|
+
try {
|
|
445
|
+
await runPromise(`ssh ${sshRemote} "which tmux"`);
|
|
446
|
+
console.log("✅ Tmux already installed");
|
|
447
|
+
} catch {
|
|
448
|
+
console.log("Installing tmux...");
|
|
449
|
+
await runPromise(`ssh ${sshRemote} "sudo apt install -y tmux"`);
|
|
450
|
+
console.log("✅ Tmux installed");
|
|
451
|
+
}
|
|
452
|
+
|
|
436
453
|
// 3. Ensure nodejs is installed on remote server
|
|
437
454
|
console.log("Ensuring Node.js is installed...");
|
|
438
455
|
try {
|
|
@@ -461,8 +478,9 @@ async function main() {
|
|
|
461
478
|
await runPromise(`ssh ${sshRemote} "sudo timedatectl set-timezone America/New_York"`);
|
|
462
479
|
console.log("✅ Timezone set to America/New_York");
|
|
463
480
|
|
|
481
|
+
// Via .tmux.conf rather than set-option, as set-option needs a running tmux server and there is none on a fresh machine
|
|
464
482
|
console.log(`Setting tmux scrollback history to 100000...`);
|
|
465
|
-
await runPromise(`ssh ${sshRemote} "tmux set-option -g history-limit 100000"`);
|
|
483
|
+
await runPromise(`ssh ${sshRemote} "grep -qxF 'set-option -g history-limit 100000' ~/.tmux.conf 2>/dev/null || echo 'set-option -g history-limit 100000' >> ~/.tmux.conf"`);
|
|
466
484
|
console.log("✅ Tmux scrollback history set to 100000");
|
|
467
485
|
|
|
468
486
|
// 5. Clone current repo into ~/machine-alwaysup with SSH key handling for private repos
|
|
@@ -491,7 +509,7 @@ async function main() {
|
|
|
491
509
|
}
|
|
492
510
|
|
|
493
511
|
// Get the public key from remote machine
|
|
494
|
-
const sshPublicKey = await
|
|
512
|
+
const sshPublicKey = await sshValue(sshRemote, "cat ~/.ssh/id_rsa.pub");
|
|
495
513
|
const keyTitle = `Machine Setup - ${sshRemote} - ${new Date().toISOString()}`;
|
|
496
514
|
|
|
497
515
|
// Add the deploy key to GitHub repository
|
|
@@ -513,8 +531,8 @@ async function main() {
|
|
|
513
531
|
console.log("✅ Dependencies installed");
|
|
514
532
|
|
|
515
533
|
// 6. Install the daemon that keeps the machine process running
|
|
516
|
-
let remoteUser =
|
|
517
|
-
let remoteHome =
|
|
534
|
+
let remoteUser = await sshValue(sshRemote, "whoami");
|
|
535
|
+
let remoteHome = await sshValue(sshRemote, "echo $HOME");
|
|
518
536
|
console.log(`Installing the ${SERVICE_UNIT_NAME} daemon (user ${remoteUser}, home ${remoteHome})...`);
|
|
519
537
|
await writeRemoteFile(sshRemote, `~/${DAEMON_SCRIPT_NAME}`, getDaemonScript(remoteHome), false);
|
|
520
538
|
await runPromise(`ssh ${sshRemote} "chmod +x ~/${DAEMON_SCRIPT_NAME}"`);
|
|
@@ -560,7 +578,7 @@ sudo systemctl start ${SERVICE_UNIT_NAME}
|
|
|
560
578
|
let screenDeadline = Date.now() + SCREEN_VERIFY_TIMEOUT;
|
|
561
579
|
let screenUp = false;
|
|
562
580
|
while (Date.now() < screenDeadline) {
|
|
563
|
-
let panePid =
|
|
581
|
+
let panePid = await sshValue(sshRemote, `tmux list-panes -t ${SERVICE_NAME} -F '#{pane_pid}' 2>/dev/null || true`, { nothrow: true });
|
|
564
582
|
if (panePid) {
|
|
565
583
|
screenUp = true;
|
|
566
584
|
break;
|
|
@@ -16,6 +16,8 @@ export function shimConsoleLogs() {
|
|
|
16
16
|
console.error(`Uncaught exception: ${String(error.stack || error)}`);
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
+
// Shared across log/warn/error/info, as writing one type can log another
|
|
20
|
+
let insideLogDisk = false;
|
|
19
21
|
function hookConsoleFnc(fncName: "log" | "warn" | "error" | "info") {
|
|
20
22
|
let console = globalThis.console;
|
|
21
23
|
let originalFnc = console[fncName];
|
|
@@ -28,10 +30,17 @@ export function shimConsoleLogs() {
|
|
|
28
30
|
if (
|
|
29
31
|
args.length > 0
|
|
30
32
|
&& String(args[0]).trim().length > 0
|
|
33
|
+
// Writing a log can itself log (ex, building the log path generates the identity CA on a fresh machine, which logs), which would recurse forever. Those inner logs only go to the real console below, skipping the disk.
|
|
34
|
+
&& !insideLogDisk
|
|
31
35
|
) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
insideLogDisk = true;
|
|
37
|
+
try {
|
|
38
|
+
// Assign to a variable, so it isn't shimmed by injectFileLocationToConsole
|
|
39
|
+
const logDiskThatIsntShimmed = diskLogger.logDisk;
|
|
40
|
+
logDiskThatIsntShimmed(fncName, ...args);
|
|
41
|
+
} finally {
|
|
42
|
+
insideLogDisk = false;
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
// Filter out objects added by injectFileLocationToConsole
|