Skip to content
Merged
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
16 changes: 11 additions & 5 deletions tests/ci-workflows/release-desktop-scripts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@ describe("widget extension signing", () => {
};
const steps = workflow.jobs?.["package-desktop"]?.steps ?? [];
const indexOfStep = (name: string) => steps.findIndex(step => step.name === name);
// Located by what a step does, not by what it is called. The first version of this file keyed
// on step names, and #5339 renamed the certificate import while this branch was open: the
// rename survived the merge, the assertion did not, and `dev` went red on a test whose subject
// was still correct.
const indexOfStepRunning = (fragment: string) =>
steps.findIndex(step => typeof step.run === "string" && step.run.includes(fragment));

test("the release build hands the widget a signing identity and forbids an ad-hoc fallback", () => {
const build = steps.find(step => step.name === "Build WidgetKit extension");
Expand All @@ -233,16 +239,16 @@ describe("widget extension signing", () => {
test("the certificate is importable before the widget is signed and is removed afterwards", () => {
// codesign resolves an identity through the keychain search list, and Tauri does not build
// its own keychain until the bundling step, which is after this one.
const importStep = indexOfStep("Import the Apple signing certificate for the widget");
const importStep = indexOfStepRunning("security create-keychain");
const buildStep = indexOfStep("Build WidgetKit extension");
expect(importStep).toBeGreaterThanOrEqual(0);
expect(buildStep).toBeGreaterThan(importStep);

const cleanup = steps.find(step => step.name === "Remove the widget signing keychain");
const cleanup = steps[indexOfStepRunning("security delete-keychain")];
expect(cleanup?.if).toContain("always()");
expect(cleanup?.run).toContain("security delete-keychain");
// The decoded p12 must not outlive the import.
expect(steps[importStep]?.run).toContain("rm -f \"$certificate\"");
// The decoded p12 must not outlive the import, including when a later command fails.
expect(steps[importStep]?.run).toContain("trap ");
expect(steps[importStep]?.run).toContain("$certificate");
Comment on lines +250 to +251

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ensure the trap actually deletes the certificate

These independent substring checks do not prove that the trap removes the decoded credential: $certificate already appears in the assignment, decode, and import commands, so changing the trap to trap 'true' EXIT or using it only for unrelated cleanup would still pass while leaving the .p12 on disk. Match the trap body itself and require it to invoke shred or rm on $certificate, preserving the intended release-secret regression guard.

AGENTS.md reference: AGENTS.md:L420-L426

Useful? React with 👍 / 👎.

});

test("the script selects binaries by Mach-O magic bytes rather than by name", () => {
Expand Down
Loading