From 46127992ff26f9524664b518b445846c1bcfbb7c Mon Sep 17 00:00:00 2001 From: realDiligent Date: Thu, 9 Jul 2026 05:52:38 +0800 Subject: [PATCH 1/2] feat(miner): add GITTENSORY_MINER_VERSION build-time override (#4310) Co-authored-by: Cursor --- .../gittensory-miner/bin/gittensory-miner.js | 5 ++-- packages/gittensory-miner/lib/status.js | 11 ++------- packages/gittensory-miner/lib/version.js | 10 ++++++++ packages/gittensory-miner/package.json | 2 +- test/unit/miner-package-skeleton.test.ts | 5 ++++ test/unit/miner-status.test.ts | 11 +++++++++ test/unit/miner-version.test.ts | 23 +++++++++++++++++++ 7 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 packages/gittensory-miner/lib/version.js create mode 100644 test/unit/miner-version.test.ts diff --git a/packages/gittensory-miner/bin/gittensory-miner.js b/packages/gittensory-miner/bin/gittensory-miner.js index 0f008c1d2e..3105ae8114 100755 --- a/packages/gittensory-miner/bin/gittensory-miner.js +++ b/packages/gittensory-miner/bin/gittensory-miner.js @@ -1,5 +1,4 @@ #!/usr/bin/env node -import { createRequire } from "node:module"; import { printHelp, printVersion, runCli } from "../lib/cli.js"; import { runDenyCheck } from "../lib/deny-check.js"; import { runGovernorCli } from "../lib/governor-ledger-cli.js"; @@ -16,6 +15,7 @@ import { resolveUpgradeCommand, startUpdateCheck, } from "../lib/update-check.js"; +import { resolveMinerVersion } from "../lib/version.js"; const cliArgs = process.argv.slice(2); @@ -54,9 +54,8 @@ if (cliArgs[0] === "governor") { process.exit(await runGovernorCli(cliArgs[1], cliArgs.slice(2))); } -const require = createRequire(import.meta.url); const packageName = "@jsonbored/gittensory-miner"; -const packageVersion = require("../package.json").version; +const packageVersion = resolveMinerVersion(process.env); const upgradeCommand = resolveUpgradeCommand(packageName); const updateCheck = startUpdateCheck(cliArgs, { diff --git a/packages/gittensory-miner/lib/status.js b/packages/gittensory-miner/lib/status.js index 76e0f9cc5f..fbe1f286cc 100644 --- a/packages/gittensory-miner/lib/status.js +++ b/packages/gittensory-miner/lib/status.js @@ -3,6 +3,7 @@ import { createRequire } from "node:module"; import { homedir } from "node:os"; import { join } from "node:path"; import { checkDockerPresent, checkLaptopStateSqlite } from "./laptop-init.js"; +import { resolveMinerVersion } from "./version.js"; // Slim laptop-mode CLI commands (#2288): `status` (what's installed + where local state lives) and `doctor` (is // this laptop set up correctly). Both are read-only and 100% local — no repo-scanning, no coding-agent invocation, @@ -33,14 +34,6 @@ export function resolveMinerStateDir(env = process.env) { return join(configHome, "gittensory-miner"); } -function readOwnVersion() { - try { - return require("../package.json").version ?? null; - } catch { - return null; - } -} - // The pinned @jsonbored/gittensory-engine version this miner is built against, read from the miner's own declared // dependency. (The engine package's `exports` map blocks `require("/package.json")`, and its built `dist` may // be absent depending on build order, so the declared-dependency version is the reliable, always-available source.) @@ -71,7 +64,7 @@ function discoverConfigFile(cwd) { export function collectStatus(env = process.env, cwd = process.cwd()) { const stateDir = resolveMinerStateDir(env); return { - package: { name: PACKAGE_NAME, version: readOwnVersion() }, + package: { name: PACKAGE_NAME, version: resolveMinerVersion(env) }, engine: { name: ENGINE_PACKAGE, version: readEngineVersion() }, node: process.version, stateDir, diff --git a/packages/gittensory-miner/lib/version.js b/packages/gittensory-miner/lib/version.js new file mode 100644 index 0000000000..eb4d31aa5a --- /dev/null +++ b/packages/gittensory-miner/lib/version.js @@ -0,0 +1,10 @@ +import ownPackageJson from "../package.json" with { type: "json" }; + +/** Package.json semver at import time — the laptop npm-install default. */ +export const MINER_PACKAGE_VERSION = ownPackageJson.version; + +/** Resolved miner release id: `GITTENSORY_MINER_VERSION` wins when set (fleet Docker image builds). */ +export function resolveMinerVersion(env = process.env) { + const override = typeof env.GITTENSORY_MINER_VERSION === "string" ? env.GITTENSORY_MINER_VERSION.trim() : ""; + return override || MINER_PACKAGE_VERSION; +} diff --git a/packages/gittensory-miner/package.json b/packages/gittensory-miner/package.json index f05833fcc8..ae2c366a7f 100644 --- a/packages/gittensory-miner/package.json +++ b/packages/gittensory-miner/package.json @@ -31,7 +31,7 @@ "lib" ], "scripts": { - "build": "node --check bin/gittensory-miner.js && node --check lib/cli.js && node --check lib/deny-check.js && node --check lib/run-state-cli.js && node --check lib/update-check.js && node --check lib/opportunity-fanout.js && node --check lib/ci-poller.js && node --check lib/run-state.js && node --check lib/deny-hooks.js && node --check lib/event-ledger.js && node --check lib/event-ledger-cli.js && node --check lib/claim-ledger.js && node --check lib/claim-ledger-expiry.js && node --check lib/portfolio-queue.js && node --check lib/portfolio-queue-cli.js && node --check lib/portfolio-discovery.js && node --check lib/opportunity-ranker.js && node --check lib/plan-store.js && node --check lib/plan-store-cli.js && node --check lib/rejection-templates.js && node --check lib/governor-ledger.js && node --check lib/governor-ledger-cli.js && node --check lib/manage-status.js && node --check lib/manage-poll.js && node --check lib/status.js && node --check lib/laptop-init.js && node --check lib/replay-objective-anchor.js && node --check lib/replay-task-generation.js && node --check lib/calibration-types.js && node --check lib/calibration.js" + "build": "node --check bin/gittensory-miner.js && node --check lib/version.js && node --check lib/cli.js && node --check lib/deny-check.js && node --check lib/run-state-cli.js && node --check lib/update-check.js && node --check lib/opportunity-fanout.js && node --check lib/ci-poller.js && node --check lib/run-state.js && node --check lib/deny-hooks.js && node --check lib/event-ledger.js && node --check lib/event-ledger-cli.js && node --check lib/claim-ledger.js && node --check lib/claim-ledger-expiry.js && node --check lib/portfolio-queue.js && node --check lib/portfolio-queue-cli.js && node --check lib/portfolio-discovery.js && node --check lib/opportunity-ranker.js && node --check lib/plan-store.js && node --check lib/plan-store-cli.js && node --check lib/rejection-templates.js && node --check lib/governor-ledger.js && node --check lib/governor-ledger-cli.js && node --check lib/manage-status.js && node --check lib/manage-poll.js && node --check lib/status.js && node --check lib/laptop-init.js && node --check lib/replay-objective-anchor.js && node --check lib/replay-task-generation.js && node --check lib/calibration-types.js && node --check lib/calibration.js" }, "dependencies": { "@jsonbored/gittensory-engine": ">=0.1.0 <1.0.0" diff --git a/test/unit/miner-package-skeleton.test.ts b/test/unit/miner-package-skeleton.test.ts index 95740f8329..e3a1d001b8 100644 --- a/test/unit/miner-package-skeleton.test.ts +++ b/test/unit/miner-package-skeleton.test.ts @@ -62,6 +62,11 @@ describe("gittensory-miner package skeleton (#2287)", () => { it("serves --help and --version from the bin entry", () => { expect(runCapture(["--help", "--no-update-check"])).toContain("gittensory-miner --help"); expect(runCapture(["--version", "--no-update-check"])).toContain("@jsonbored/gittensory-miner/"); + expect( + runCapture(["--version", "--no-update-check"], { + GITTENSORY_MINER_VERSION: "gittensory-miner-fleet@abc1234", + }), + ).toContain("gittensory-miner-fleet@abc1234"); }); it("documents foundation scope and local checkout install paths in the README", () => { diff --git a/test/unit/miner-status.test.ts b/test/unit/miner-status.test.ts index f7537cbebc..4ce4bb0ca7 100644 --- a/test/unit/miner-status.test.ts +++ b/test/unit/miner-status.test.ts @@ -43,6 +43,17 @@ describe("gittensory-miner status/doctor (#2288)", () => { expect(status.configFile).toBe(join(root, ".gittensory-miner.yml")); // discovered }); + it("collectStatus prefers GITTENSORY_MINER_VERSION over package.json (#4310)", () => { + const status = collectStatus( + { + GITTENSORY_MINER_CONFIG_DIR: "/s", + GITTENSORY_MINER_VERSION: "gittensory-miner-fleet@deadbeef", + }, + tempRoot(), + ); + expect(status.package.version).toBe("gittensory-miner-fleet@deadbeef"); + }); + it("runStatus prints human-readable text (0) and machine JSON with --json", () => { const log = vi.spyOn(console, "log").mockImplementation(() => {}); expect(runStatus([], { GITTENSORY_MINER_CONFIG_DIR: "/s" }, tempRoot())).toBe(0); diff --git a/test/unit/miner-version.test.ts b/test/unit/miner-version.test.ts new file mode 100644 index 0000000000..d239f7758e --- /dev/null +++ b/test/unit/miner-version.test.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest"; +import { + MINER_PACKAGE_VERSION, + resolveMinerVersion, +} from "../../packages/gittensory-miner/lib/version.js"; + +describe("gittensory-miner version resolution (#4310)", () => { + it("defaults to the package.json semver when GITTENSORY_MINER_VERSION is unset", () => { + expect(MINER_PACKAGE_VERSION).toMatch(/^\d+\.\d+\.\d+$/); + expect(resolveMinerVersion({})).toBe(MINER_PACKAGE_VERSION); + expect(resolveMinerVersion({ GITTENSORY_MINER_VERSION: "" })).toBe(MINER_PACKAGE_VERSION); + expect(resolveMinerVersion({ GITTENSORY_MINER_VERSION: " " })).toBe(MINER_PACKAGE_VERSION); + }); + + it("prefers a nonblank GITTENSORY_MINER_VERSION override (fleet Docker build ref)", () => { + expect( + resolveMinerVersion({ GITTENSORY_MINER_VERSION: "gittensory-miner-fleet@abc1234" }), + ).toBe("gittensory-miner-fleet@abc1234"); + expect( + resolveMinerVersion({ GITTENSORY_MINER_VERSION: " 0.9.0-beta.1 " }), + ).toBe("0.9.0-beta.1"); + }); +}); From b2e76f4922bd41898db87a9942c14e674de7d6a8 Mon Sep 17 00:00:00 2001 From: realDiligent Date: Thu, 9 Jul 2026 05:58:30 +0800 Subject: [PATCH 2/2] fix(miner): add version.d.ts for typecheck (#4310) Co-authored-by: Cursor --- packages/gittensory-miner/lib/version.d.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/gittensory-miner/lib/version.d.ts diff --git a/packages/gittensory-miner/lib/version.d.ts b/packages/gittensory-miner/lib/version.d.ts new file mode 100644 index 0000000000..1b7404ce8e --- /dev/null +++ b/packages/gittensory-miner/lib/version.d.ts @@ -0,0 +1,3 @@ +export const MINER_PACKAGE_VERSION: string; + +export function resolveMinerVersion(env?: Record): string;