fix(ci): Mac buildx without osxkeychain; soft-fail screencapture

Headless Air/Mini runners fail docker/setup-buildx when credsStore points
at a missing docker-credential-osxkeychain binary. Point DOCKER_CONFIG at
an empty config for macOS jobs only.

macOS screenshot jobs fail when screencapture has no interactive display;
skip those captures and warn on missing screenshot artifacts instead of
failing the workflow.
This commit is contained in:
cynarAI 2026-09-21 20:12:50 +02:00
parent ee56e1795e
commit a8e08352bc
3 changed files with 36 additions and 10 deletions

View File

@ -65,5 +65,5 @@ jobs:
path: |
apps/desktop/e2e/screenshots/08-setup-macos-native-controls.png
apps/desktop/e2e/screenshots/09-macos-dock.png
if-no-files-found: error
if-no-files-found: warn
retention-days: 1

View File

@ -126,6 +126,15 @@ jobs:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
# Headless Mac runners often have credsStore=osxkeychain without the helper binary,
# which breaks buildx bootstrap when pulling moby/buildkit.
- name: Use Docker config without osxkeychain
if: runner.os == 'macOS'
run: |
set -euo pipefail
mkdir -p "$RUNNER_TEMP/docker-config"
printf '{}\n' > "$RUNNER_TEMP/docker-config/config.json"
echo "DOCKER_CONFIG=$RUNNER_TEMP/docker-config" >> "$GITHUB_ENV"
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Log in to GHCR
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0

View File

@ -108,11 +108,25 @@ test("first run asks whether to use a local or existing instance", async () => {
await expect(setup.locator(".titlebar")).toHaveCSS("padding-left", "88px");
expect((await setup.locator(".titlebar-name").boundingBox())?.x).toBeGreaterThanOrEqual(88);
if (process.platform === "darwin") {
// Headless/self-hosted Mac runners often lack an interactive display session;
// screencapture then fails with "could not create image from display".
const captureOrSkip = async (args: string[], label: string) => {
try {
await execFileAsync("screencapture", args);
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
if (/could not create image from display|no displays|not authorized|capture failed/i.test(message)) {
console.warn(`screencapture skipped (${label}): ${message}`);
return;
}
throw err;
}
};
if (process.env.CI) {
await execFileAsync("screencapture", [
"-x",
path.join(import.meta.dirname, "screenshots", "09-macos-dock.png"),
]);
await captureOrSkip(
["-x", path.join(import.meta.dirname, "screenshots", "09-macos-dock.png")],
"dock",
);
}
await app.evaluate(({ BrowserWindow }) => {
const window = BrowserWindow.getAllWindows()[0];
@ -122,11 +136,14 @@ test("first run asks whether to use a local or existing instance", async () => {
window.focus();
});
await setup.waitForTimeout(500);
await execFileAsync("screencapture", [
"-x",
"-R40,40,720,700",
path.join(import.meta.dirname, "screenshots", "08-setup-macos-native-controls.png"),
]);
await captureOrSkip(
[
"-x",
"-R40,40,720,700",
path.join(import.meta.dirname, "screenshots", "08-setup-macos-native-controls.png"),
],
"native-controls",
);
}
});