Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/fork-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ jobs:
resource_key: darwin-x64
cli_archive: false
relay_client_tracing: false
emit_macos_inspection: true

desktop_mac_arm64:
name: Desktop macOS arm64
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/release-desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ on:
required: false
default: true
type: boolean
# Fork qualification can request a native inspection of the produced
# Intel DMG. Other reusable callers keep their existing artifact shape.
emit_macos_inspection:
required: false
default: false
type: boolean
clerk_publishable_key:
required: true
type: string
Expand Down Expand Up @@ -555,6 +561,24 @@ jobs:
done
fi

# The Linux qualify job cannot mount a DMG. Emit its inspection from the
# native Mac runner and carry the digest-bound record with the DMG.
- name: Inspect macOS release artifact provenance
if: inputs.emit_macos_inspection && inputs.platform == 'mac'
shell: bash
env:
RELEASE_VERSION: ${{ inputs.version }}
RELEASE_SHA: ${{ inputs.ref }}
run: |
set -euo pipefail
node scripts/verify-fork-candidate.ts \
--candidate-dir release-publish \
--version "$RELEASE_VERSION" \
--sha "$RELEASE_SHA" \
--repository "nullStack65/t3code" \
--targets mac \
--emit-inspection "release-publish/fork-inspection-evidence-macos-x64.json"

- name: Collect resource monitor
shell: bash
run: |
Expand Down
124 changes: 124 additions & 0 deletions scripts/lib/candidate-provenance-inspect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// @effect-diagnostics nodeBuiltinImport:off - This test creates disposable synthetic files and a stub executable to verify the host-only DMG extraction boundary.
import * as NodeFS from "node:fs";
import * as NodeOS from "node:os";
import * as NodePath from "node:path";

import { assert, it } from "@effect/vitest";
import { HostProcessPlatform } from "@t3tools/shared/hostProcess";

import { inspectCandidateProvenance } from "./candidate-provenance-inspect.ts";
import { verifyTargetPackagedProvenance } from "./fork-release-manifest.ts";

const VERSION = "0.0.44";
const SHA = "bcc1a58b19a9d610a4f08fed191a364767bc65b3";
const EXPECTED_RECORD = {
repository: "nullStack65/t3code",
sourceSha: SHA,
version: VERSION,
platform: "mac",
arch: "x64",
};

it("leaves an unopenable nonnative DMG for digest-bound native inspection", () => {
if (HostProcessPlatform.defaultValue() !== "linux") return;

const root = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-mac-inspection-test-"));
const tools = NodePath.join(root, "tools");
const candidate = NodePath.join(root, "candidate");
NodeFS.mkdirSync(tools);
NodeFS.mkdirSync(candidate);
const dmgName = `T3-Code-${VERSION}-x64.dmg`;
const dmgPath = NodePath.join(candidate, dmgName);
NodeFS.writeFileSync(dmgPath, "synthetic DMG bytes");

// Force the non-native extraction attempt to fail without depending on a
// runner's installed 7-Zip version or whether that build supports HFS.
const sevenZip = NodePath.join(tools, "7z");
const which = NodePath.join(tools, "which");
NodeFS.writeFileSync(sevenZip, "#!/bin/sh\nexit 1\n", { mode: 0o755 });
NodeFS.writeFileSync(
which,
`#!/bin/sh\nif [ "$1" = "7z" ]; then echo "${sevenZip}"; exit 0; fi\nexit 1\n`,
{ mode: 0o755 },
);

const originalPath = process.env.PATH;
process.env.PATH = `${tools}:${originalPath ?? ""}`;
try {
const inspection = inspectCandidateProvenance({
candidateDir: candidate,
version: VERSION,
targets: "mac",
includeMacosArm64: false,
});
assert.equal(inspection.provenance.macDmg, undefined);

const observedAssets = [
{
name: dmgName,
sha256: inspection.evidence.digests.macDmg!,
size: NodeFS.statSync(dmgPath).size,
},
];
const evidence = {
...inspection.evidence,
host: "darwin-x64",
records: { macDmg: EXPECTED_RECORD },
digests: { macDmg: inspection.evidence.digests.macDmg! },
};
const expected = { repository: "nullStack65/t3code", version: VERSION, sourceSha: SHA };

const missingEvidence = verifyTargetPackagedProvenance({
provenance: inspection.provenance,
evidence: [],
observedAssets,
expected,
targets: "mac",
includeMacosArm64: false,
});
assert.equal(missingEvidence.ok, false);
assert.match(
missingEvidence.failures.join("\n"),
/no digest-bound inspection evidence matched/,
);

const matched = verifyTargetPackagedProvenance({
provenance: inspection.provenance,
evidence: [evidence],
observedAssets,
expected,
targets: "mac",
includeMacosArm64: false,
});
assert.deepEqual(matched, { ok: true, failures: [] });

const stale = verifyTargetPackagedProvenance({
provenance: inspection.provenance,
evidence: [{ ...evidence, digests: { macDmg: "f".repeat(64) } }],
observedAssets,
expected,
targets: "mac",
includeMacosArm64: false,
});
assert.equal(stale.ok, false);
assert.match(stale.failures.join("\n"), /inspection evidence is bound to digest/);

const nativeUnreadable = verifyTargetPackagedProvenance({
provenance: { macDmg: null },
evidence: [evidence],
observedAssets,
expected,
targets: "mac",
includeMacosArm64: false,
});
assert.equal(nativeUnreadable.ok, false);
assert.match(
nativeUnreadable.failures.join("\n"),
/Intel macOS DMG has no readable packaged provenance/,
);
} finally {
if (originalPath === undefined) delete process.env.PATH;
else process.env.PATH = originalPath;
NodeFS.rmSync(root, { recursive: true, force: true });
}
});
5 changes: 4 additions & 1 deletion scripts/lib/candidate-provenance-inspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,10 @@ function inspectMacDmg(dmg: string, scratch: string): PackagedProvenanceRecord |
if (sevenZip === undefined) return undefined;
const dir = NodeFS.mkdtempSync(NodePath.join(scratch, "dmg-"));
const status = run(sevenZip, ["x", "-y", `-o${dir}`, dmg], { allowFailure: true });
return status === 0 ? readAsarBuildInfoInTree(dir) : null;
// A failed 7-Zip extraction did not inspect the DMG. Leave it available for
// digest-bound evidence from the native Mac runner; a successful extraction
// with missing or invalid app metadata still remains an observed failure.
return status === 0 ? readAsarBuildInfoInTree(dir) : undefined;
}

