@rightkit/release 0.2.137 → 0.2.139
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/README.md +11 -0
- package/build-release.mjs +30 -21
- package/cache-policy.mjs +14 -0
- package/cli/right-release.mjs +4 -1
- package/committed-source.mjs +1 -1
- package/development.mjs +2 -2
- package/inventory-check.mjs +1 -1
- package/managed-cargo.mjs +13 -3
- package/msix-appinstaller.mjs +24 -0
- package/msix-build.mjs +164 -0
- package/msix-config.mjs +70 -0
- package/msix-plan.mjs +68 -0
- package/msix-target.mjs +28 -0
- package/ownership-admission.mjs +125 -0
- package/ownership-approval.mjs +3 -0
- package/ownership-internal-owners.json +0 -35
- package/ownership-key-command.mjs +13 -4
- package/ownership-key-elevation.mjs +124 -0
- package/ownership-repositories.json +3 -1
- package/ownership.mjs +2 -2
- package/package.json +3 -3
- package/pe-imports.mjs +59 -0
- package/preflight.mjs +37 -23
- package/project-type.mjs +43 -0
- package/publish-update.mjs +11 -5
- package/release-invocation.mjs +8 -6
- package/release.mjs +30 -6
- package/rightkit-ownership.json +0 -35
- package/rightkit-sync.mjs +2 -5
- package/rightkit-versions.json +14 -8
- package/swift-build-context.mjs +43 -0
- package/swift-mac-app.mjs +146 -0
- package/swift-package-command.mjs +85 -0
- package/swift-windows-stage.mjs +103 -0
package/preflight.mjs
CHANGED
|
@@ -23,6 +23,7 @@ import path from "node:path";
|
|
|
23
23
|
import { spawnSync } from "./background-process.mjs";
|
|
24
24
|
import { brokerManagedHost } from "./cargo-contract.mjs";
|
|
25
25
|
import { createOwnershipEvidence } from "./ownership-evidence.mjs";
|
|
26
|
+
import { isSwiftProject } from "./project-type.mjs";
|
|
26
27
|
|
|
27
28
|
export const PREFLIGHT_OK = "ok";
|
|
28
29
|
export const PREFLIGHT_WARN = "warn";
|
|
@@ -179,11 +180,24 @@ export function collectPreflight({
|
|
|
179
180
|
isBrokerManagedHost = brokerManagedHost,
|
|
180
181
|
ownership = true,
|
|
181
182
|
ownershipEvidenceFactory = createOwnershipEvidence,
|
|
183
|
+
projectType,
|
|
184
|
+
msix = false,
|
|
185
|
+
findSdkTool = findWindowsSdkTool,
|
|
182
186
|
} = {}) {
|
|
183
187
|
const checks = [];
|
|
184
188
|
const windows = platform === "win" || platform === "win32";
|
|
189
|
+
const swift = isSwiftProject(projectType);
|
|
185
190
|
|
|
186
|
-
if (
|
|
191
|
+
if (swift) {
|
|
192
|
+
const swiftVersion = versionProbe("swift");
|
|
193
|
+
checks.push(
|
|
194
|
+
swiftVersion
|
|
195
|
+
? ok("swift", swiftVersion)
|
|
196
|
+
: fail("swift", "swift was not found on PATH; SwiftPM apps build with the Swift toolchain", "install the pinned Swift toolchain (swift.org / Swift on Windows) and verify: swift --version"),
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (appRoot && !swift) {
|
|
187
201
|
const target = targetLink ?? nativeLayout?.targetLink ?? path.join(appRoot, "src-tauri", "target");
|
|
188
202
|
const targetLabel = nativeLayout?.targetPrefix || "src-tauri/target/";
|
|
189
203
|
let entry = null;
|
|
@@ -225,29 +239,27 @@ export function collectPreflight({
|
|
|
225
239
|
}
|
|
226
240
|
|
|
227
241
|
if (windows) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
makeappx
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
242
|
+
// makeappx/signtool are MSIX requirements; NSIS/portable targets sign through sign-windows.
|
|
243
|
+
if (msix) {
|
|
244
|
+
const makeappx = process.env.MAKEAPPX_PATH ? { version: "MAKEAPPX_PATH" } : findSdkTool("makeappx.exe");
|
|
245
|
+
checks.push(
|
|
246
|
+
makeappx
|
|
247
|
+
? ok("windows-sdk", `makeappx.exe from SDK ${makeappx.version}`)
|
|
248
|
+
: fail(
|
|
249
|
+
"windows-sdk",
|
|
250
|
+
"msix target configured but no makeappx.exe found under any installed Windows 10/11 SDK",
|
|
251
|
+
"install the Windows SDK, or set MAKEAPPX_PATH to an explicit makeappx.exe",
|
|
252
|
+
),
|
|
253
|
+
);
|
|
254
|
+
}
|
|
238
255
|
|
|
239
|
-
const signtool =
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
"signtool",
|
|
245
|
-
"no signtool.exe found under any installed Windows SDK",
|
|
246
|
-
"install the Windows SDK Build Tools, or set AZURE_SIGNTOOL_PATH",
|
|
247
|
-
),
|
|
248
|
-
);
|
|
256
|
+
const signtool = findSdkTool("signtool.exe");
|
|
257
|
+
const signtoolMissing = "install the Windows SDK Build Tools, or set AZURE_SIGNTOOL_PATH";
|
|
258
|
+
if (signtool) checks.push(ok("signtool", `signtool.exe from SDK ${signtool.version}`));
|
|
259
|
+
else if (msix) checks.push(fail("signtool", "msix target configured but no signtool.exe found under any installed Windows SDK", signtoolMissing));
|
|
260
|
+
else checks.push(warn("signtool", "no signtool.exe found under any installed Windows SDK", signtoolMissing));
|
|
249
261
|
|
|
250
|
-
const vendorsOpenssl = cargoLockPaths.some((lockPath) => graphVendorsOpenssl(lockPath));
|
|
262
|
+
const vendorsOpenssl = !swift && cargoLockPaths.some((lockPath) => graphVendorsOpenssl(lockPath));
|
|
251
263
|
if (vendorsOpenssl) {
|
|
252
264
|
const perl = resolveWindowsPerl({ env });
|
|
253
265
|
checks.push(
|
|
@@ -262,7 +274,9 @@ export function collectPreflight({
|
|
|
262
274
|
}
|
|
263
275
|
}
|
|
264
276
|
|
|
265
|
-
if (
|
|
277
|
+
if (swift) {
|
|
278
|
+
// No Rust compiler cache applies to SwiftPM targets.
|
|
279
|
+
} else if (isBrokerManagedHost(env)) {
|
|
266
280
|
checks.push(ok("compiler-cache", "broker-managed; compiler-cache selection and status are recorded in build receipts"));
|
|
267
281
|
} else {
|
|
268
282
|
const sccache = versionProbe("sccache");
|
package/project-type.mjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Project-type awareness for release preflight: which toolchain a target needs.
|
|
2
|
+
// Pure; filesystem access is injectable. Swift (SwiftPM) apps need `swift`, not
|
|
3
|
+
// cargo/rustc; Tauri/Rust targets keep their existing requirements.
|
|
4
|
+
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
|
|
8
|
+
export const PROJECT_TYPES = Object.freeze(["tauri", "cargo", "swiftpm"]);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Explicit `target.projectType` / `config.projectType` wins. Otherwise a Package.swift with no Cargo
|
|
12
|
+
* manifest (root or src-tauri) is swiftpm; everything else is tauri/cargo (unchanged behaviour).
|
|
13
|
+
*/
|
|
14
|
+
export function resolveProjectType({ appRoot, config = {}, target = {}, exists = existsSync } = {}) {
|
|
15
|
+
const explicit = target.projectType ?? config.projectType;
|
|
16
|
+
if (explicit !== undefined) {
|
|
17
|
+
if (!PROJECT_TYPES.includes(explicit)) throw Object.assign(new Error(`projectType must be one of ${PROJECT_TYPES.join(", ")}; got ${explicit}`), { code: "PROJECT_TYPE_INVALID" });
|
|
18
|
+
return explicit;
|
|
19
|
+
}
|
|
20
|
+
if (appRoot) {
|
|
21
|
+
const roots = [appRoot, path.resolve(appRoot, config.workdir ?? ".")];
|
|
22
|
+
const hasSwift = roots.some((r) => exists(path.join(r, "Package.swift")));
|
|
23
|
+
const hasCargo = roots.some((r) => exists(path.join(r, "Cargo.toml")) || exists(path.join(r, "src-tauri", "Cargo.toml")));
|
|
24
|
+
if (hasSwift && !hasCargo) return "swiftpm";
|
|
25
|
+
}
|
|
26
|
+
return "tauri";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const isSwiftProject = (projectType) => projectType === "swiftpm";
|
|
30
|
+
|
|
31
|
+
/** Executables the build itself needs (the config's own preflight.executables are appended by callers). */
|
|
32
|
+
export function requiredBuildExecutables({ projectType, packageManager = "pnpm", usesPackageManager = true } = {}) {
|
|
33
|
+
if (isSwiftProject(projectType)) return ["git", "swift", ...(usesPackageManager && packageManager ? [packageManager] : [])];
|
|
34
|
+
return ["git", packageManager, "cargo", "rustc"];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** True when the Windows target packages an MSIX (needs makeappx and signtool). */
|
|
38
|
+
export function targetUsesMsix(target) {
|
|
39
|
+
return Boolean(target?.msix) || target?.signingContract === "windows-msix-signed-v1";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** SwiftPM targets build and package inside prePackage (mac DMG) or the MSIX step; no separate `package` command is required. */
|
|
43
|
+
export const packageCommandOptional = (target, projectType) => targetUsesMsix(target) || (projectType === "swiftpm" && Boolean(target?.prePackage?.cmd));
|
package/publish-update.mjs
CHANGED
|
@@ -75,6 +75,12 @@ const artifactFile = (declared) => {
|
|
|
75
75
|
return artifact.file;
|
|
76
76
|
};
|
|
77
77
|
const verifiedArtifact = (file) => sealed.artifacts.get(path.basename(file));
|
|
78
|
+
// MSIX updates (updater.kind appinstaller) trust the package Authenticode signature (publisher-pinned in
|
|
79
|
+
// the manifest), so no minisign .sig exists; the route records the sealed package digest instead.
|
|
80
|
+
const appInstallerKind = target?.updater?.kind === "appinstaller";
|
|
81
|
+
const signatureFor = (artifact) => appInstallerKind
|
|
82
|
+
? `msix-authenticode-sha256:${assertArtifactUnchanged(verifiedArtifact(artifact.file)) && verifiedArtifact(artifact.file).sha256}`
|
|
83
|
+
: signatureText(artifactFile(artifact.signature));
|
|
78
84
|
const signatureText = (file) => {
|
|
79
85
|
const signature = assertArtifactUnchanged(verifiedArtifact(file)).toString("utf8").trim();
|
|
80
86
|
if (!signature) throw new PublicationError("PUBLICATION_SIGNATURE_MISSING", `sealed updater signature is empty: ${file}`);
|
|
@@ -89,7 +95,7 @@ function git(args) {
|
|
|
89
95
|
if (tier === "patch" && !installers.length) fail(`${config?.app ?? "app"} ${platform} patch has no installer.artifacts`);
|
|
90
96
|
if (tier === "update" && !artifacts.length) fail(`${config?.app ?? "app"} ${platform} update has no updater.artifacts`);
|
|
91
97
|
|
|
92
|
-
if (sealed) for (const artifact of artifacts)
|
|
98
|
+
if (sealed) for (const artifact of artifacts) signatureFor(artifact);
|
|
93
99
|
let releaseToken = null;
|
|
94
100
|
if (!dryRun && (tier === "update" || artifacts.length > 0)) {
|
|
95
101
|
try {
|
|
@@ -114,13 +120,13 @@ if (tier === "patch") {
|
|
|
114
120
|
const installerKey = patchInstallerKey(artifact);
|
|
115
121
|
assertCurrentKey(installerKey, "installer");
|
|
116
122
|
const file = artifactFile(artifact.file);
|
|
117
|
-
|
|
123
|
+
if (!appInstallerKind) artifactFile(artifact.signature);
|
|
118
124
|
if (!uploadedKeys.has(installerKey)) {
|
|
119
125
|
console.log(`${dryRun ? "[dry-run] " : ""}UPLOAD public/${installerKey}`);
|
|
120
126
|
if (!dryRun) uploadVerifiedR2Artifact(verifiedArtifact(file), installerKey, "public", { cwd: root });
|
|
121
127
|
uploadedKeys.add(installerKey);
|
|
122
128
|
}
|
|
123
|
-
const signature = dryRun ? `<signature:${artifact.signature}>` :
|
|
129
|
+
const signature = dryRun ? `<signature:${artifact.signature ?? "msix-authenticode"}>` : signatureFor(artifact);
|
|
124
130
|
const artifactKey = artifact.artifactKey || installerKey.replaceAll("/", "__");
|
|
125
131
|
const metadata = dryRun ? { sha256: null, sizeBytes: null } : await fileMetadata(file);
|
|
126
132
|
platforms[artifact.platform] = {
|
|
@@ -210,13 +216,13 @@ const uploadedKeys = new Set();
|
|
|
210
216
|
for (const artifact of artifacts) {
|
|
211
217
|
assertCurrentKey(artifact.key, "updater");
|
|
212
218
|
const file = artifactFile(artifact.file);
|
|
213
|
-
|
|
219
|
+
if (!appInstallerKind) artifactFile(artifact.signature);
|
|
214
220
|
if (!uploadedKeys.has(artifact.key)) {
|
|
215
221
|
console.log(`${dryRun ? "[dry-run] " : ""}UPLOAD private/${artifact.key}`);
|
|
216
222
|
if (!dryRun) uploadVerifiedR2Artifact(verifiedArtifact(file), artifact.key, "private", { cwd: root });
|
|
217
223
|
uploadedKeys.add(artifact.key);
|
|
218
224
|
}
|
|
219
|
-
const signature = dryRun ? `<signature:${artifact.signature}>` :
|
|
225
|
+
const signature = dryRun ? `<signature:${artifact.signature ?? "msix-authenticode"}>` : signatureFor(artifact);
|
|
220
226
|
const artifactKey = artifact.artifactKey || artifact.key.replaceAll("/", "__");
|
|
221
227
|
const metadata = dryRun ? { sha256: null, sizeBytes: null } : await fileMetadata(file);
|
|
222
228
|
platforms[artifact.platform] = {
|
package/release-invocation.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawnSync } from "./background-process.mjs";
|
|
2
|
+
import { resolveProjectType } from "./project-type.mjs";
|
|
2
3
|
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { resolveNativeCargoLayout } from "./native-cargo-layout.mjs";
|
|
@@ -128,18 +129,19 @@ export function resolveConfiguredBuildInputs(config, target, label = "release co
|
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
export function resolveReleaseBuildInputs({ repoRoot, appRoot, configPath, config, target, env = process.env }) {
|
|
132
|
+
const swift = resolveProjectType({ appRoot, config, target }) === "swiftpm";
|
|
131
133
|
const nativeLayout = resolveNativeCargoLayout({
|
|
132
134
|
appRoot,
|
|
133
135
|
config,
|
|
134
|
-
requireManifest:
|
|
135
|
-
requireLock:
|
|
136
|
+
requireManifest: !swift,
|
|
137
|
+
requireLock: !swift,
|
|
136
138
|
});
|
|
137
139
|
const requiredInputs = [
|
|
138
140
|
configPath,
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
...(swift
|
|
142
|
+
// SwiftPM: Package.swift is required; Package.resolved and the Node manifests only when they exist.
|
|
143
|
+
? [path.join(appRoot, "Package.swift"), ...["Package.resolved", "package.json", "pnpm-lock.yaml"].map((f) => path.join(appRoot, f)).filter((f) => existsSync(f))]
|
|
144
|
+
: [path.join(appRoot, "package.json"), path.join(appRoot, "pnpm-lock.yaml"), nativeLayout.manifestPath, nativeLayout.lockPath]),
|
|
143
145
|
...(target?.preflight?.files ?? []).map((file) => path.resolve(appRoot, expandEnv(file, env))),
|
|
144
146
|
].filter((file, index, files) => files.indexOf(file) === index);
|
|
145
147
|
for (const file of requiredInputs) {
|
package/release.mjs
CHANGED
|
@@ -17,6 +17,10 @@ import {
|
|
|
17
17
|
resolveNativeFinalizerConfig,
|
|
18
18
|
validateNativeFinalizationOutput,
|
|
19
19
|
} from "./native-release-finalization.mjs";
|
|
20
|
+
import { packageCommandOptional, resolveProjectType, targetUsesMsix } from "./project-type.mjs";
|
|
21
|
+
import { MSIX_SIGNING_CONTRACT, assertValidMsixTarget } from "./msix-config.mjs";
|
|
22
|
+
import { buildMsix } from "./msix-build.mjs";
|
|
23
|
+
import { msixBuildOptions } from "./msix-target.mjs";
|
|
20
24
|
import { collectPreflight, formatPreflight, preflightFailures } from "./preflight.mjs";
|
|
21
25
|
import { patchTauriBundleType } from "./tauri-bundle-marker.mjs";
|
|
22
26
|
import { verifyNsisEmbeddedBinary } from "./nsis-payload.mjs";
|
|
@@ -118,7 +122,10 @@ const workdir = path.resolve(root, config.workdir ?? ".");
|
|
|
118
122
|
const nativeLayout = resolveNativeCargoLayout({ appRoot: root, config });
|
|
119
123
|
const nativeAssembly = config.nativeAssembly;
|
|
120
124
|
const nativeFinalizer = resolveNativeFinalizerConfig(nativeAssembly);
|
|
121
|
-
|
|
125
|
+
// A SwiftPM app without a package.json has no Node package contract to validate.
|
|
126
|
+
if (!(resolveProjectType({ appRoot: root, config, target: config.targets?.[opts.platform] }) === "swiftpm" && !existsSync(path.join(root, "package.json")))) {
|
|
127
|
+
await validateRightKitPackageContract(root, config.app, config.hostedWorkflows);
|
|
128
|
+
}
|
|
122
129
|
validateRightKitCargoContract(root, RIGHTKIT_CARGO_ALLOWED, config.app ?? path.basename(root));
|
|
123
130
|
const target = config.targets?.[opts.platform];
|
|
124
131
|
if (!target) fail(`${config.app ?? "app"} has no ${opts.platform} release target`);
|
|
@@ -131,13 +138,18 @@ if (target.signed !== true) {
|
|
|
131
138
|
if (opts.platform === "win") {
|
|
132
139
|
const isNsis = target.signingContract === WINDOWS_NSIS_SIGNING_CONTRACT;
|
|
133
140
|
const isPortable = target.signingContract === WINDOWS_PORTABLE_SIGNING_CONTRACT;
|
|
134
|
-
|
|
141
|
+
const isMsix = target.signingContract === MSIX_SIGNING_CONTRACT;
|
|
142
|
+
if (!isNsis && !isPortable && !isMsix) fail(`${config.app ?? "app"} win must declare signingContract: ${WINDOWS_NSIS_SIGNING_CONTRACT}, ${WINDOWS_PORTABLE_SIGNING_CONTRACT} or ${MSIX_SIGNING_CONTRACT}`);
|
|
143
|
+
if (isMsix) {
|
|
144
|
+
try { assertValidMsixTarget(target, config.app ?? "app"); } catch (error) { fail(error.message); }
|
|
145
|
+
} else {
|
|
135
146
|
if (!target.prePackage?.cmd) fail(`${config.app ?? "app"} win must declare prePackage for the raw EXE build`);
|
|
136
147
|
if (!target.sign?.prePackageFiles?.length) fail(`${config.app ?? "app"} win must declare at least one sign.prePackageFiles raw EXE`);
|
|
137
148
|
if (isNsis && target.sign.prePackageFiles.length !== 1) fail(`${config.app ?? "app"} win NSIS must declare exactly one sign.prePackageFiles raw EXE`);
|
|
138
149
|
if (isNsis && !target.sign?.files?.length) fail(`${config.app ?? "app"} win NSIS must declare sign.files for installer signing`);
|
|
139
150
|
if (isNsis && target.sign.prePackageFiles.some((file) => target.sign.files.includes(file))) fail(`${config.app ?? "app"} win raw EXE and installer signing files must be distinct`);
|
|
140
151
|
if (isPortable && target.sign?.files?.length) fail(`${config.app ?? "app"} win portable release must sign every executable through sign.prePackageFiles and omit sign.files`);
|
|
152
|
+
}
|
|
141
153
|
}
|
|
142
154
|
if (opts.platform === "mac") {
|
|
143
155
|
if (target.signingContract !== MACOS_PORTABLE_SIGNING_CONTRACT) fail(`${config.app ?? "app"} mac must declare signingContract: ${MACOS_PORTABLE_SIGNING_CONTRACT}`);
|
|
@@ -150,7 +162,7 @@ if (opts.upload && target.publishBlocked) fail(`${config.app ?? "app"} ${opts.pl
|
|
|
150
162
|
* Assemble preflight inputs from the app's own files. Kept here (not in
|
|
151
163
|
* preflight.mjs) so the check module stays free of release.mjs's config shape.
|
|
152
164
|
*/
|
|
153
|
-
function releasePreflight({ config, configPath, root, repoRoot, platform, nativeLayout: suppliedNativeLayout = nativeLayout }) {
|
|
165
|
+
function releasePreflight({ config, configPath, root, repoRoot, platform, nativeLayout: suppliedNativeLayout = nativeLayout, projectTarget = config.targets?.[platform] }) {
|
|
154
166
|
let version;
|
|
155
167
|
try {
|
|
156
168
|
version = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8")).version;
|
|
@@ -173,6 +185,8 @@ function releasePreflight({ config, configPath, root, repoRoot, platform, native
|
|
|
173
185
|
cargoLockPaths,
|
|
174
186
|
nativeLayout: suppliedNativeLayout,
|
|
175
187
|
targetLink: suppliedNativeLayout?.targetLink,
|
|
188
|
+
projectType: resolveProjectType({ appRoot: root, config, target: projectTarget }),
|
|
189
|
+
msix: targetUsesMsix(projectTarget),
|
|
176
190
|
});
|
|
177
191
|
}
|
|
178
192
|
|
|
@@ -234,7 +248,7 @@ if (opts.doctor) {
|
|
|
234
248
|
const releaseLock = acquireReleaseLock(root, config.app ?? path.basename(root), opts.platform, opts.tier);
|
|
235
249
|
const mode = "package";
|
|
236
250
|
const command = target.package;
|
|
237
|
-
if (!command) fail(`${config.app ?? "app"} has no ${opts.platform} ${mode} command`);
|
|
251
|
+
if (!command && !packageCommandOptional(target, resolveProjectType({ appRoot: root, config, target }))) fail(`${config.app ?? "app"} has no ${opts.platform} ${mode} command`);
|
|
238
252
|
if (opts.upload && !target.publish && !target.upload) {
|
|
239
253
|
fail(`${config.app ?? "app"} has no ${opts.platform} upload config`);
|
|
240
254
|
}
|
|
@@ -255,7 +269,17 @@ await runConfiguredChecks({
|
|
|
255
269
|
|
|
256
270
|
let nativeFinalization = null;
|
|
257
271
|
let bundleMarkerReceipts = [];
|
|
258
|
-
if (opts.platform === "win") {
|
|
272
|
+
if (opts.platform === "win" && target.signingContract === MSIX_SIGNING_CONTRACT) {
|
|
273
|
+
// MSIX order: prePackage builds + stages the payload; buildMsix signs inner PE files (DLLs, EXEs),
|
|
274
|
+
// packs the exact signed bytes, signs the package through sign-windows, verifies signer == Publisher,
|
|
275
|
+
// writes the App Installer route and the seal record. Never a second signer.
|
|
276
|
+
await runCommand(target.prePackage, root);
|
|
277
|
+
const options = msixBuildOptions({ root, target, app: config.app, dryRun: opts.dryRun, receipts: {
|
|
278
|
+
pe: windowsReceiptPath(root, "raw-exe"), msix: windowsReceiptPath(root, "installer"),
|
|
279
|
+
dir: path.dirname(windowsReceiptPath(root, "raw-exe")) } });
|
|
280
|
+
const built = buildMsix(options, { log: (event) => console.log(`right-release: ${JSON.stringify(event)}`) });
|
|
281
|
+
console.log(`right-release: msix ${built.dryRun ? "dry-run" : "built"} ${options.out}`);
|
|
282
|
+
} else if (opts.platform === "win") {
|
|
259
283
|
const rawFiles = target.sign.prePackageFiles.map((p) => path.resolve(root, p));
|
|
260
284
|
await runCommand(target.prePackage, root);
|
|
261
285
|
for (const file of rawFiles) await mustExist(file, `missing raw EXE signing artifact: ${file}`);
|
|
@@ -300,7 +324,7 @@ if (opts.platform === "win") {
|
|
|
300
324
|
}
|
|
301
325
|
}
|
|
302
326
|
|
|
303
|
-
if (opts.platform !== "mac" || runMacPhase("package")) await runCommand(command, root);
|
|
327
|
+
if (command && (opts.platform !== "mac" || runMacPhase("package"))) await runCommand(command, root);
|
|
304
328
|
|
|
305
329
|
for (const rel of target.artifacts ?? []) {
|
|
306
330
|
await mustExist(resolveReleaseArtifactPath(root, rel), `missing release artifact: ${rel}`);
|
package/rightkit-ownership.json
CHANGED
|
@@ -2348,45 +2348,10 @@
|
|
|
2348
2348
|
}
|
|
2349
2349
|
],
|
|
2350
2350
|
"internalOwners": [
|
|
2351
|
-
{
|
|
2352
|
-
"package": "@rightkit/build-control-broker",
|
|
2353
|
-
"path": "packages/build-control-broker/package.json",
|
|
2354
|
-
"reason": "Private build-control infrastructure; not an application capability"
|
|
2355
|
-
},
|
|
2356
|
-
{
|
|
2357
|
-
"package": "@rightkit/build-control-clients",
|
|
2358
|
-
"path": "packages/build-control-clients/package.json",
|
|
2359
|
-
"reason": "Private build-control infrastructure; not an application capability"
|
|
2360
|
-
},
|
|
2361
|
-
{
|
|
2362
|
-
"package": "@rightkit/build-control-core",
|
|
2363
|
-
"path": "packages/build-control-core/package.json",
|
|
2364
|
-
"reason": "Private build-control infrastructure; not an application capability"
|
|
2365
|
-
},
|
|
2366
|
-
{
|
|
2367
|
-
"package": "@rightkit/build-control-phase0",
|
|
2368
|
-
"path": "packages/build-control-phase0/package.json",
|
|
2369
|
-
"reason": "Private build-control infrastructure; not an application capability"
|
|
2370
|
-
},
|
|
2371
2351
|
{
|
|
2372
2352
|
"package": "@rightkit/build-control-policy",
|
|
2373
2353
|
"path": "packages/build-control-policy/package.json",
|
|
2374
2354
|
"reason": "Private build-control infrastructure; not an application capability"
|
|
2375
|
-
},
|
|
2376
|
-
{
|
|
2377
|
-
"package": "@rightkit/build-control-staging",
|
|
2378
|
-
"path": "packages/build-control-staging/package.json",
|
|
2379
|
-
"reason": "Private build-control infrastructure; not an application capability"
|
|
2380
|
-
},
|
|
2381
|
-
{
|
|
2382
|
-
"package": "@rightkit/build-control-phase0-macos",
|
|
2383
|
-
"path": "packages/build-control-phase0/macos/package.json",
|
|
2384
|
-
"reason": "Private native build-control feasibility fixture"
|
|
2385
|
-
},
|
|
2386
|
-
{
|
|
2387
|
-
"package": "@rightkit/build-control-phase0-windows",
|
|
2388
|
-
"path": "packages/build-control-phase0/windows/package.json",
|
|
2389
|
-
"reason": "Private native build-control feasibility fixture"
|
|
2390
2355
|
}
|
|
2391
2356
|
]
|
|
2392
2357
|
}
|
package/rightkit-sync.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { fileURLToPath } from "node:url";
|
|
|
10
10
|
const packageRoot = path.dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
const rightkitRoot = path.resolve(packageRoot, "..", "..");
|
|
12
12
|
const VERSIONS_FILE = path.join(packageRoot, "rightkit-versions.json");
|
|
13
|
-
const USER_AGENT = "rightkit-sync/1 (https://github.com/bogusyogi/
|
|
13
|
+
const USER_AGENT = "rightkit-sync/1 (https://github.com/bogusyogi/rightkit)";
|
|
14
14
|
|
|
15
15
|
const field = (toml, key) => toml.match(new RegExp(`^${key}\\s*=\\s*"([^"]*)"`, "m"))?.[1] ?? null;
|
|
16
16
|
|
|
@@ -178,12 +178,10 @@ export function recordPublished({ registry, name, version }, { file = VERSIONS_F
|
|
|
178
178
|
} catch (error) { log(`[right-release] release feed not updated (${error.message}); run node rightkit-sync.mjs`); }
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
/** The
|
|
181
|
+
/** The session hook carries byte copies of the catalog and versions; keep them exact. */
|
|
182
182
|
export function syncConsumerCopies(root = rightkitRoot) {
|
|
183
183
|
const release = path.join(root, "packages", "release");
|
|
184
184
|
const targets = [
|
|
185
|
-
["rightkit-ownership.json", path.join(root, "packages", "build-control-clients", "src", "ownership-catalog.json")],
|
|
186
|
-
["rightkit-versions.json", path.join(root, "packages", "build-control-clients", "src", "rightkit-versions.json")],
|
|
187
185
|
["rightkit-ownership.json", path.join(root, "packages", "build-control-policy", "src", "ownership-session-catalog.json")],
|
|
188
186
|
["rightkit-ownership.json", path.join(root, "packages", "build-control-policy", "src", "ownership-fingerprints.json")],
|
|
189
187
|
["rightkit-versions.json", path.join(root, "packages", "build-control-policy", "src", "ownership-session-versions.json")],
|
|
@@ -191,7 +189,6 @@ export function syncConsumerCopies(root = rightkitRoot) {
|
|
|
191
189
|
["background-process.mjs", path.join(root, "packages", "build-control-policy", "src", "background-process.mjs")],
|
|
192
190
|
["ownership-source.mjs", path.join(root, "packages", "build-control-policy", "src", "ownership-source.mjs")],
|
|
193
191
|
["ownership-availability.mjs", path.join(root, "packages", "build-control-policy", "src", "ownership-availability.mjs")],
|
|
194
|
-
["ownership-availability.mjs", path.join(root, "packages", "build-control-clients", "src", "ownership-availability.mjs")],
|
|
195
192
|
];
|
|
196
193
|
const updated = [];
|
|
197
194
|
for (const [source, target] of targets) {
|
package/rightkit-versions.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"@rightkit/app-shell": "0.3.0",
|
|
17
17
|
"@rightkit/ax": "0.2.4",
|
|
18
18
|
"@rightkit/doc-render": "0.1.4",
|
|
19
|
-
"@rightkit/git": "0.2.
|
|
19
|
+
"@rightkit/git": "0.2.31",
|
|
20
20
|
"@rightkit/hooks": "0.1.2",
|
|
21
21
|
"@rightkit/i18n": "0.1.0",
|
|
22
22
|
"@rightkit/legal": "0.3.1",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@rightkit/platform-ui": "0.2.0",
|
|
30
30
|
"@rightkit/qa": "0.4.0",
|
|
31
31
|
"@rightkit/qa-chrome": "0.1.3",
|
|
32
|
-
"@rightkit/release": "0.2.
|
|
32
|
+
"@rightkit/release": "0.2.139",
|
|
33
33
|
"@rightkit/settings-ui": "0.3.0",
|
|
34
34
|
"@rightkit/shell": "0.1.0",
|
|
35
35
|
"@rightkit/tauri": "0.2.0",
|
|
@@ -71,7 +71,8 @@
|
|
|
71
71
|
"0.2.26",
|
|
72
72
|
"0.2.27",
|
|
73
73
|
"0.2.28",
|
|
74
|
-
"0.2.29"
|
|
74
|
+
"0.2.29",
|
|
75
|
+
"0.2.30"
|
|
75
76
|
],
|
|
76
77
|
"@rightkit/legal-ui": [
|
|
77
78
|
"0.1.0",
|
|
@@ -166,7 +167,9 @@
|
|
|
166
167
|
"0.2.133",
|
|
167
168
|
"0.2.134",
|
|
168
169
|
"0.2.135",
|
|
169
|
-
"0.2.136"
|
|
170
|
+
"0.2.136",
|
|
171
|
+
"0.2.137",
|
|
172
|
+
"0.2.138"
|
|
170
173
|
],
|
|
171
174
|
"@rightkit/qa": [
|
|
172
175
|
"0.1.0",
|
|
@@ -283,7 +286,7 @@
|
|
|
283
286
|
"rightkit-oauth": "0.3.0",
|
|
284
287
|
"rightkit-ocr": "0.1.2",
|
|
285
288
|
"rightkit-ort": "0.2.2",
|
|
286
|
-
"rightkit-ownership": "0.2.
|
|
289
|
+
"rightkit-ownership": "0.2.1",
|
|
287
290
|
"rightkit-pdf": "0.2.0",
|
|
288
291
|
"rightkit-playback": "0.1.1",
|
|
289
292
|
"rightkit-process": "0.3.3",
|
|
@@ -340,7 +343,7 @@
|
|
|
340
343
|
"rightkit-oauth": "0.3.0",
|
|
341
344
|
"rightkit-ocr": "0.1.2",
|
|
342
345
|
"rightkit-ort": "0.2.2",
|
|
343
|
-
"rightkit-ownership": "0.2.
|
|
346
|
+
"rightkit-ownership": "0.2.1",
|
|
344
347
|
"rightkit-pdf": "0.2.0",
|
|
345
348
|
"rightkit-playback": "0.1.1",
|
|
346
349
|
"rightkit-process": "0.3.3",
|
|
@@ -365,7 +368,7 @@
|
|
|
365
368
|
"@rightkit/app-shell": "0.3.0",
|
|
366
369
|
"@rightkit/ax": "0.2.4",
|
|
367
370
|
"@rightkit/doc-render": "0.1.4",
|
|
368
|
-
"@rightkit/git": "0.2.
|
|
371
|
+
"@rightkit/git": "0.2.31",
|
|
369
372
|
"@rightkit/hooks": "0.1.2",
|
|
370
373
|
"@rightkit/i18n": "0.1.0",
|
|
371
374
|
"@rightkit/legal": "0.3.1",
|
|
@@ -378,7 +381,7 @@
|
|
|
378
381
|
"@rightkit/platform-ui": "0.2.0",
|
|
379
382
|
"@rightkit/qa": "0.4.0",
|
|
380
383
|
"@rightkit/qa-chrome": "0.1.3",
|
|
381
|
-
"@rightkit/release": "0.2.
|
|
384
|
+
"@rightkit/release": "0.2.139",
|
|
382
385
|
"@rightkit/settings-ui": "0.3.0",
|
|
383
386
|
"@rightkit/shell": "0.1.0",
|
|
384
387
|
"@rightkit/tauri": "0.2.0",
|
|
@@ -387,6 +390,9 @@
|
|
|
387
390
|
}
|
|
388
391
|
},
|
|
389
392
|
"legacyCargo": {
|
|
393
|
+
"rightkit-ownership": [
|
|
394
|
+
"0.2.0"
|
|
395
|
+
],
|
|
390
396
|
"rightkit-browser": [
|
|
391
397
|
"0.2.0",
|
|
392
398
|
"0.2.1",
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Everything the sealed `build` path does differently for a SwiftPM target, as pure/stub-friendly
|
|
2
|
+
// functions so build-release.mjs only branches once. Rust-only steps (rustc/cargo probes, Cargo lock
|
|
3
|
+
// identity, broker cargo target, Cache V2 shared Rust cache, target bridge, CARGO/SCCACHE env) are skipped.
|
|
4
|
+
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { resolveSwiftCacheIdentity } from "./cache-policy.mjs";
|
|
7
|
+
|
|
8
|
+
const RUST_ENV = ["CARGO_HOME", "CARGO_TARGET_DIR", "RUSTC_WRAPPER", "SCCACHE_DIR", "SCCACHE_BASEDIRS", "SCCACHE_CACHE_SIZE", "SCCACHE_IGNORE_SERVER_IO_ERROR", "RUSTFLAGS", "RIGHT_RELEASE_CACHE_OWNER"];
|
|
9
|
+
|
|
10
|
+
export function swiftArchitecture({ target = {}, platform, hostArch = process.arch }) {
|
|
11
|
+
const arch = target.msix?.identity?.architecture ?? target.architecture ?? (hostArch === "arm64" ? "arm64" : "x64");
|
|
12
|
+
return platform === "mac" ? (arch === "x64" ? "x86_64" : arch) : arch;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** exec(cmd, args) -> stdout string. Throws when swift is missing. */
|
|
16
|
+
export function collectSwiftToolVersions({ packageManager, exec, nodeVersion = process.version }) {
|
|
17
|
+
const swift = exec("swift", ["--version"]).trim();
|
|
18
|
+
if (!swift) throw new Error("swift --version printed nothing");
|
|
19
|
+
return { node: nodeVersion, packageManager: packageManager ? `${packageManager} ${exec(packageManager, ["--version"]).trim()}` : null, swift, cargo: null, rustc: null, rustHost: null, sccache: null };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Plan for a swiftpm sealed build: identity, forced non-shared cache mode, no broker cargo target, no target
|
|
24
|
+
* bridge, a plain build/cache dir under the vault, and an environment with every Rust variable removed.
|
|
25
|
+
*/
|
|
26
|
+
export function planSwiftBuild({ appRoot, vaultRoot, platform, target, toolVersions, profile = "release", hostArch }) {
|
|
27
|
+
const architecture = swiftArchitecture({ target, platform, hostArch });
|
|
28
|
+
const identity = resolveSwiftCacheIdentity({ swiftVersion: toolVersions.swift, packageResolvedPath: path.join(appRoot, "Package.resolved"), architecture, profile: target.profile ?? profile });
|
|
29
|
+
const buildDir = path.resolve(vaultRoot, "cache", "swift-build", platform, identity.fingerprint);
|
|
30
|
+
return {
|
|
31
|
+
identity, architecture, buildDir,
|
|
32
|
+
cacheMode: "legacy",
|
|
33
|
+
managedCargoTarget: null,
|
|
34
|
+
targetBridge: { run: (fn) => fn(), ensure() {} },
|
|
35
|
+
sanitizeEnv(env) {
|
|
36
|
+
const next = { ...env };
|
|
37
|
+
for (const name of RUST_ENV) delete next[name];
|
|
38
|
+
next.RIGHT_RELEASE_SWIFT_BUILD_DIR = buildDir;
|
|
39
|
+
return next;
|
|
40
|
+
},
|
|
41
|
+
watchDirs: [buildDir, path.join(appRoot, ".build")],
|
|
42
|
+
};
|
|
43
|
+
}
|