ci: Run format check alongside build (no-changelog) (#39387)

This commit is contained in:
Declan Carroll 2026-09-23 12:51:51 +00:00 committed by GitHub
parent 1f873774ab
commit 507a1eb419
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 21 deletions

View File

@ -143,8 +143,8 @@ export function getAddedFiles(baseRef, headRef = 'HEAD') {
}
/**
* Deepen the shallow clone until the merge base between the fetched base ref
* (FETCH_HEAD) and headRef is reliably reachable.
* Fetch the base ref, then deepen only if its merge base with headRef is not
* reliably reachable from the checkout.
*
* A single fixed deepen is not enough for stale PRs whose divergence point is
* older than the shallow boundary. We fetch with an exponentially growing
@ -159,7 +159,12 @@ export function getAddedFiles(baseRef, headRef = 'HEAD') {
function fetchUntilMergeBase(baseRef, headRef) {
let step = Number(process.env.CI_FILTER_DEEPEN_STEP) || 200;
const maxDeepen = Number(process.env.CI_FILTER_MAX_DEEPEN) || 20_000;
deepenFetch(baseRef, step, maxDeepen);
// A PR merge checkout already has the base commit as its first parent.
const hasBaseCommit = headRef === 'HEAD^2' && hasCommit('HEAD^1');
const depth = isShallow() && !hasBaseCommit ? `--depth=${step} ` : '';
execSync(`git fetch --no-tags --prune --filter=blob:none ${depth}origin ${baseRef}`, {
stdio: 'pipe',
});
while (!hasReliableMergeBase(headRef)) {
if (!isShallow()) {
@ -167,8 +172,17 @@ function fetchUntilMergeBase(baseRef, headRef) {
`No merge base between FETCH_HEAD and ${headRef} after fetching the full history of "${baseRef}" (unrelated histories).`,
);
}
step *= 2;
deepenFetch(baseRef, step, maxDeepen);
step *= 2;
}
}
function hasCommit(ref) {
try {
execSync(`git cat-file -e ${ref}^{commit}`, { stdio: 'pipe' });
return true;
} catch {
return false;
}
}

View File

@ -45,6 +45,8 @@ jobs:
with:
# 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) }}
# Include recent history so the PR filter can reuse the checkout.
fetch-depth: 200
- name: Capture commit SHA for cache consistency
id: commit-sha
@ -124,7 +126,6 @@ jobs:
packages/frontend/@n8n/chat/**
packages/frontend/@n8n/frontend-vite-config/**
turbo.json
.github/workflows/ci-pull-requests.yml
.github/workflows/test-frontend-declarations-reusable.yml
.github/actions/setup-nodejs/**
workflows: .github/**
@ -151,6 +152,7 @@ jobs:
# data plane, and the executions code merges v1 and v2 rows. A path
# this list misses skips `e2e-engine`, and `required-checks` counts
# a skipped job as a pass, so the gap would be silent.
# Use force-engine-e2e when changing the engine job in this workflow.
engine-e2e:
packages/@n8n/engine/**
packages/@n8n/node-engine-compatibility/**
@ -163,7 +165,6 @@ jobs:
packages/cli/src/workflow-runner.ts
packages/testing/containers/**
packages/testing/playwright/**
.github/workflows/ci-pull-requests.yml
instance-ai-workflow-eval:
packages/@n8n/instance-ai/src/**
packages/@n8n/instance-ai/evaluations/**
@ -224,10 +225,6 @@ jobs:
if: fromJSON(steps.ci-filter.outputs.results).ci
run: node scripts/turbo-critical-path.mjs >> "$GITHUB_STEP_SUMMARY"
- name: Run format check
if: fromJSON(steps.ci-filter.outputs.results).ci
run: pnpm format:check
- name: Generate shard matrix
id: generate-matrix
if: fromJSON(steps.ci-filter.outputs.results).ci || fromJSON(steps.ci-filter.outputs.results).e2e
@ -262,11 +259,34 @@ jobs:
echo "Affected packages: $PACKAGES"
echo "list=$PACKAGES" >> "$GITHUB_OUTPUT"
format-check:
name: Format check
runs-on: ${{ vars.RUNNER_PROVIDER == 'github' && 'ubuntu-latest' || 'blacksmith-2vcpu-ubuntu-2204' }}
permissions:
contents: read
steps:
- uses: useblacksmith/checkout@bcec731f1eb1367240608d1c889a75b96db6ec53 # v1.5.0
with:
ref: ${{ github.event_name == 'merge_group' && github.event.merge_group.head_sha || format('refs/pull/{0}/merge', github.event.pull_request.number) }}
- name: Install format tools
uses: ./.github/actions/setup-nodejs
with:
install-command: pnpm install --frozen-lockfile --filter n8n-monorepo --ignore-scripts
build-command: ''
# Keep the partial pnpm store separate from the full install cache.
cache-dependency-path: |
pnpm-lock.yaml
package.json
- name: Run format check
run: pnpm format:check
unit-test:
name: Unit tests
if: needs.install-and-build.outputs.unit == 'true'
uses: ./.github/workflows/test-unit-reusable.yml
needs: install-and-build
needs: [install-and-build, format-check]
with:
ref: ${{ needs.install-and-build.outputs.commit_sha }}
collectCoverage: ${{ github.event_name != 'merge_group' }}
@ -278,7 +298,7 @@ jobs:
name: Typecheck
if: needs.install-and-build.outputs.ci == 'true'
runs-on: ${{ vars.RUNNER_PROVIDER == 'github' && 'ubuntu-latest' || 'blacksmith-4vcpu-ubuntu-2204' }}
needs: install-and-build
needs: [install-and-build, format-check]
env:
# Inherited by every worker turbo spawns, so the real budget is
# concurrency x cap: 2 x 6 GB fits the runner's 15.2 GB.
@ -299,7 +319,7 @@ jobs:
name: Lint
if: needs.install-and-build.outputs.ci == 'true'
uses: ./.github/workflows/test-linting-reusable.yml
needs: install-and-build
needs: [install-and-build, format-check]
with:
ref: ${{ needs.install-and-build.outputs.commit_sha }}
@ -307,7 +327,7 @@ jobs:
name: Check packaging
if: needs.install-and-build.outputs.ci == 'true'
runs-on: ${{ vars.RUNNER_PROVIDER == 'github' && 'ubuntu-latest' || 'blacksmith-4vcpu-ubuntu-2204' }}
needs: install-and-build
needs: [install-and-build, format-check]
steps:
- uses: useblacksmith/checkout@bcec731f1eb1367240608d1c889a75b96db6ec53 # v1.5.0
with:
@ -326,7 +346,7 @@ jobs:
# cache hit instead of racing to rebuild.
prepare-docker:
name: Prepare Docker
needs: install-and-build
needs: [install-and-build, format-check]
if: >-
github.repository == 'n8n-io/n8n' &&
github.event_name != 'merge_group' &&
@ -394,7 +414,7 @@ jobs:
# the production-bundle e2e job bundles around.
dev-server-smoke:
name: Dev-server boot smoke
needs: install-and-build
needs: [install-and-build, format-check]
if: needs.install-and-build.outputs.dev_server_smoke == 'true' && github.event_name != 'merge_group'
uses: ./.github/workflows/test-dev-server-smoke-reusable.yml
with:
@ -407,7 +427,7 @@ jobs:
# release.
frontend-declarations:
name: Frontend declarations
needs: install-and-build
needs: [install-and-build, format-check]
if: needs.install-and-build.outputs.frontend_declarations == 'true'
uses: ./.github/workflows/test-frontend-declarations-reusable.yml
with:
@ -415,7 +435,7 @@ jobs:
db-tests:
name: DB Tests
needs: install-and-build
needs: [install-and-build, format-check]
if: needs.install-and-build.outputs.db == 'true'
uses: ./.github/workflows/test-db-reusable.yml
with:
@ -440,7 +460,7 @@ jobs:
security-checks:
name: Security Checks
needs: install-and-build
needs: [install-and-build, format-check]
if: needs.install-and-build.outputs.workflows == 'true'
uses: ./.github/workflows/sec-ci-reusable.yml
with:
@ -449,7 +469,7 @@ jobs:
workflow-scripts:
name: Workflow scripts
needs: install-and-build
needs: [install-and-build, format-check]
if: needs.install-and-build.outputs.workflow_scripts == 'true'
uses: ./.github/workflows/test-workflow-scripts-reusable.yml
with:
@ -461,10 +481,11 @@ jobs:
# heavy workflow eval. Non-blocking initially; promote to required after stability.
instance-ai-discovery-evals:
name: Instance AI Discovery Evals
needs: install-and-build
needs: [install-and-build, format-check]
if: >-
!cancelled() &&
needs.install-and-build.result == 'success' &&
needs.format-check.result == 'success' &&
needs.install-and-build.outputs.instance_ai_workflow_eval == 'true' &&
github.repository == 'n8n-io/n8n' &&
github.event_name != 'merge_group' &&
@ -481,6 +502,7 @@ jobs:
needs:
[
install-and-build,
format-check,
unit-test,
typecheck,
lint,