From e2d09643bf6147df03f1751cb5241ce63869fc98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 9 Sep 2026 00:05:38 +0200 Subject: [PATCH 1/2] fix(ci): dispatch camoufox template updates with camoufox's own Playwright version The matrix already knows camoufox cannot use every Playwright release. It reads the supported range from the package metadata and builds the camoufox image with its own version list: const imagePlaywrightVersions = isCamoufoxImage ? camoufoxPlaywrightVersions : latestFivePlaywrightVersions; The dispatch to actor-templates then ignores that. It sends `latestPlaywrightVersion` - the global latest - alongside a hardcoded image list that includes camoufox. actor-templates writes that version into the camoufox Dockerfiles, producing a `FROM` tag that was never built. Today camoufox-js@0.12.0 declares `playwright-core: "<1.61.0"`, so the newest camoufox image is 24-1.60.0 while the other images are at 24-1.63.0. The dispatch claims 1.63.0 for all five. apify/actor-templates#872 is the result: it pins apify/actor-node-playwright-camoufox:24-1.61.1, which does not exist on Docker Hub, and its Docker build jobs fail. Split the dispatch in two. The four regular images keep the existing version; camoufox gets its own dispatch carrying `latestCamoufoxPlaywrightVersion`, which was already computed one line away. The camoufox step is skipped when the matrix resolved no supported version - the same condition under which no camoufox image is built. The Python playwright workflow had the identical defect and gets the same fix. It happens to be harmless right now (camoufox==0.5.6 supports <1.63, and the latest Python Playwright is 1.62.0, so both versions coincide) but it would break the moment Playwright 1.63 reaches the Python images. Verified by running both matrix scripts with GITHUB_OUTPUT set: node:playwright latest-module-version=1.63.0 latest-camoufox-module-version=1.60.0 python:playwright latest-module-version=1.62.0 latest-camoufox-module-version=1.62.0 1.60.0 matches the newest camoufox tag actually on Docker Hub. Matrices with no camoufox image (node:normal, node:puppeteer) emit no camoufox output, unchanged. Typecheck clean, 23 tests pass, biome reports no formatting changes. Co-Authored-By: Claude Opus 5 --- .../src/matrices/node/playwright.ts | 6 ++++- .../src/matrices/python/playwright.ts | 6 ++++- .../version-matrix/src/shared/constants.ts | 27 +++++++++++++------ .../workflows/release-node-playwright.yaml | 20 +++++++++++++- .../workflows/release-python-playwright.yaml | 20 +++++++++++++- 5 files changed, 67 insertions(+), 12 deletions(-) diff --git a/.github/actions/version-matrix/src/matrices/node/playwright.ts b/.github/actions/version-matrix/src/matrices/node/playwright.ts index 17486b3b..5247d32e 100644 --- a/.github/actions/version-matrix/src/matrices/node/playwright.ts +++ b/.github/actions/version-matrix/src/matrices/node/playwright.ts @@ -73,7 +73,11 @@ const cacheParams: CacheValues = { CERTIFICATES_UPDATED_AT: certificatesUpdatedAt ? [certificatesUpdatedAt] : [], }; -await setParametersForTriggeringUpdateWorkflowOnActorTemplates('node', latestPlaywrightVersion); +await setParametersForTriggeringUpdateWorkflowOnActorTemplates( + 'node', + latestPlaywrightVersion, + latestCamoufoxPlaywrightVersion, +); if (!(await needsToRunMatrixGeneration('node:playwright', cacheParams))) { console.error('Matrix generation is not needed, exiting.'); diff --git a/.github/actions/version-matrix/src/matrices/python/playwright.ts b/.github/actions/version-matrix/src/matrices/python/playwright.ts index 56588236..4b1b7b8a 100644 --- a/.github/actions/version-matrix/src/matrices/python/playwright.ts +++ b/.github/actions/version-matrix/src/matrices/python/playwright.ts @@ -68,7 +68,11 @@ const cacheParams: CacheValues = { CERTIFICATES_UPDATED_AT: certificatesUpdatedAt ? [certificatesUpdatedAt] : [], }; -await setParametersForTriggeringUpdateWorkflowOnActorTemplates('python', latestPlaywrightVersion); +await setParametersForTriggeringUpdateWorkflowOnActorTemplates( + 'python', + latestPlaywrightVersion, + latestCamoufoxPlaywrightVersion, +); if (!(await needsToRunMatrixGeneration('python:playwright', cacheParams))) { console.error('Matrix is up to date, skipping new image building'); diff --git a/.github/actions/version-matrix/src/shared/constants.ts b/.github/actions/version-matrix/src/shared/constants.ts index dbddcde2..06c8f4f4 100644 --- a/.github/actions/version-matrix/src/shared/constants.ts +++ b/.github/actions/version-matrix/src/shared/constants.ts @@ -18,9 +18,19 @@ export const latestPythonVersion = '3.14'; */ export const latestNodeVersion = '24'; +/** + * Writes the parameters the release workflow sends to actor-templates as a `repository_dispatch`. + * + * `camoufoxModuleVersion` is separate from `moduleVersion` on purpose. Camoufox only supports a subset of the + * Playwright releases, so its image is built with an older Playwright than the other images in the same matrix - see + * `resolveCamoufoxPlaywrightVersions`. Sending one version for both would tell actor-templates to pin a camoufox image + * tag that was never built. It is left unset when the camoufox image is not part of this matrix run, and the workflow + * skips the camoufox dispatch in that case. + */ export async function setParametersForTriggeringUpdateWorkflowOnActorTemplates( runtime: 'python' | 'node', moduleVersion?: string, + camoufoxModuleVersion?: string, ) { let latestRuntimeVersion: string; @@ -33,19 +43,20 @@ export async function setParametersForTriggeringUpdateWorkflowOnActorTemplates( break; } + const output = [ + `latest-runtime-version=${latestRuntimeVersion}`, + ...(moduleVersion ? [`latest-module-version=${moduleVersion}`] : []), + ...(camoufoxModuleVersion ? [`latest-camoufox-module-version=${camoufoxModuleVersion}`] : []), + '', + ].join('\n'); + if (!process.env.GITHUB_OUTPUT) { console.error('GITHUB_OUTPUT is not set'); - console.error( - `Would have appended the following to the output: -latest-runtime-version=${latestRuntimeVersion}${moduleVersion ? `\nlatest-module-version=${moduleVersion}` : ''}\n`, - ); + console.error(`Would have appended the following to the output:\n${output}`); return; } - await appendFile( - process.env.GITHUB_OUTPUT!, - `latest-runtime-version=${latestRuntimeVersion}${moduleVersion ? `\nlatest-module-version=${moduleVersion}` : ''}\n`, - ); + await appendFile(process.env.GITHUB_OUTPUT!, output); } diff --git a/.github/workflows/release-node-playwright.yaml b/.github/workflows/release-node-playwright.yaml index 1062b1ab..0d01b8d6 100644 --- a/.github/workflows/release-node-playwright.yaml +++ b/.github/workflows/release-node-playwright.yaml @@ -104,11 +104,29 @@ jobs: event-type: update-templates client-payload: |- { - "base_image": "apify/actor-node-playwright,apify/actor-node-playwright-chrome,apify/actor-node-playwright-firefox,apify/actor-node-playwright-webkit,apify/actor-node-playwright-camoufox", + "base_image": "apify/actor-node-playwright,apify/actor-node-playwright-chrome,apify/actor-node-playwright-firefox,apify/actor-node-playwright-webkit", "module_version": "${{ steps.set-matrix.outputs.latest-module-version }}", "default_runtime_version": "${{ steps.set-matrix.outputs.latest-runtime-version }}" } + # Camoufox supports only a subset of the Playwright releases, so its image is built with an older Playwright + # than the other images above. It gets its own dispatch with its own version - sending it the version the other + # images use would make actor-templates pin an image tag that was never built. The step is skipped when the + # matrix resolved no supported Playwright version, which is also when no camoufox image was built. + - name: Trigger workflow on actor-templates for camoufox + if: ((steps.commit.outputs.committed == 'true' || github.event.inputs.trigger_templates_pr == 'true') && steps.set-matrix.outputs.latest-runtime-version != '') && steps.set-matrix.outputs.latest-camoufox-module-version != '' + uses: peter-evans/repository-dispatch@v4 + with: + token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }} + repository: apify/actor-templates + event-type: update-templates + client-payload: |- + { + "base_image": "apify/actor-node-playwright-camoufox", + "module_version": "${{ steps.set-matrix.outputs.latest-camoufox-module-version }}", + "default_runtime_version": "${{ steps.set-matrix.outputs.latest-runtime-version }}" + } + # Build master images that are not dependent on existing builds. build-main: needs: [matrix] diff --git a/.github/workflows/release-python-playwright.yaml b/.github/workflows/release-python-playwright.yaml index 18f7ec74..fac2acff 100644 --- a/.github/workflows/release-python-playwright.yaml +++ b/.github/workflows/release-python-playwright.yaml @@ -95,11 +95,29 @@ jobs: event-type: update-templates client-payload: |- { - "base_image": "apify/actor-python-playwright,apify/actor-python-playwright-chrome,apify/actor-python-playwright-firefox,apify/actor-python-playwright-webkit,apify/actor-python-playwright-camoufox", + "base_image": "apify/actor-python-playwright,apify/actor-python-playwright-chrome,apify/actor-python-playwright-firefox,apify/actor-python-playwright-webkit", "module_version": "${{ steps.set-matrix.outputs.latest-module-version }}", "default_runtime_version": "${{ steps.set-matrix.outputs.latest-runtime-version }}" } + # Camoufox supports only a subset of the Playwright releases, so its image is built with an older Playwright + # than the other images above. It gets its own dispatch with its own version - sending it the version the other + # images use would make actor-templates pin an image tag that was never built. The step is skipped when the + # matrix resolved no supported Playwright version, which is also when no camoufox image was built. + - name: Trigger workflow on actor-templates for camoufox + if: ((steps.commit.outputs.committed == 'true' || github.event.inputs.trigger_templates_pr == 'true') && steps.set-matrix.outputs.latest-runtime-version != '') && steps.set-matrix.outputs.latest-camoufox-module-version != '' + uses: peter-evans/repository-dispatch@v4 + with: + token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }} + repository: apify/actor-templates + event-type: update-templates + client-payload: |- + { + "base_image": "apify/actor-python-playwright-camoufox", + "module_version": "${{ steps.set-matrix.outputs.latest-camoufox-module-version }}", + "default_runtime_version": "${{ steps.set-matrix.outputs.latest-runtime-version }}" + } + # Build master images that are not dependent on existing builds. build-main: needs: [matrix] From 47249b49a53cfef1b6e178f943ce8e486f32017a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 9 Sep 2026 06:07:49 +0000 Subject: [PATCH 2/2] chore(ci): trim camoufox dispatch comments in release workflows Condense the four-line comment above each camoufox dispatch step to a single line, per review feedback. No behavior change. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01TQJXEZ7g4H4fHv76J3hM5D --- .github/workflows/release-node-playwright.yaml | 5 +---- .github/workflows/release-python-playwright.yaml | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release-node-playwright.yaml b/.github/workflows/release-node-playwright.yaml index 0d01b8d6..3cc122b2 100644 --- a/.github/workflows/release-node-playwright.yaml +++ b/.github/workflows/release-node-playwright.yaml @@ -109,10 +109,7 @@ jobs: "default_runtime_version": "${{ steps.set-matrix.outputs.latest-runtime-version }}" } - # Camoufox supports only a subset of the Playwright releases, so its image is built with an older Playwright - # than the other images above. It gets its own dispatch with its own version - sending it the version the other - # images use would make actor-templates pin an image tag that was never built. The step is skipped when the - # matrix resolved no supported Playwright version, which is also when no camoufox image was built. + # Camoufox lags behind on Playwright, so it needs its own dispatch with its own version. - name: Trigger workflow on actor-templates for camoufox if: ((steps.commit.outputs.committed == 'true' || github.event.inputs.trigger_templates_pr == 'true') && steps.set-matrix.outputs.latest-runtime-version != '') && steps.set-matrix.outputs.latest-camoufox-module-version != '' uses: peter-evans/repository-dispatch@v4 diff --git a/.github/workflows/release-python-playwright.yaml b/.github/workflows/release-python-playwright.yaml index fac2acff..03d7b52e 100644 --- a/.github/workflows/release-python-playwright.yaml +++ b/.github/workflows/release-python-playwright.yaml @@ -100,10 +100,7 @@ jobs: "default_runtime_version": "${{ steps.set-matrix.outputs.latest-runtime-version }}" } - # Camoufox supports only a subset of the Playwright releases, so its image is built with an older Playwright - # than the other images above. It gets its own dispatch with its own version - sending it the version the other - # images use would make actor-templates pin an image tag that was never built. The step is skipped when the - # matrix resolved no supported Playwright version, which is also when no camoufox image was built. + # Camoufox lags behind on Playwright, so it needs its own dispatch with its own version. - name: Trigger workflow on actor-templates for camoufox if: ((steps.commit.outputs.committed == 'true' || github.event.inputs.trigger_templates_pr == 'true') && steps.set-matrix.outputs.latest-runtime-version != '') && steps.set-matrix.outputs.latest-camoufox-module-version != '' uses: peter-evans/repository-dispatch@v4