diff --git a/.github/actions/setup-nodejs-github/action.yml b/.github/actions/setup-nodejs-github/action.yml deleted file mode 100644 index 1d1d4f75d9b3e..0000000000000 --- a/.github/actions/setup-nodejs-github/action.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: 'GitHub Node.js Build Setup for Github Hosted Runners' -description: 'Configures Node.js with pnpm, installs dependencies, enables Turborepo caching, and builds the project or an optional command.' - -inputs: - node-version: - description: 'Node.js version to use. Uses latest 22.x by default.' - required: false - default: '22.x' - build-command: - description: 'Command to execute for building the project or an optional command. Leave empty to skip build step.' - required: false - default: 'pnpm build' - type: string - -runs: - using: 'composite' - steps: - - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: ${{ inputs.node-version }} - - - name: Setup pnpm and Install Dependencies - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - with: - run_install: true - - - name: Configure Turborepo Cache - uses: rharkor/caching-for-turbo@2b4b5b14a8d16b8556a58993a8ac331d56d8906d # v2.3.2 - - - name: Build Project - run: ${{ inputs.build-command }} - shell: bash diff --git a/.github/actions/setup-nodejs-blacksmith/action.yml b/.github/actions/setup-nodejs/action.yml similarity index 56% rename from .github/actions/setup-nodejs-blacksmith/action.yml rename to .github/actions/setup-nodejs/action.yml index f4df26107e819..d3172ea993edd 100644 --- a/.github/actions/setup-nodejs-blacksmith/action.yml +++ b/.github/actions/setup-nodejs/action.yml @@ -1,4 +1,8 @@ -name: 'Blacksmith Node.js Build Setup' +# This action works transparently on both Blacksmith and GitHub-hosted runners. +# Blacksmith runners benefit from transparent caching and optional Docker layer caching. +# GitHub-hosted runners use standard GitHub Actions caching. + +name: 'Node.js Build Setup' description: 'Configures Node.js with pnpm, installs dependencies, enables Turborepo caching, (optional) sets up Docker layer caching, and builds the project or an optional command.' inputs: @@ -7,7 +11,7 @@ inputs: required: false default: '22.x' enable-docker-cache: - description: 'Whether to set up Blacksmith Buildx for Docker layer caching.' + description: 'Whether to set up Blacksmith Buildx for Docker layer caching (Blacksmith runners only).' required: false default: 'false' type: boolean @@ -20,22 +24,25 @@ inputs: runs: using: 'composite' steps: + - name: Setup pnpm + uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 + - name: Setup Node.js - uses: useblacksmith/setup-node@65c6ca86fdeb0ab3d85e78f57e4f6a7e4780b391 # v5.0.4 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version: ${{ inputs.node-version }} + cache: 'pnpm' - - name: Setup pnpm and Install Dependencies - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - with: - run_install: true + - name: Install Dependencies + run: pnpm install --frozen-lockfile + shell: bash - name: Configure Turborepo Cache - uses: useblacksmith/caching-for-turbo@bafb57e7ebdbf1185762286ec94d24648cd3938a # v1 + uses: rharkor/caching-for-turbo@cda201ff2b32699a2ae9f59704db029e3dde4fbd # v2.3.5 - name: Setup Docker Builder for Docker Cache if: ${{ inputs.enable-docker-cache == 'true' }} - uses: useblacksmith/setup-docker-builder@0b434dfbb431f4e3a2bcee7a773a56bd363184c5 # v1 + uses: useblacksmith/setup-docker-builder@53647ab5afe8827af5623b35bd4302eabd41619f # v1.2.0 - name: Build Project run: ${{ inputs.build-command }} diff --git a/.github/scripts/docker/docker-config.mjs b/.github/scripts/docker/docker-config.mjs index cbd35faff7d82..972631c9e5f75 100644 --- a/.github/scripts/docker/docker-config.mjs +++ b/.github/scripts/docker/docker-config.mjs @@ -31,7 +31,7 @@ class BuildContext { case 'pull_request': context.version = `pr-${pr}`; context.release_type = 'dev'; - context.push_to_ghcr = false; + context.platforms = ['linux/amd64']; break; case 'workflow_dispatch': diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index c549c5a31585e..fb56db5e8d4c3 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -34,7 +34,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Node.js and Build - uses: ./.github/actions/setup-nodejs-github + uses: ./.github/actions/setup-nodejs with: build-command: pnpm build diff --git a/.github/workflows/check-documentation-urls.yml b/.github/workflows/check-documentation-urls.yml index 97fc6c8fbf51c..6d1f1330cd49e 100644 --- a/.github/workflows/check-documentation-urls.yml +++ b/.github/workflows/check-documentation-urls.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node.js - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: build-command: turbo build --filter=*nodes* diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index a99932c2f53ac..8d2042c65a85f 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -46,7 +46,7 @@ jobs: fetch-depth: 0 - name: Setup Node.js - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: build-command: pnpm run build --filter=@n8n/utils --filter=@n8n/vitest-config --filter=@n8n/design-system diff --git a/.github/workflows/ci-evals.yml b/.github/workflows/ci-evals.yml index a2d8f4688b989..2af1bea9c4b27 100644 --- a/.github/workflows/ci-evals.yml +++ b/.github/workflows/ci-evals.yml @@ -45,7 +45,7 @@ jobs: echo "LANGSMITH_DATASET_NAME=$DATASET" >> "$GITHUB_ENV" - name: Setup and Build - uses: ./.github/actions/setup-nodejs-blacksmith + uses: ./.github/actions/setup-nodejs - name: Install uv uses: astral-sh/setup-uv@d9e0f98d3fc6adb07d1e3d37f3043649ddad06a1 # 6.5.0 diff --git a/.github/workflows/ci-manual-build-unit-tests.yml b/.github/workflows/ci-manual-build-unit-tests.yml index dcacc0b9b11f0..abdf103afd8d2 100644 --- a/.github/workflows/ci-manual-build-unit-tests.yml +++ b/.github/workflows/ci-manual-build-unit-tests.yml @@ -55,7 +55,7 @@ jobs: ref: ${{ inputs.ref }} - name: Setup and Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs - name: Run format check run: pnpm format:check diff --git a/.github/workflows/ci-master.yml b/.github/workflows/ci-master.yml index c9d782cc0fe7e..f2c7203584fbd 100644 --- a/.github/workflows/ci-master.yml +++ b/.github/workflows/ci-master.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup and Build - uses: ./.github/actions/setup-nodejs-github + uses: ./.github/actions/setup-nodejs unit-test: name: Unit tests diff --git a/.github/workflows/ci-postgres-mysql.yml b/.github/workflows/ci-postgres-mysql.yml index 39324e8d43902..3b569979e63e8 100644 --- a/.github/workflows/ci-postgres-mysql.yml +++ b/.github/workflows/ci-postgres-mysql.yml @@ -19,7 +19,7 @@ on: concurrency: group: db-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: false + cancel-in-progress: true env: NODE_OPTIONS: '--max-old-space-size=3072' @@ -33,7 +33,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup and Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs sqlite-pooled: name: SQLite Pooled @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup and Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs - name: Test SQLite Pooled working-directory: packages/cli @@ -70,7 +70,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup and Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs - name: Start MariaDB uses: isbang/compose-action@802a148945af6399a338c7906c267331b39a71af # v2.0.0 @@ -99,7 +99,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup and Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs - name: Start MySQL uses: isbang/compose-action@802a148945af6399a338c7906c267331b39a71af # v2.0.0 @@ -124,7 +124,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup and Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs - name: Start Postgres uses: isbang/compose-action@802a148945af6399a338c7906c267331b39a71af # v2.0.0 diff --git a/.github/workflows/ci-pull-requests.yml b/.github/workflows/ci-pull-requests.yml index b7734e1181fbc..c97655c79b9ae 100644 --- a/.github/workflows/ci-pull-requests.yml +++ b/.github/workflows/ci-pull-requests.yml @@ -2,9 +2,10 @@ name: Build, unit test and lint branch on: pull_request: + merge_group: concurrency: - group: ci-${{ github.event.pull_request.number || github.ref }} + group: ci-${{ github.event.pull_request.number || github.event.merge_group.head_sha || github.ref }} cancel-in-progress: true env: @@ -19,10 +20,16 @@ jobs: outputs: frontend_changed: ${{ steps.paths-filter.outputs.frontend == 'true' }} non_python_changed: ${{ steps.paths-filter.outputs.non-python == 'true' }} + commit_sha: ${{ steps.commit-sha.outputs.sha }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: - ref: refs/pull/${{ github.event.pull_request.number }}/merge + # Use merge_group SHA when in merge queue, otherwise PR merge ref + ref: ${{ github.event_name == 'merge_group' && github.event.merge_group.head_sha || format('refs/pull/{0}/merge', github.event.pull_request.number) }} + + - name: Capture commit SHA for cache consistency + id: commit-sha + run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" - name: Check for frontend changes uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 @@ -41,7 +48,7 @@ jobs: - '!packages/@n8n/task-runner-python/**' - name: Setup and Build if: steps.paths-filter.outputs.non-python == 'true' - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs - name: Run format check if: steps.paths-filter.outputs.non-python == 'true' @@ -63,16 +70,16 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: - ref: refs/pull/${{ github.event.pull_request.number }}/merge + ref: ${{ needs.install-and-build.outputs.commit_sha }} - name: Setup pnpm CLI - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 + uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version: '22.x' - cache: pnpm + cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile @@ -92,7 +99,7 @@ jobs: uses: ./.github/workflows/units-tests-reusable.yml needs: install-and-build with: - ref: refs/pull/${{ github.event.pull_request.number }}/merge + ref: ${{ needs.install-and-build.outputs.commit_sha }} collectCoverage: true secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} @@ -105,10 +112,10 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: - ref: refs/pull/${{ github.event.pull_request.number }}/merge + ref: ${{ needs.install-and-build.outputs.commit_sha }} - name: Setup Node.js - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: build-command: pnpm typecheck @@ -118,13 +125,15 @@ jobs: uses: ./.github/workflows/linting-reusable.yml needs: install-and-build with: - ref: refs/pull/${{ github.event.pull_request.number }}/merge + ref: ${{ needs.install-and-build.outputs.commit_sha }} e2e-tests: name: E2E Tests - needs: [install-and-build] + needs: install-and-build if: needs.install-and-build.outputs.non_python_changed == 'true' uses: ./.github/workflows/playwright-test-ci.yml + with: + branch: ${{ needs.install-and-build.outputs.commit_sha }} secrets: inherit # This job is required by GitHub branch protection rules. diff --git a/.github/workflows/data-tooling.yml b/.github/workflows/data-tooling.yml index 80fa385a9f305..4085715055a99 100644 --- a/.github/workflows/data-tooling.yml +++ b/.github/workflows/data-tooling.yml @@ -31,7 +31,7 @@ jobs: - packages/cli/** - name: Setup, build and export sqlite if: steps.paths-filter.outputs.db == 'true' - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: build-command: | pnpm build @@ -66,7 +66,7 @@ jobs: - name: Setup and Build if: steps.paths-filter.outputs.db == 'true' - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs - name: Start Postgres if: steps.paths-filter.outputs.db == 'true' diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index 2a5a636fee024..474fcb943de05 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -86,9 +86,10 @@ jobs: fetch-depth: 0 - name: Setup and Build - uses: ./.github/actions/setup-nodejs-blacksmith + uses: ./.github/actions/setup-nodejs with: build-command: pnpm build:n8n + enable-docker-cache: 'true' - name: Determine Docker tags for all images id: determine-tags @@ -104,9 +105,6 @@ jobs: echo "${key}: ${value%%,*}..." # Show first tag for brevity done - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - - name: Login to GitHub Container Registry if: needs.determine-build-context.outputs.push_enabled == 'true' uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 @@ -125,7 +123,7 @@ jobs: password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push n8n Docker image - uses: useblacksmith/build-push-action@574eb0ee0b59c6a687ace24192f0727dfb65d6d7 # v1.2 + uses: useblacksmith/build-push-action@30c71162f16ea2c27c3e21523255d209b8b538c1 # v2 with: context: . file: ./docker/images/n8n/Dockerfile @@ -140,7 +138,7 @@ jobs: tags: ${{ steps.determine-tags.outputs.n8n_tags }} - name: Build and push task runners Docker image (Alpine) - uses: useblacksmith/build-push-action@574eb0ee0b59c6a687ace24192f0727dfb65d6d7 # v1.2 + uses: useblacksmith/build-push-action@30c71162f16ea2c27c3e21523255d209b8b538c1 # v2 with: context: . file: ./docker/images/runners/Dockerfile @@ -155,7 +153,7 @@ jobs: tags: ${{ steps.determine-tags.outputs.runners_tags }} - name: Build and push task runners Docker image (distroless) - uses: useblacksmith/build-push-action@574eb0ee0b59c6a687ace24192f0727dfb65d6d7 # v1.2 + uses: useblacksmith/build-push-action@30c71162f16ea2c27c3e21523255d209b8b538c1 # v2 with: context: . file: ./docker/images/runners/Dockerfile.distroless diff --git a/.github/workflows/linting-reusable.yml b/.github/workflows/linting-reusable.yml index 9a069831854d4..6f928e8b00c74 100644 --- a/.github/workflows/linting-reusable.yml +++ b/.github/workflows/linting-reusable.yml @@ -27,7 +27,7 @@ jobs: ref: ${{ inputs.ref }} - name: Build and Test - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: build-command: pnpm lint node-version: ${{ inputs.nodeVersion }} diff --git a/.github/workflows/playwright-test-ci.yml b/.github/workflows/playwright-test-ci.yml index b438301908dea..33b5b4129b1fd 100644 --- a/.github/workflows/playwright-test-ci.yml +++ b/.github/workflows/playwright-test-ci.yml @@ -2,15 +2,23 @@ name: E2E Tests for CI on: workflow_call: + inputs: + branch: + description: 'GitHub branch/ref to test' + required: false + type: string + default: '' jobs: # Multi-main: postgres + redis + caddy + 2 mains + 1 worker # Only runs for internal PRs (not community/fork PRs) + # Builds Docker images locally per shard for faster parallel execution multi-main-ui: name: 'Multi-Main: UI' if: ${{ !github.event.pull_request.head.repo.fork }} uses: ./.github/workflows/playwright-test-reusable.yml with: + branch: ${{ inputs.branch }} test-mode: docker-build test-command: pnpm --filter=n8n-playwright test:container:multi-main:ui shards: '[1, 2, 3, 4, 5, 6, 7, 8]' @@ -23,6 +31,7 @@ jobs: if: ${{ !github.event.pull_request.head.repo.fork }} uses: ./.github/workflows/playwright-test-reusable.yml with: + branch: ${{ inputs.branch }} test-mode: docker-build test-command: pnpm --filter=n8n-playwright test:container:multi-main:isolated shards: '[1]' @@ -37,6 +46,7 @@ jobs: if: ${{ github.event.pull_request.head.repo.fork }} uses: ./.github/workflows/playwright-test-reusable.yml with: + branch: ${{ inputs.branch }} test-mode: local test-command: pnpm --filter=n8n-playwright test:local shards: '[1, 2, 3, 4, 5]' @@ -48,6 +58,7 @@ jobs: if: ${{ github.event.pull_request.head.repo.fork }} uses: ./.github/workflows/playwright-test-reusable.yml with: + branch: ${{ inputs.branch }} test-mode: local test-command: pnpm --filter=n8n-playwright test:local:isolated shards: '[1]' diff --git a/.github/workflows/playwright-test-coverage.yml b/.github/workflows/playwright-test-coverage.yml index cdcadef6f5da2..a5d1ff261ac81 100644 --- a/.github/workflows/playwright-test-coverage.yml +++ b/.github/workflows/playwright-test-coverage.yml @@ -6,10 +6,10 @@ on: workflow_dispatch: # Allow manual triggering env: - PLAYWRIGHT_BROWSERS_PATH: packages/testing/playwright/ms-playwright-cache NODE_OPTIONS: --max-old-space-size=16384 TESTCONTAINERS_RYUK_DISABLED: true PLAYWRIGHT_WORKERS: 4 + PLAYWRIGHT_BROWSERS_PATH: packages/testing/playwright/.playwright-browsers jobs: coverage: @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Setup Environment - uses: ./.github/actions/setup-nodejs-blacksmith + uses: ./.github/actions/setup-nodejs env: INCLUDE_TEST_CONTROLLER: 'true' @@ -31,7 +31,7 @@ jobs: INCLUDE_TEST_CONTROLLER: 'true' - name: Install Browsers - run: pnpm turbo install-browsers:ci + run: pnpm turbo run install-browsers --filter=n8n-playwright - name: Run Container Coverage Tests id: coverage-tests diff --git a/.github/workflows/playwright-test-reusable.yml b/.github/workflows/playwright-test-reusable.yml index d51a4534b906e..526e4097b83cb 100644 --- a/.github/workflows/playwright-test-reusable.yml +++ b/.github/workflows/playwright-test-reusable.yml @@ -23,7 +23,7 @@ on: default: '[1, 2, 3, 4, 5, 6, 7, 8]' type: string docker-image: - description: 'Docker image to use (for docker-pull mode)' + description: 'Docker image to use (for docker-pull mode). The runners image is derived automatically from the n8n image.' required: false default: 'n8nio/n8n:nightly' type: string @@ -53,13 +53,16 @@ on: required: false env: - PLAYWRIGHT_BROWSERS_PATH: packages/testing/playwright/ms-playwright-cache - NODE_OPTIONS: --max-old-space-size=3072 + NODE_OPTIONS: ${{ contains(inputs.runner, '2vcpu') && '--max-old-space-size=6144' || '' }} # Disable Ryuk to avoid issues with Docker since it needs privileged access, containers are cleaned on teardown anyway TESTCONTAINERS_RYUK_DISABLED: true - PLAYWRIGHT_WORKERS: ${{ inputs.workers || '2' }} # Configurable workers, defaults to 2 to reduce resource contention + PLAYWRIGHT_WORKERS: ${{ inputs.workers != '' && inputs.workers || '2' }} # Must match CI's COVERAGE_ENABLED to ensure Turbo cache hits (it's a globalEnv in turbo.json) COVERAGE_ENABLED: 'true' + # Browser cache location - must match install-browsers script + PLAYWRIGHT_BROWSERS_PATH: packages/testing/playwright/.playwright-browsers + N8N_DOCKER_IMAGE: ${{ inputs.test-mode == 'docker-build' && 'n8nio/n8n:local' || inputs.docker-image }} + N8N_SKIP_LICENSES: 'true' jobs: test: @@ -79,28 +82,24 @@ jobs: ref: ${{ inputs.branch || github.ref }} - name: Setup Environment - uses: ./.github/actions/setup-nodejs-blacksmith + uses: ./.github/actions/setup-nodejs with: - build-command: ${{ inputs.test-mode == 'docker-build' && 'pnpm build:docker' || 'pnpm turbo build:playwright' }} - enable-docker-cache: ${{ inputs.test-mode != 'local' }} + # docker-build: build app + docker image locally + # docker-pull: no build needed, image is pre-built + # local: build app for local server + build-command: ${{ inputs.test-mode == 'docker-build' && 'pnpm build:docker' || (inputs.test-mode == 'local' && 'pnpm build' || '') }} + enable-docker-cache: ${{ inputs.test-mode == 'docker-build' }} env: INCLUDE_TEST_CONTROLLER: ${{ inputs.test-mode == 'docker-build' && 'true' || '' }} - name: Install Browsers - if: inputs.test-mode == 'docker-build' - run: pnpm turbo install-browsers:ci + run: pnpm turbo run install-browsers --filter=n8n-playwright - name: Pre-pull Test Container Images if: ${{ !contains(inputs.test-command, 'test:local') }} run: | # Pre-pull all test container images to avoid network changes during test execution npx tsx packages/testing/containers/pull-test-images.ts || true - env: - N8N_DOCKER_IMAGE: ${{ inputs.test-mode == 'docker-build' && 'n8nio/n8n:local' || inputs.docker-image }} - - - name: Prepare Test Image - if: inputs.test-mode == 'docker-pull' - run: pnpm --filter=n8n-playwright prepare-test-image ${{ inputs.docker-image }} - name: Run Tests run: | @@ -108,7 +107,6 @@ jobs: --shard=${{ matrix.shard }}/${{ strategy.job-total }} \ --workers=${{ env.PLAYWRIGHT_WORKERS }} env: - N8N_DOCKER_IMAGE: ${{ inputs.test-mode == 'docker-build' && 'n8nio/n8n:local' || inputs.docker-image }} CURRENTS_RECORD_KEY: ${{ secrets.CURRENTS_RECORD_KEY }} QA_PERFORMANCE_METRICS_WEBHOOK_URL: ${{ secrets.QA_PERFORMANCE_METRICS_WEBHOOK_URL }} QA_PERFORMANCE_METRICS_WEBHOOK_USER: ${{ secrets.QA_PERFORMANCE_METRICS_WEBHOOK_USER }} diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 60e32beb27b08..f26f980eb5e4f 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup and Build ARM64 - uses: ./.github/actions/setup-nodejs-blacksmith + uses: ./.github/actions/setup-nodejs env: N8N_FAIL_ON_POPULARITY_FETCH_ERROR: true @@ -53,7 +53,7 @@ jobs: fi - name: Setup and Build - uses: ./.github/actions/setup-nodejs-github + uses: ./.github/actions/setup-nodejs env: N8N_FAIL_ON_POPULARITY_FETCH_ERROR: true @@ -133,7 +133,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Restore Turbo Cache - uses: ./.github/actions/setup-nodejs-github + uses: ./.github/actions/setup-nodejs - name: Create a frontend release uses: getsentry/action-release@e769183448303de84c5a06aaaddf9da7be26d6c7 # v1.7.0 diff --git a/.github/workflows/release-standalone-package.yml b/.github/workflows/release-standalone-package.yml index f5dd2a9db0075..681b92c5b0fdb 100644 --- a/.github/workflows/release-standalone-package.yml +++ b/.github/workflows/release-standalone-package.yml @@ -41,7 +41,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup and Build - uses: ./.github/actions/setup-nodejs-github + uses: ./.github/actions/setup-nodejs with: build-command: 'pnpm turbo build --filter "...${{ github.event.inputs.package }}"' diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index 8174a49841d72..e859c37a7accc 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -28,7 +28,7 @@ jobs: with: fetch-depth: 0 - name: Setup Node.js - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: build-command: pnpm run build --filter=@n8n/utils --filter=@n8n/vitest-config --filter=@n8n/design-system diff --git a/.github/workflows/sync-public-api-docs.yml b/.github/workflows/sync-public-api-docs.yml index 4ba97452a63a0..b105262730985 100644 --- a/.github/workflows/sync-public-api-docs.yml +++ b/.github/workflows/sync-public-api-docs.yml @@ -31,10 +31,10 @@ jobs: fetch-depth: 0 # Fetch all history for git log - name: Setup PNPM - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 + uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version: '22.x' cache: 'pnpm' @@ -107,7 +107,7 @@ jobs: # Find all commits between the last success and now that touched the relevant files # NOTE: The pathspecs here mirror the workflow's 'paths' trigger for precision - RELEVANT_COMMITS=$(git log --pretty=format:"- [%h](https://github.com/${{ github.repository }}/commit/%H) %s" $LAST_SUCCESS_SHA..${{ github.sha }} -- \ + RELEVANT_COMMITS=$(git log --pretty=format:"- [%h](https://github.com/${{ github.repository }}/commit/%H) %s" "${LAST_SUCCESS_SHA}..${{ github.sha }}" -- \ 'packages/cli/src/public-api/**/*.css' \ 'packages/cli/src/public-api/**/*.yaml' \ 'packages/cli/src/public-api/**/*.yml') @@ -129,9 +129,11 @@ jobs: SOURCE_LINK="Source commit(s):"$'\n'"$RELEVANT_COMMITS" fi - echo "source_link<> "$GITHUB_OUTPUT" - echo "$SOURCE_LINK" >> "$GITHUB_OUTPUT" - echo "EOF" >> "$GITHUB_OUTPUT" + { + echo "source_link<> "$GITHUB_OUTPUT" - name: Create PR in Docs Repo if: steps.verify_file.outputs.file_exists == 'true' diff --git a/.github/workflows/test-workflows-callable.yml b/.github/workflows/test-workflows-callable.yml index 5748ef647f196..f684b9af0158d 100644 --- a/.github/workflows/test-workflows-callable.yml +++ b/.github/workflows/test-workflows-callable.yml @@ -34,7 +34,7 @@ jobs: ref: ${{ inputs.git_ref }} - name: Set up Environment - uses: ./.github/actions/setup-nodejs-blacksmith + uses: ./.github/actions/setup-nodejs - name: Set up Workflow Tests run: pnpm --filter=n8n-playwright test:workflows:setup diff --git a/.github/workflows/units-tests-reusable.yml b/.github/workflows/units-tests-reusable.yml index 07d12979c9003..c1048a45a8750 100644 --- a/.github/workflows/units-tests-reusable.yml +++ b/.github/workflows/units-tests-reusable.yml @@ -37,7 +37,7 @@ jobs: ref: ${{ inputs.ref }} - name: Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: node-version: ${{ inputs.nodeVersion }} @@ -70,7 +70,7 @@ jobs: ref: ${{ inputs.ref }} - name: Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: node-version: ${{ inputs.nodeVersion }} @@ -103,7 +103,7 @@ jobs: ref: ${{ inputs.ref }} - name: Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: node-version: ${{ inputs.nodeVersion }} @@ -140,7 +140,7 @@ jobs: ref: ${{ inputs.ref }} - name: Build - uses: n8n-io/n8n/.github/actions/setup-nodejs-blacksmith@f5fbbbe0a28a886451c886cac6b49192a39b0eea # v1.104.1 + uses: ./.github/actions/setup-nodejs with: node-version: ${{ inputs.nodeVersion }} diff --git a/.github/workflows/update-node-popularity.yml b/.github/workflows/update-node-popularity.yml index 9f42729310baf..97163b73c19c7 100644 --- a/.github/workflows/update-node-popularity.yml +++ b/.github/workflows/update-node-popularity.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Node.js and Dependencies - uses: ./.github/actions/setup-nodejs-github + uses: ./.github/actions/setup-nodejs with: build-command: '' # Skip build, we only need to fetch data diff --git a/.gitignore b/.gitignore index 54b0222a7e943..7cb236a46c029 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,7 @@ test-results.json *.0x packages/testing/playwright/playwright-report packages/testing/playwright/test-results -packages/testing/playwright/ms-playwright-cache +packages/testing/playwright/.playwright-browsers test-results/ compiled_app_output trivy_report* diff --git a/packages/testing/containers/test-containers.ts b/packages/testing/containers/test-containers.ts index 1a33819812f7b..aafdb5dd94524 100644 --- a/packages/testing/containers/test-containers.ts +++ b/packages/testing/containers/test-containers.ts @@ -5,18 +5,15 @@ // Use N8N_DOCKER_IMAGE env var if set, otherwise default to 'n8nio/n8n:local' const n8nImage = process.env.N8N_DOCKER_IMAGE ?? 'n8nio/n8n:local'; -// Derive the task runner image from the n8n image tag for consistency +// Derive the task runner image from the n8n image for consistency // e.g., 'n8nio/n8n:local' -> 'n8nio/runners:local' -// e.g., 'n8nio/n8n:1.50.0' -> 'n8nio/runners:1.50.0' +// e.g., 'ghcr.io/n8n-io/n8n:pr-123' -> 'ghcr.io/n8n-io/runners:pr-123' function getTaskRunnerImage(): string { // Allow explicit override via env var if (process.env.N8N_RUNNERS_IMAGE) { return process.env.N8N_RUNNERS_IMAGE; } - - // Extract the tag from the n8n image and apply it to runners - const tag = n8nImage.split(':').at(-1) ?? 'local'; - return `n8nio/runners:${tag}`; + return n8nImage.replace(/\/n8n:/, '/runners:'); } export const TEST_CONTAINER_IMAGES = { diff --git a/packages/testing/playwright/package.json b/packages/testing/playwright/package.json index 8b32bc83443c0..4fafd7aa435bd 100644 --- a/packages/testing/playwright/package.json +++ b/packages/testing/playwright/package.json @@ -27,8 +27,7 @@ "test:workflows:update": "playwright test --project=cli-workflows --update-snapshots", "coverage:report": "node scripts/generate-coverage-report.js", "coverage:clean": "rm -rf coverage .nyc_output", - "install-browsers:local": "playwright install chromium --with-deps", - "install-browsers:ci": "PLAYWRIGHT_BROWSERS_PATH=./ms-playwright-cache playwright install chromium --with-deps", + "install-browsers": "PLAYWRIGHT_BROWSERS_PATH=./.playwright-browsers playwright install chromium --with-deps", "browsers:uninstall": "playwright uninstall --all", "prepare-test-image": "node scripts/build-test-image.mjs", "lint": "eslint . --quiet", diff --git a/scripts/build-n8n.mjs b/scripts/build-n8n.mjs index 1f1d35c4ed12a..531cd462b0522 100755 --- a/scripts/build-n8n.mjs +++ b/scripts/build-n8n.mjs @@ -105,16 +105,21 @@ try { buildProcess.pipe(process.stdout); await buildProcess; - // Generate third-party licenses for production build - echo(chalk.yellow('INFO: Generating third-party licenses...')); - try { - const licenseProcess = $`cd ${config.rootDir} && node scripts/generate-third-party-licenses.mjs`; - licenseProcess.pipe(process.stdout); - await licenseProcess; - echo(chalk.green('✅ Third-party licenses generated successfully')); - } catch (error) { - echo(chalk.yellow('⚠️ Warning: Third-party license generation failed, continuing build...')); - echo(chalk.red(`ERROR: License generation failed: ${error.message}`)); + // Generate third-party licenses for production builds + // Skip with N8N_SKIP_LICENSES=true for CI test builds + if (process.env.N8N_SKIP_LICENSES !== 'true') { + echo(chalk.yellow('INFO: Generating third-party licenses...')); + try { + const licenseProcess = $`cd ${config.rootDir} && node scripts/generate-third-party-licenses.mjs`; + licenseProcess.pipe(process.stdout); + await licenseProcess; + echo(chalk.green('✅ Third-party licenses generated successfully')); + } catch (error) { + echo(chalk.yellow('⚠️ Warning: Third-party license generation failed, continuing build...')); + echo(chalk.red(`ERROR: License generation failed: ${error.message}`)); + } + } else { + echo(chalk.gray('INFO: Skipping license generation (N8N_SKIP_LICENSES=true)')); } echo(chalk.green('✅ pnpm install and build completed')); diff --git a/turbo.json b/turbo.json index 6085621b98682..9c8b20fe6e221 100644 --- a/turbo.json +++ b/turbo.json @@ -35,21 +35,13 @@ }, "watch": { "cache": false, "persistent": true }, "dev": { "cache": false, "persistent": true }, - "build:playwright": { - "dependsOn": ["install-browsers:ci", "build"] - }, - "install-browsers:ci": { + "install-browsers": { "cache": true, - "inputs": ["package.json"], - "outputs": ["ms-playwright-cache/**"], + "inputs": ["$TURBO_DEFAULT$", "../../pnpm-lock.yaml"], + "outputs": [".playwright-browsers/**"], "env": ["PLAYWRIGHT_BROWSERS_PATH"] }, - "install-browsers:local": { - "cache": false, - "inputs": ["package.json"] - }, "test:container:standard": { - "dependsOn": ["install-browsers:local"], "env": ["E2E_TESTS"], "cache": false }