Files
twenty/nx.json
T
Charles BochetandGitHub d37ed7e07c Optimize merge queue to only run E2E and integrate prettier into lint (#18459)
## Summary

- **Merge queue optimization**: Created a dedicated
`ci-merge-queue.yaml` workflow that only runs Playwright E2E tests on
`ubuntu-latest-8-cores`. Removed `merge_group` trigger from all 7
existing CI workflows (front, server, shared, website, sdk, zapier,
docker-compose). The merge queue goes from ~30+ parallel jobs to a
single focused E2E job.
- **Label-based merge queue simulation**: Added `run-merge-queue` label
support so developers can trigger the exact merge queue E2E pipeline on
any open PR before it enters the queue.
- **Prettier in lint**: Chained `prettier --check` into `lint` and
`prettier --write` into `lint --configuration=fix` across `nx.json`
defaults, `twenty-front`, and `twenty-server`. Prettier formatting
errors are now caught by `lint` and fixed by `lint:fix` /
`lint:diff-with-main --configuration=fix`.

## After merge (manual repo settings)

Update GitHub branch protection required status checks:
1. Remove old per-workflow merge queue checks (`ci-front-status-check`,
`ci-e2e-status-check`, `ci-server-status-check`, etc.)
2. Add `ci-merge-queue-status-check` as the required check for the merge
queue
2026-03-06 13:20:57 +01:00

298 lines
8.5 KiB
JSON

{
"workspaceLayout": {
"appsDir": "packages",
"libsDir": "packages"
},
"namedInputs": {
"default": ["{projectRoot}/**/*"],
"excludeStories": [
"default",
"!{projectRoot}/.storybook/*",
"!{projectRoot}/**/tsconfig.storybook.json",
"!{projectRoot}/**/*.stories.(ts|tsx)",
"!{projectRoot}/**/__stories__/*"
],
"excludeTests": [
"default",
"!{projectRoot}/**/jest.config.(js|ts)",
"!{projectRoot}/**/tsconfig.spec.json",
"!{projectRoot}/**/*.test.(ts|tsx)",
"!{projectRoot}/**/*.spec.(ts|tsx)",
"!{projectRoot}/**/*.integration-spec.ts",
"!{projectRoot}/**/__tests__/*"
],
"production": [
"default",
"excludeStories",
"excludeTests",
"!{projectRoot}/**/__mocks__/*",
"!{projectRoot}/**/testing/*"
]
},
"targetDefaults": {
"build": {
"cache": true,
"inputs": ["^production", "production"],
"dependsOn": ["^build"]
},
"start": {
"cache": false,
"dependsOn": ["^build"]
},
"lint": {
"executor": "nx:run-commands",
"cache": true,
"options": {
"cwd": "{projectRoot}",
"command": "npx oxlint -c .oxlintrc.json . && (prettier . --check --cache --cache-location ../../.cache/prettier/{projectRoot} --cache-strategy metadata || (echo 'ERROR: Prettier formatting check failed! Fix with: npx nx lint --configuration=fix' && false))"
},
"configurations": {
"ci": {},
"fix": {
"command": "npx oxlint --fix -c .oxlintrc.json . && prettier . --write --cache --cache-location ../../.cache/prettier/{projectRoot} --cache-strategy metadata"
}
},
"dependsOn": ["^build", "twenty-oxlint-rules:build"]
},
"lint:diff-with-main": {
"executor": "nx:run-commands",
"cache": false,
"options": {
"command": "FILES=$(git diff --name-only --diff-filter=d main -- {projectRoot}/ | grep -E '{args.pattern}'); [ -z \"$FILES\" ] && echo 'No changed files.' || (npx oxlint -c {projectRoot}/.oxlintrc.json $FILES && (prettier --check $FILES || (echo 'ERROR: Prettier formatting check failed! Fix with: npx nx lint:diff-with-main --configuration=fix' && false)))",
"pattern": "\\.(ts|tsx|js|jsx)$"
},
"configurations": {
"fix": {
"command": "FILES=$(git diff --name-only --diff-filter=d main -- {projectRoot}/ | grep -E '{args.pattern}'); [ -z \"$FILES\" ] && echo 'No changed files.' || (npx oxlint --fix -c {projectRoot}/.oxlintrc.json $FILES && prettier --write $FILES)"
}
}
},
"fmt": {
"executor": "nx:run-commands",
"cache": true,
"options": {
"cwd": "{projectRoot}",
"command": "prettier {args.files} --check --cache {args.cache} --cache-location {args.cacheLocation} --write {args.write} --cache-strategy {args.cacheStrategy}",
"cache": true,
"cacheLocation": "../../.cache/prettier/{projectRoot}",
"cacheStrategy": "metadata",
"write": false
},
"configurations": {
"ci": {
"cacheStrategy": "content"
},
"fix": {
"write": true
}
},
"dependsOn": ["^build"]
},
"typecheck": {
"executor": "nx:run-commands",
"cache": true,
"options": {
"cwd": "{projectRoot}",
"command": "tsgo -p tsconfig.json"
},
"configurations": {
"watch": {
"command": "tsgo -p tsconfig.json --watch"
}
},
"dependsOn": ["^build"]
},
"test": {
"executor": "@nx/jest:jest",
"cache": true,
"dependsOn": ["^build"],
"inputs": [
"^default",
"excludeStories",
"{workspaceRoot}/jest.preset.js"
],
"outputs": ["{projectRoot}/coverage"],
"options": {
"jestConfig": "{projectRoot}/jest.config.mjs",
"silent": true,
"coverage": true,
"coverageReporters": ["text-summary"],
"cacheDirectory": "../../.cache/jest/{projectRoot}"
},
"configurations": {
"ci": {
"ci": true,
"maxWorkers": 1
},
"coverage": {
"coverageReporters": ["lcov", "text"]
},
"watch": {
"watch": true
}
}
},
"test:e2e": {
"cache": true,
"dependsOn": ["^build"]
},
"storybook:build": {
"executor": "nx:run-commands",
"cache": true,
"inputs": ["^default", "excludeTests"],
"outputs": ["{projectRoot}/{options.output-dir}"],
"options": {
"cwd": "{projectRoot}",
"command": "NODE_OPTIONS='--max-old-space-size=10240' storybook build --test",
"output-dir": "storybook-static",
"config-dir": ".storybook"
},
"dependsOn": ["^build"]
},
"storybook:serve:dev": {
"executor": "nx:run-commands",
"cache": true,
"dependsOn": ["^build"],
"options": {
"cwd": "{projectRoot}",
"command": "storybook dev",
"config-dir": ".storybook"
}
},
"storybook:serve:static": {
"executor": "nx:run-commands",
"dependsOn": ["storybook:build"],
"options": {
"cwd": "{projectRoot}",
"command": "npx http-server {args.staticDir} -a={args.host} --port={args.port} --silent={args.silent}",
"staticDir": "storybook-static",
"host": "localhost",
"port": 6006,
"silent": true
}
},
"storybook:test": {
"executor": "nx:run-commands",
"cache": true,
"inputs": ["^default", "excludeTests"],
"outputs": ["{projectRoot}/coverage/storybook"],
"options": {
"cwd": "{projectRoot}",
"command": "vitest run --coverage --shard={args.shard}",
"shard": "1/1"
}
},
"storybook:test:no-coverage": {
"executor": "nx:run-commands",
"inputs": ["^default", "excludeTests"],
"options": {
"cwd": "{projectRoot}",
"command": "vitest run --shard={args.shard}",
"shard": "1/1"
}
},
"storybook:coverage": {
"executor": "nx:run-commands",
"cache": true,
"inputs": [
"^default",
"excludeTests",
"{projectRoot}/coverage/storybook/coverage-storybook.json"
],
"outputs": [
"{projectRoot}/coverage/storybook",
"!{projectRoot}/coverage/storybook/coverage-storybook.json"
],
"options": {
"command": "npx nyc report --reporter={args.reporter} --reporter=text-summary -t {args.coverageDir} --report-dir {args.coverageDir} --check-coverage={args.checkCoverage} --cwd={projectRoot}",
"coverageDir": "coverage/storybook",
"reporter": "lcov",
"checkCoverage": true
},
"configurations": {
"text": {
"reporter": "text"
}
}
},
"chromatic": {
"executor": "nx:run-commands",
"options": {
"cwd": "{projectRoot}",
"commands": [
{
"command": "nx storybook:build {projectName}",
"forwardAllArgs": false
},
"chromatic --storybook-build-dir=storybook-static {args.ci}"
],
"parallel": false
},
"configurations": {
"ci": {
"ci": "--exit-zero-on-changes"
}
}
},
"@nx/jest:jest": {
"cache": true,
"inputs": [
"^default",
"excludeStories",
"{workspaceRoot}/jest.preset.js"
],
"options": {
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
},
"@nx/vite:build": {
"cache": true,
"dependsOn": ["^build"],
"inputs": ["default", "^default"]
},
"@nx/vitest:test": {
"cache": true,
"inputs": ["default", "^default"]
}
},
"generators": {
"@nx/react": {
"application": {
"style": "@linaria/react",
"bundler": "vite",
"compiler": "swc",
"unitTestRunner": "jest",
"projectNameAndRootFormat": "derived"
},
"library": {
"style": "@linaria/react",
"bundler": "vite",
"compiler": "swc",
"unitTestRunner": "jest",
"projectNameAndRootFormat": "derived"
},
"component": {
"style": "@linaria/react"
}
}
},
"tasksRunnerOptions": {
"default": {
"options": {
"cacheableOperations": ["storybook:build"]
}
}
},
"useInferencePlugins": false,
"defaultBase": "main",
"tui": {
"enabled": false
}
}