hub-runner 0.2.5 → 0.2.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/lib/launchd.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  // The runner's launchd job: a plist in the user's LaunchAgents, loaded in the GUI domain, so it starts at login and
2
2
  // outlives every app. `RunAtLoad` without `KeepAlive`: a crash waits for `hub-runner start`.
3
3
  import { execFileSync, spawnSync } from 'node:child_process';
4
- import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
5
- import { dirname } from 'node:path';
6
- import { LABEL, credentialsFile, logFile, mainFile, plistFile, runnerDir, version } from './paths.mjs';
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
5
+ import { dirname, join } from 'node:path';
6
+ import { LABEL, appHome, credentialsFile, logFile, mainFile, plistFile, runnerDir, version } from './paths.mjs';
7
7
  import { deviceName } from './device.mjs';
8
8
 
9
9
  const xml = (s) => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
@@ -31,9 +31,19 @@ function bootout() {
31
31
  }
32
32
  }
33
33
 
34
- export function plist({ takeOver }) {
34
+ /** What the job runs: the app's install through its `current` symlink, or this npm install with the shell's pnpm. */
35
+ function program(home) {
36
+ if (home) {
37
+ const bin = join(home, 'bin');
38
+ return { node: join(bin, 'node'), main: join(home, 'hub-runner', 'main.mjs'), pnpm: join(bin, 'pnpm'), path: `${bin}:${process.env.PATH}`, build: readFileSync(join(home, 'build'), 'utf8').trim() };
39
+ }
35
40
  const pnpm = execFileSync('/bin/sh', ['-c', 'command -v pnpm'], { encoding: 'utf8' }).trim();
36
- const env = { HUB_PNPM: pnpm, PATH: process.env.PATH, HUB_RUNNER_DIR: runnerDir(), HUB_RUNNER_BUILD: version(), HUB_DEVICE_NAME: deviceName(), ...(takeOver ? { HUB_RUNNER_TAKE_OVER: '1' } : {}) };
41
+ return { node: process.execPath, main: mainFile(), pnpm, path: process.env.PATH, build: version() };
42
+ }
43
+
44
+ export function plist({ takeOver }) {
45
+ const run = program(appHome());
46
+ const env = { HUB_PNPM: run.pnpm, PATH: run.path, HUB_RUNNER_DIR: runnerDir(), HUB_RUNNER_BUILD: run.build, HUB_DEVICE_NAME: deviceName(), ...(takeOver ? { HUB_RUNNER_TAKE_OVER: '1' } : {}) };
37
47
  return `<?xml version="1.0" encoding="UTF-8"?>
38
48
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
39
49
  <plist version="1.0">
@@ -42,8 +52,8 @@ export function plist({ takeOver }) {
42
52
  <string>${LABEL}</string>
43
53
  <key>ProgramArguments</key>
44
54
  <array>
45
- <string>${xml(process.execPath)}</string>
46
- <string>${xml(mainFile())}</string>
55
+ <string>${xml(run.node)}</string>
56
+ <string>${xml(run.main)}</string>
47
57
  </array>
48
58
  <key>WorkingDirectory</key>
49
59
  <string>${xml(runnerDir())}</string>
@@ -77,9 +87,11 @@ export function stop() {
77
87
  if (loaded()) bootout();
78
88
  }
79
89
 
80
- /** Starts the loaded job again, or loads it from the plist the last `start` wrote. */
90
+ /** Starts the loaded job again, or loads it from the plist the last `start` wrote. The app's install writes the plist
91
+ * again first, because its `HUB_RUNNER_BUILD` names the version `current` points at now. */
81
92
  export function kickstart() {
82
- if (loaded()) launchctl(['kickstart', '-k', `${domain()}/${LABEL}`]);
93
+ if (appHome()) start();
94
+ else if (loaded()) launchctl(['kickstart', '-k', `${domain()}/${LABEL}`]);
83
95
  else if (existsSync(plistFile())) launchctl(['bootstrap', domain(), plistFile()]);
84
96
  else throw new Error('not started yet: run `hub-runner start`');
85
97
  }
package/lib/paths.mjs CHANGED
@@ -10,3 +10,6 @@ export const logFile = () => join(runnerDir(), 'runner.log');
10
10
  export const plistFile = () => join(homedir(), 'Library', 'LaunchAgents', `${LABEL}.plist`);
11
11
  export const mainFile = () => new URL('../main.mjs', import.meta.url).pathname;
12
12
  export const version = () => JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
13
+ // The Hub app's own install (native/Sources/HubCore/RunnerInstall.swift): Node, pnpm and this package under the
14
+ // `current` symlink the app moves on each update, so the launchd job always runs the version the app installed last.
15
+ export const appHome = () => process.env.HUB_RUNNER_HOME || null;
package/main.mjs CHANGED
@@ -5005,6 +5005,7 @@ var deviceFile = join16(dir, "device-id");
5005
5005
  if (!existsSync11(deviceFile)) writeFileSync7(deviceFile, randomUUID());
5006
5006
  var device = readFileSync10(deviceFile, "utf8").trim();
5007
5007
  var credentials = process.env.HUB_URL || process.env.HUB_SESSION ? { hubUrl: need("HUB_URL"), session: need("HUB_SESSION"), bypass: process.env.HUB_PROTECTION_BYPASS || void 0 } : JSON.parse(readFileSync10(join16(dir, "credentials.json"), "utf8"));
5008
+ if ("workspace" in credentials && credentials.workspace) status("starting", { workspace: credentials.workspace });
5008
5009
  var deviceName = process.env.HUB_DEVICE_NAME || device;
5009
5010
  var started = await run3({
5010
5011
  hubUrl: credentials.hubUrl.replace(/\/$/, ""),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hub-runner",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Runs a hub workspace's Mac bots on this Mac under launchd, with no app needed.",
6
6
  "type": "module",