ci: Run nightly e2e on test-enabled -pc image build (#37104)

This commit is contained in:
Iván Ovejero
2026-08-27 14:05:55 +00:00
committed by GitHub
parent 68afc97ac9
commit f5557eff90
7 changed files with 100 additions and 43 deletions
+15 -1
View File
@@ -12,7 +12,7 @@ description: 'Builds n8nio/n8n + n8nio/runners test images and publishes them as
inputs:
build-variant:
description: 'standard or coverage. Coverage uses build:docker:coverage.'
description: 'standard, coverage, or pc. Coverage uses build:docker:coverage. pc builds n8n on the pointer-compressed Node base images.'
required: false
default: 'standard'
@@ -35,6 +35,20 @@ runs:
enable-docker-cache: true
env:
INCLUDE_TEST_CONTROLLER: 'true'
# Keep the pc pins in sync with the -pc build in docker-build-push.yml.
BUILDER_IMAGE: ${{ inputs.build-variant == 'pc' && 'n8nio/node-pc:26.7.0-dev@sha256:c64642dcb9464e50bd08aef8504affafeb795d01aed2f7ab158976c334a36ef6' || '' }}
RUNTIME_IMAGE: ${{ inputs.build-variant == 'pc' && 'n8nio/node-pc:26.7.0@sha256:6577d0742ad043baaa39db7dda2ce8aeb73f32c84eb241c49bf716f170c53297' || '' }}
- name: Assert pointer compression
if: steps.cache-check.outputs.cache-hit != 'true' && inputs.build-variant == 'pc'
shell: bash
run: |
docker run --rm --entrypoint node n8nio/n8n:local -e "
if (!process.config.variables.v8_enable_pointer_compression) {
throw new Error('pc variant image is not pointer-compressed');
}
console.log(process.version, 'pointer compression: on');
"
- name: Save image tarball
if: steps.cache-check.outputs.cache-hit != 'true'
+1 -1
View File
@@ -15,7 +15,7 @@ description: 'Restores the zstd-compressed n8n + runners image tarball from the
inputs:
build-variant:
description: 'Variant of the image to load. Must match what build-n8n-docker used (standard or coverage).'
description: 'Variant of the image to load. Must match what build-n8n-docker used (standard, coverage, or pc).'
required: false
default: 'standard'
cache-sha:
+2 -2
View File
@@ -220,8 +220,8 @@ jobs:
NODE_VERSION=${{ env.NODE_VERSION }}
N8N_VERSION=${{ needs.determine-build-context.outputs.n8n_version }}
N8N_RELEASE_TYPE=${{ needs.determine-build-context.outputs.release_type }}
BUILDER_IMAGE=n8nio/node-pc:26.5.1-dev@sha256:9ecfe9d5c7ea835bccc604d06c3cb76a837b64496d4a999338cb8b53a50bb0bd
RUNTIME_IMAGE=n8nio/node-pc:26.5.1@sha256:e535408e7815904c98f81fb0203f7f657047d7db3d4edc77de44d2ea72c6bf18
BUILDER_IMAGE=n8nio/node-pc:26.7.0-dev@sha256:c64642dcb9464e50bd08aef8504affafeb795d01aed2f7ab158976c334a36ef6
RUNTIME_IMAGE=n8nio/node-pc:26.7.0@sha256:6577d0742ad043baaa39db7dda2ce8aeb73f32c84eb241c49bf716f170c53297
IMAGE_DESCRIPTION=Workflow Automation Tool (pointer-compressed variant, internal to n8n Cloud, no support or stability guarantees)
platforms: ${{ matrix.docker_platform }}
provenance: false # Disabled - using SLSA L3 generator for isolated provenance
@@ -11,7 +11,7 @@ on:
workflow_call:
inputs:
build-variant:
description: 'standard or coverage'
description: 'standard, coverage, or pc'
required: false
default: 'standard'
type: string
+72 -36
View File
@@ -1,70 +1,106 @@
name: 'Test: E2E on -pc image'
# Boots the pointer-compressed n8n image and runs the e2e suite against it.
# The e2e suite needs the test-only e2e controller, which published images
# exclude. So: assert the published -pc image boots pointer-compressed, then
# run the full suite against a test-enabled twin (build-variant: pc).
on:
schedule:
- cron: '0 2 * * *' # after the nightly Docker build at midnight
workflow_dispatch:
inputs:
image:
description: 'n8n image to test'
published-image:
description: 'Published -pc image to health-check'
required: false
default: 'n8nio/n8n:nightly-pc'
type: string
runners-image:
description: 'Task runner image to boot beside it'
required: false
default: 'n8nio/runners:nightly'
type: string
permissions:
contents: read
env:
TEST_IMAGE_N8N: ${{ inputs.image || 'n8nio/n8n:nightly-pc' }}
TEST_IMAGE_TASK_RUNNER: ${{ inputs.runners-image || 'n8nio/runners:nightly' }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
e2e-pc:
name: E2E on -pc image (${{ matrix.shard }}/4)
runs-on: blacksmith-4vcpu-ubuntu-2204
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
assert-published:
name: Published -pc image health check
runs-on: blacksmith-2vcpu-ubuntu-2204
timeout-minutes: 10
steps:
- uses: useblacksmith/checkout@41cdeedae8edb2e684ba22896a5fd2a3cb85db6b # v1
with:
persist-credentials: false
- name: Pull image and assert pointer compression
- name: Assert pointer compression and boot to healthz
env:
PUBLISHED_IMAGE: ${{ inputs.published-image || 'n8nio/n8n:nightly-pc' }}
run: |
docker pull --quiet "$TEST_IMAGE_N8N"
docker run --rm --entrypoint node "$TEST_IMAGE_N8N" -e "
docker pull --quiet "$PUBLISHED_IMAGE"
docker run --rm --entrypoint node "$PUBLISHED_IMAGE" -e "
if (!process.config.variables.v8_enable_pointer_compression) {
throw new Error('image is not pointer-compressed');
}
console.log(process.version, 'pointer compression: on');
"
docker run -d --name published-pc -p 5678:5678 "$PUBLISHED_IMAGE"
for i in $(seq 1 24); do
if curl -sf http://localhost:5678/healthz > /dev/null; then
echo "healthz reachable after ~$((i * 5))s"
exit 0
fi
sleep 5
done
echo '::error::published image did not reach /healthz within 120s'
docker logs published-pc 2>&1 | tail -50
exit 1
- name: Build the test harness
prepare-docker:
name: Prepare Docker (pc)
uses: ./.github/workflows/prepare-docker-reusable.yml
with:
build-variant: pc
runner: blacksmith-8vcpu-ubuntu-2204
secrets: inherit
generate-matrix:
name: Generate shard matrix
runs-on: blacksmith-2vcpu-ubuntu-2204
outputs:
matrix: ${{ steps.gen.outputs.matrix }}
steps:
- uses: useblacksmith/checkout@41cdeedae8edb2e684ba22896a5fd2a3cb85db6b # v1
with:
persist-credentials: false
- name: Setup
uses: ./.github/actions/setup-nodejs
with:
build-command: 'pnpm turbo build --filter=n8n-playwright...'
build-command: pnpm turbo run build --filter=@n8n/playwright-janitor
- name: Install Playwright browsers
working-directory: packages/testing/playwright
run: npx playwright install chromium --with-deps
- name: Generate matrix (16 shards, duration-weighted)
id: gen
run: |
MATRIX=$(node packages/testing/playwright/scripts/distribute-tests.mjs --matrix 16 --orchestrate)
echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT"
- name: Run e2e against the image
working-directory: packages/testing/playwright
run: pnpm test:container:sqlite:e2e -- --shard=${{ matrix.shard }}/4
e2e:
name: E2E on the pc twin
needs: [prepare-docker, generate-matrix]
uses: ./.github/workflows/test-e2e-reusable.yml
with:
test-mode: docker-artifact
test-command: pnpm --filter=n8n-playwright test:container:sqlite:e2e
workers: '1'
runner: blacksmith-4vcpu-ubuntu-2204
timeout-minutes: 55
pre-generated-matrix: ${{ needs.generate-matrix.outputs.matrix }}
artifact-prefix: pc
build-variant: pc
currents-project-id: 'LRxcNt'
secrets: inherit
notify-on-failure:
name: Notify Cats on -pc e2e failure
runs-on: ubuntu-latest
needs: [e2e-pc]
if: always() && needs.e2e-pc.result == 'failure' && github.event_name == 'schedule'
needs: [assert-published, prepare-docker, generate-matrix, e2e]
if: always() && contains(needs.*.result, 'failure') && github.event_name == 'schedule'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
+1 -1
View File
@@ -53,7 +53,7 @@ on:
default: 'e2e'
type: string
build-variant:
description: 'Build variant for docker-artifact mode. Must match the variant used by prepare-docker (standard or coverage).'
description: 'Build variant for docker-artifact mode. Must match the variant used by prepare-docker (standard, coverage, or pc).'
required: false
default: 'standard'
type: string