export interface InspectCandidateInput {
Expand Down
47 changes: 47 additions & 0 deletions scripts/lib/fork-release-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,50 @@ it.effect("release-desktop binds provenance to the checked-out ref", () =>
assert.include(text, 'T3CODE_RELEASE_BUILD: "1"');
}),
);

it.effect("the fork release attaches native digest-bound Intel DMG inspection evidence", () =>
Effect.gen(function* () {
const fork = yield* Effect.promise(() => readWorkflow("fork-release.yml"));
const desktop = yield* Effect.promise(() => readWorkflow("release-desktop.yml"));
const intelMac = jobBlock(fork, "desktop_mac_x64");
const qualify = jobBlock(fork, "qualify");
const desktopInput = desktop.slice(
desktop.indexOf(" emit_macos_inspection:"),
desktop.indexOf(" clerk_publishable_key:"),
);

assert.include(intelMac, "emit_macos_inspection: true");
assert.include(desktopInput, "emit_macos_inspection:");
assert.include(desktopInput, "default: false");
const inspect = desktop.slice(
desktop.indexOf("- name: Inspect macOS release artifact provenance"),
desktop.indexOf("- name: Collect resource monitor"),
);
assert.include(inspect, "inputs.emit_macos_inspection && inputs.platform == 'mac'");
assert.include(inspect, "scripts/verify-fork-candidate.ts");
assert.include(inspect, "--candidate-dir release-publish");
assert.include(inspect, '--version "$RELEASE_VERSION"');
assert.include(inspect, '--sha "$RELEASE_SHA"');
assert.include(inspect, '--repository "nullStack65/t3code"');
assert.include(inspect, "--targets mac");
assert.include(inspect, "--emit-inspection");
assert.include(inspect, "fork-inspection-evidence-macos-x64.json");
assert.isBelow(
desktop.indexOf("- name: Inspect macOS release artifact provenance"),
desktop.indexOf("- name: Upload build artifacts"),
);
assert.include(
desktop.slice(desktop.indexOf("- name: Upload build artifacts")),
"release-publish/*",
);
const downloadDesktop = qualify.slice(
qualify.indexOf("- name: Download desktop artifacts"),
qualify.indexOf("- name: Download CLI archives"),
);
assert.include(downloadDesktop, "pattern: desktop-*");
assert.include(downloadDesktop, "merge-multiple: true");
assert.include(downloadDesktop, "path: candidate");
assert.include(qualify, "fork-inspection-evidence*.json");
assert.include(qualify, "--inspection-evidence");
}),
);
Loading