@rightkit/release 0.2.3 → 0.2.5

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": "@rightkit/release",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Portable Right Suite release CLI/SDK: signed installers, updater artifacts, patch/update routing, hardening, R2 publish, and RightApps registration.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,7 +37,6 @@ const installers = target?.installer?.artifacts ?? [];
37
37
 
38
38
  if (tier === "patch") {
39
39
  if (!installers.length) fail(`${config?.app ?? "app"} ${platform} patch has no installer.artifacts`);
40
- if (!artifacts.length) fail(`${config?.app ?? "app"} ${platform} patch has no updater.artifacts for the free app-update manifest`);
41
40
  for (const installer of installers) {
42
41
  assertCurrentKey(installer.key, "installer");
43
42
  const file = path.resolve(root, installer.file);
@@ -78,6 +77,10 @@ if (tier === "patch") {
78
77
  uploadedKeys.add(installer.key);
79
78
  }
80
79
  }
80
+ if (!artifacts.length) {
81
+ console.log(`${dryRun ? "[dry-run] " : ""}NO patch updater artifacts; skipping patch manifest registration`);
82
+ process.exit(0);
83
+ }
81
84
  const version = config.version || target.updater.version;
82
85
  if (!version) fail(`${config.app} config must expose version or targets.${platform}.updater.version`);
83
86
  const body = {
@@ -51,6 +51,23 @@ function versionedFixture() {
51
51
  return config;
52
52
  }
53
53
 
54
+ function installerOnlyFixture() {
55
+ const dir = mkdtempSync(path.join(os.tmpdir(), "right-publish-test-"));
56
+ const config = path.join(dir, "right-release.config.mjs");
57
+ writeFileSync(config, `export default ${JSON.stringify({
58
+ schema: 1,
59
+ app: "fixture",
60
+ version: "1.2.3",
61
+ targets: {
62
+ win: {
63
+ installer: { artifacts: [{ file: "Fixture-Setup.exe", key: "fixture/installers/windows/current/Fixture-Setup.exe" }] },
64
+ updater: { artifacts: [] },
65
+ },
66
+ },
67
+ })};\n`);
68
+ return config;
69
+ }
70
+
54
71
  function run(tier) {
55
72
  const config = fixture();
56
73
  return spawnSync(process.execPath, [publisher, "--config", config, "--platform", "win", "--dry-run"], {
@@ -85,6 +102,19 @@ test("routes feature updates to the Pro-gated release endpoint", () => {
85
102
  assert.doesNotMatch(result.stdout, /Fixture-Setup\.exe/);
86
103
  });
87
104
 
105
+ test("allows an installer-only patch without registering an updater manifest", () => {
106
+ const config = installerOnlyFixture();
107
+ const result = spawnSync(process.execPath, [publisher, "--config", config, "--platform", "win", "--dry-run"], {
108
+ encoding: "utf8",
109
+ env: { ...process.env, RIGHT_RELEASE_TIER: "patch" },
110
+ });
111
+ assert.equal(result.status, 0, result.stderr);
112
+ assert.match(result.stdout, /UPLOAD public\/fixture\/installers\/windows\/current\/Fixture-Setup\.exe/);
113
+ assert.match(result.stdout, /NO patch updater artifacts/);
114
+ assert.doesNotMatch(result.stdout, /\/v1\/admin\/apps\/patches/);
115
+ assert.doesNotMatch(result.stdout, /UPLOAD private\//);
116
+ });
117
+
88
118
  test("refuses to publish without a valid tier", () => {
89
119
  const result = run("");
90
120
  assert.notEqual(result.status, 0);
package/release.mjs CHANGED
@@ -9,11 +9,11 @@ const HARDENING_SCAN = path.resolve(TOOL_ROOT, "hardeningscan.mjs");
9
9
  const UPLOAD_LARGE = path.resolve(TOOL_ROOT, "upload-large.mjs");
10
10
  const SIGN_WINDOWS = path.resolve(TOOL_ROOT, "sign-windows.mjs");
11
11
  const SIGN_UPDATER = path.resolve(TOOL_ROOT, "sign-updater.mjs");
12
- const VERSION = "0.2.3";
12
+ const VERSION = "0.2.4";
13
13
  const TIERS = new Set(["patch", "update"]);
14
14
  const RIGHTKIT_EXPECTED = new Map([
15
- ["@rightkit/license", "^0.1.3"],
16
- ["@rightkit/logs", "^0.1.1"],
15
+ ["@rightkit/license", "^0.1.5"],
16
+ ["@rightkit/logs", "^0.1.2"],
17
17
  ["@rightkit/release", `^${VERSION}`],
18
18
  ]);
19
19
  const FORBIDDEN_RIGHTKIT_SPEC = /^(?:git|file|link|workspace):|github|github\.com/i;
package/release.test.mjs CHANGED
@@ -17,8 +17,8 @@ function fixture({ signed = true, publish = false, packageJson } = {}) {
17
17
  packageJson ?? {
18
18
  name: "fixture",
19
19
  scripts: { "release:patch:win": "right-release --platform win --tier patch" },
20
- dependencies: { "@rightkit/license": "^0.1.3", "@rightkit/logs": "^0.1.1" },
21
- devDependencies: { "@rightkit/release": "^0.2.3" },
20
+ dependencies: { "@rightkit/license": "^0.1.5", "@rightkit/logs": "^0.1.2" },
21
+ devDependencies: { "@rightkit/release": "^0.2.4" },
22
22
  },
23
23
  null,
24
24
  2,
@@ -6,9 +6,9 @@ import test from "node:test";
6
6
 
7
7
  const workspace = path.resolve(new URL("../..", import.meta.url).pathname.replace(/^\/(\w:)/, "$1"));
8
8
  const pubkey = "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDI5Mzk1RjlGRjQ2NjI2MUQKUldRZEptYjBuMTg1S1VSUXlBdFM4WmtzaHArYko0U2hRMDVlSDJmSExVZG82Q0hoQ2srUlhqanAK";
9
- const licensePackage = "^0.1.3";
10
- const logsPackage = "^0.1.1";
11
- const releasePackage = "^0.2.3";
9
+ const licensePackage = "^0.1.5";
10
+ const logsPackage = "^0.1.3";
11
+ const releasePackage = "^0.2.4";
12
12
  const apps = [
13
13
  { key: "viewright", root: "viewright", tauri: "src-tauri/tauri.conf.json", host: "viewright.cc" },
14
14
  { key: "scraperight", root: "scraperight", tauri: "src-tauri/tauri.conf.json", host: "scraperight.cc" },
@@ -54,8 +54,8 @@ for (const app of apps) {
54
54
  assert.equal(target.upload, undefined, "generic uploads bypass tier manifest routing");
55
55
  assert.equal(target.publish.cmd, "right-release");
56
56
  assert.match(target.publish.args.join(" "), /^publish-update\b/);
57
- assert.ok(target.updater.artifacts.length);
58
- assert.ok(target.installer.artifacts.length, "patch releases must refresh the public installer");
57
+ assert.ok(new Set(target.updater.artifacts.map((artifact) => artifact.key)).size <= 1, `${app.key} ${platform} must expose at most one current updater R2 object key`);
58
+ assert.ok(new Set(target.installer.artifacts.map((artifact) => artifact.key)).size <= 1, `${app.key} ${platform} must expose at most one current installer R2 object key`);
59
59
  for (const installer of target.installer.artifacts) {
60
60
  assert.match(installer.key, /\/installers\/(mac|windows)\/current\//, `${app.key} ${platform} installers must replace the stable current R2 object`);
61
61
  }