@bivy/bivy 0.1.1 → 0.1.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/control-plane-tasks.js +17 -0
- package/dist/git-auth.js +7 -1
- package/dist/server.js +21 -1
- package/package.json +1 -1
|
@@ -117,6 +117,23 @@ export class ControlPlaneTaskPoller {
|
|
|
117
117
|
poke() {
|
|
118
118
|
void this.tick();
|
|
119
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Replace the routing labels this live poller serves.
|
|
122
|
+
*
|
|
123
|
+
* Node names are editable while the daemon is running, and targeted queue
|
|
124
|
+
* labels are derived from that name (`bivy/<name>`). Keeping the startup-time
|
|
125
|
+
* labels forever leaves work routed to a renamed node pending until the daemon
|
|
126
|
+
* restarts. Update in place so already-running queue jobs are not disturbed,
|
|
127
|
+
* then poll immediately for work addressed to the new name.
|
|
128
|
+
*/
|
|
129
|
+
setLabels(labels) {
|
|
130
|
+
const next = Array.from(new Set(labels.map((label) => label.trim()).filter(Boolean)));
|
|
131
|
+
if (!next.length || (next.length === this.cfg.labels.length && next.every((label, i) => label === this.cfg.labels[i])))
|
|
132
|
+
return;
|
|
133
|
+
this.cfg.labels = next;
|
|
134
|
+
console.log(`[control-plane-tasks] now watching hosted queue for labels [${next.join(", ")}]`);
|
|
135
|
+
this.poke();
|
|
136
|
+
}
|
|
120
137
|
stop() {
|
|
121
138
|
if (this.timer)
|
|
122
139
|
clearInterval(this.timer);
|
package/dist/git-auth.js
CHANGED
|
@@ -88,7 +88,13 @@ function writeIfChanged(file, content, mode) {
|
|
|
88
88
|
export function ensureCredentialHelper() {
|
|
89
89
|
fs.mkdirSync(credDir(), { recursive: true, mode: 0o700 });
|
|
90
90
|
writeIfChanged(workerPath(), WORKER_SOURCE, 0o700);
|
|
91
|
-
|
|
91
|
+
// Git can invoke a credential helper after its caller's checkout has been
|
|
92
|
+
// removed (for example while an old daemon drains across an npm update, or
|
|
93
|
+
// while a broken clone is being rebuilt). Node resolves its cwd before it
|
|
94
|
+
// evaluates the worker and aborts with uv_cwd when that inherited directory
|
|
95
|
+
// has been unlinked. Move to a stable directory in the shell first; the worker
|
|
96
|
+
// resolves endpoint.json from import.meta.url and never relies on cwd.
|
|
97
|
+
const shim = `#!/usr/bin/env sh\ncd / || exit 0\nexec ${shDq(process.execPath)} ${shDq(workerPath())} "$@"\n`;
|
|
92
98
|
writeIfChanged(shimPath(), shim, 0o700);
|
|
93
99
|
return shimPath();
|
|
94
100
|
}
|
package/dist/server.js
CHANGED
|
@@ -86,7 +86,7 @@ const repoRoot = path.resolve(__dirname, "..");
|
|
|
86
86
|
// running from source. Packaged/release builds may override them (BIVY_ASSET_ROOT,
|
|
87
87
|
// BIVY_DATA_DIR) so it can write outside the read-only app bundle.
|
|
88
88
|
const assetRoot = process.env.BIVY_ASSET_ROOT ?? repoRoot;
|
|
89
|
-
const appDir = process.env.BIVY_DATA_DIR ?? path.join(repoRoot, ".bivy");
|
|
89
|
+
const appDir = path.resolve(process.env.BIVY_DATA_DIR ?? path.join(repoRoot, ".bivy"));
|
|
90
90
|
// Load persisted env from cli.json into process.env so config written there —
|
|
91
91
|
// e.g. connecting a GitHub App (BIVY_GITHUB_APP_ID / BIVY_GITHUB_HOSTED_TASKS /
|
|
92
92
|
// BIVY_NODE_LABEL) — takes effect on the NEXT restart even if the service
|
|
@@ -115,6 +115,13 @@ initSharedDepCache(appDir);
|
|
|
115
115
|
// Materialize the git credential helper under the data dir so repo clones can
|
|
116
116
|
// authenticate without ever writing a token into their remote URL / .git/config.
|
|
117
117
|
configureGitAuth(appDir);
|
|
118
|
+
// Never leave the daemon parked in its installed package directory. A global
|
|
119
|
+
// npm update atomically replaces that directory while the old process drains;
|
|
120
|
+
// any later child process (notably git's remote/credential helpers) then aborts
|
|
121
|
+
// before running with "Unable to read current working directory". appDir is the
|
|
122
|
+
// durable state root and every workspace/asset path below is already absolute.
|
|
123
|
+
// Anchoring the process itself fixes all subprocess paths, not just `git clone`.
|
|
124
|
+
process.chdir(appDir);
|
|
118
125
|
// Make `bivy update` and user-scoped npm globals available to agents/tools
|
|
119
126
|
// launched by the daemon even when the node runs under systemd/launchd with a
|
|
120
127
|
// minimal PATH. The installer also symlinks ~/.local/bin/bivy, but adding these
|
|
@@ -2377,6 +2384,9 @@ const RELAY_COMMANDS = {
|
|
|
2377
2384
|
"node.rename"(msg, ctx) {
|
|
2378
2385
|
const prev = identity.name;
|
|
2379
2386
|
const name = identity.setName(String(msg.name ?? ""));
|
|
2387
|
+
// Queue routing follows the node name (`bivy/<name>`). Update the live
|
|
2388
|
+
// poller now instead of leaving it on its startup-time label until restart.
|
|
2389
|
+
refreshControlPlaneTaskLabels();
|
|
2380
2390
|
void advertiseNodeName(name, prev);
|
|
2381
2391
|
ctx.broadcast({ type: "node.updated", name });
|
|
2382
2392
|
ctx.reply({ type: "node.updated", name });
|
|
@@ -3850,6 +3860,7 @@ async function advertiseNodeName(name, prevName) {
|
|
|
3850
3860
|
const accepted = typeof data?.node?.name === "string" ? data.node.name : undefined;
|
|
3851
3861
|
if (accepted && accepted !== identity.name) {
|
|
3852
3862
|
identity.setName(accepted);
|
|
3863
|
+
refreshControlPlaneTaskLabels();
|
|
3853
3864
|
broadcast({ type: "node.updated", name: accepted });
|
|
3854
3865
|
relay?.sendEvent({ type: "node.updated", name: accepted });
|
|
3855
3866
|
}
|
|
@@ -3859,6 +3870,7 @@ async function advertiseNodeName(name, prevName) {
|
|
|
3859
3870
|
// optimistic local change so the node name stays consistent with the account.
|
|
3860
3871
|
if (prevName && prevName !== identity.name) {
|
|
3861
3872
|
identity.setName(prevName);
|
|
3873
|
+
refreshControlPlaneTaskLabels();
|
|
3862
3874
|
broadcast({ type: "node.updated", name: prevName });
|
|
3863
3875
|
relay?.sendEvent({ type: "node.updated", name: prevName });
|
|
3864
3876
|
}
|
|
@@ -4524,6 +4536,14 @@ async function startGitHubTasksIfConfigured() {
|
|
|
4524
4536
|
githubPoller.start();
|
|
4525
4537
|
}
|
|
4526
4538
|
let controlPlanePoller;
|
|
4539
|
+
/** Refresh a running queue poller's labels after the node is renamed. */
|
|
4540
|
+
function refreshControlPlaneTaskLabels() {
|
|
4541
|
+
if (!controlPlanePoller)
|
|
4542
|
+
return;
|
|
4543
|
+
const cfg = resolveControlPlaneTaskConfig(loadRelayConfig(appDir), process.env, identity.name);
|
|
4544
|
+
if (cfg)
|
|
4545
|
+
controlPlanePoller.setLabels(cfg.labels);
|
|
4546
|
+
}
|
|
4527
4547
|
let githubApps;
|
|
4528
4548
|
const installationIdByRepo = new Map();
|
|
4529
4549
|
/** Resolve (once) the GitHub Apps configured on this node. */
|