chore(deps): bump react-grid-layout from 1.5.2 to 1.5.4 #261
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: [main] | |
| merge_group: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| lint-typecheck: | |
| name: Lint & Typecheck | |
| runs-on: ${{ github.actor == 'dependabot[bot]' && 'ubuntu-latest' || fromJSON('["self-hosted", "linux", "x64"]') }} | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: 'yarn' | |
| - name: Install dependencies | |
| run: yarn install --immutable | |
| - name: Build shared | |
| run: npx nx build twenty-shared | |
| - name: Build oxlint plugin | |
| run: npx nx build twenty-oxlint-rules | |
| - name: Typecheck frontend | |
| run: npx nx typecheck twenty-front | |
| - name: Typecheck server | |
| run: npx nx typecheck twenty-server | |
| - name: Lint frontend | |
| run: npx nx lint twenty-front | |
| - name: Lint server (oxlint) | |
| # oxlint has an intermittent thread panic on large codebases — treat as warning | |
| run: cd packages/twenty-server && npx oxlint --type-aware -c .oxlintrc.json src/ || echo "::warning::oxlint exited non-zero (possible thread panic — known issue)" | |
| continue-on-error: true | |
| - name: Lint server (prettier) | |
| run: cd packages/twenty-server && npx prettier src/ --check | |
| brand-drift: | |
| name: Brand drift check | |
| runs-on: ${{ github.actor == 'dependabot[bot]' && 'ubuntu-latest' || fromJSON('["self-hosted", "linux", "x64"]') }} | |
| timeout-minutes: 5 | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Detect "twenty" in PR-added lines | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| ALLOWLIST_FILE: .brand-drift-allowlist.txt | |
| SCAN_PATHS: 'packages/ README.md NOTICE' | |
| run: | | |
| set -euo pipefail | |
| if [ ! -f "${ALLOWLIST_FILE}" ]; then | |
| echo "::error::Missing ${ALLOWLIST_FILE} at repo root." | |
| exit 1 | |
| fi | |
| mapfile -t ALLOWED < <(grep -vE '^\s*(#|$)' "${ALLOWLIST_FILE}" || true) | |
| is_allowed() { | |
| local candidate="$1" | |
| for entry in "${ALLOWED[@]}"; do | |
| if [ "${candidate}" = "${entry}" ]; then | |
| return 0 | |
| fi | |
| done | |
| return 1 | |
| } | |
| MERGE_BASE=$(git merge-base "${BASE_SHA}" "${HEAD_SHA}") | |
| # shellcheck disable=SC2086 | |
| CHANGED_FILES=$(git diff --name-only --diff-filter=AM \ | |
| "${MERGE_BASE}" "${HEAD_SHA}" -- ${SCAN_PATHS} || true) | |
| if [ -z "${CHANGED_FILES}" ]; then | |
| echo "No files in scope changed in this PR." | |
| exit 0 | |
| fi | |
| violations=0 | |
| while IFS= read -r file; do | |
| [ -z "${file}" ] && continue | |
| if is_allowed "${file}"; then | |
| echo "skip (allowlisted): ${file}" | |
| continue | |
| fi | |
| added=$(git diff -U0 "${MERGE_BASE}" "${HEAD_SHA}" -- "${file}" \ | |
| | grep -E '^\+[^+]' || true) | |
| if [ -z "${added}" ]; then | |
| continue | |
| fi | |
| # Exclude package imports (twenty-shared, twenty-ui, etc.) — those are legitimate | |
| filtered=$(echo "${added}" | grep -ivE "from ['\"]twenty-|require\(['\"]twenty-" || true) | |
| if [ -n "${filtered}" ] && echo "${filtered}" | grep -iqE 'twenty'; then | |
| echo "::error file=${file}::Brand drift: PR adds 'twenty' to ${file}." | |
| echo "${added}" | grep -iE 'twenty' | sed 's/^/ /' | |
| violations=$((violations + 1)) | |
| fi | |
| done <<< "${CHANGED_FILES}" | |
| if [ "${violations}" -gt 0 ]; then | |
| echo "::error::${violations} file(s) introduced 'twenty' outside the brand-drift allowlist." | |
| exit 1 | |
| fi | |
| echo "Brand drift check passed." | |
| # MAIN LANE — full Linux server test coverage, unchanged, but now runs ONLY | |
| # on push to main. PRs and the merge queue get the same suite on the mac | |
| # runner via `server-tests-mac` below (the PR-lane primary gate). Linux test | |
| # coverage is NOT lost — every merge to main still runs this full job on the | |
| # existing [self-hosted, linux, x64] runners. | |
| server-tests: | |
| name: Server unit tests | |
| if: github.event_name == 'push' | |
| runs-on: ${{ github.actor == 'dependabot[bot]' && 'ubuntu-latest' || fromJSON('["self-hosted", "linux", "x64"]') }} | |
| timeout-minutes: 40 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: 'yarn' | |
| - name: Install dependencies | |
| run: yarn install --immutable | |
| - name: Build shared | |
| run: npx nx build twenty-shared | |
| - name: Run server tests | |
| # Fail closed: a non-zero exit from the test run must fail the job so | |
| # release green-CI gates cannot pass while server tests fail. | |
| # | |
| # Root cause of the previous (removed) `continue-on-error: true`: | |
| # jest.config.mjs enforced global coverage thresholds (30/20/25/30) and | |
| # the codebase currently sits below them (~27% statements). jest then | |
| # exited non-zero *even when every test passed*, so CI swallowed the | |
| # exit code — which ALSO masked genuine test failures. Coverage | |
| # enforcement is now opt-in (JEST_ENFORCE_COVERAGE, see jest.config.mjs), | |
| # so this step's exit code reflects test pass/fail only: a failing test | |
| # (and only a failing test) fails the job. | |
| # `^build` (nx targetDefaults) builds workspace deps (twenty-emails / | |
| # twenty-client-sdk) first so they resolve in the jest module context; | |
| # `--configuration=ci` pins maxWorkers=1 for deterministic runs. | |
| run: npx nx test twenty-server --configuration=ci -- --passWithNoTests | |
| # PR LANE (primary test gate) — runs the SAME server unit test suite on the | |
| # dedicated self-hosted macOS runner (mac-m4-exe-crm, M4 / 16 cores). Check | |
| # context: "Server unit tests (mac)". Runs ONLY on pull_request + merge_group | |
| # (merge queue requires protection-required contexts to report on merge_group | |
| # or the queue stalls). | |
| # | |
| # Why: the Linux build-my runners share one overloaded host — the full yarn | |
| # workspace install + jest run took 30+ min there and queued behind other | |
| # jobs. The mac runner is a dedicated 16-core box. | |
| # | |
| # `--maxWorkers=6` overrides the `--configuration=ci` pin of maxWorkers=1 | |
| # (nx CLI args take precedence over configuration values). maxWorkers=1 on | |
| # Linux exists to avoid core thrash on the SHARED build-my host; the mac | |
| # runner runs only this job, so 6 workers on 16 cores is safe headroom while | |
| # leaving cores for the dev box's own load. | |
| # | |
| # macOS notes: no Docker on this runner (docker-dependent jobs stay on | |
| # Linux — see security-scan); setup-node cache keys include runner OS+arch, | |
| # so the macOS-arm64 yarn cache never collides with the Linux-x64 one. | |
| server-tests-mac: | |
| name: Server unit tests (mac) | |
| if: github.event_name == 'pull_request' || github.event_name == 'merge_group' | |
| runs-on: ${{ github.actor == 'dependabot[bot]' && 'ubuntu-latest' || fromJSON('["self-hosted", "macOS", "ARM64", "mac-fast"]') }} | |
| timeout-minutes: 40 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: 'yarn' | |
| - name: Install dependencies | |
| run: yarn install --immutable | |
| - name: Build shared | |
| run: npx nx build twenty-shared | |
| - name: Run server tests | |
| # Same fail-closed semantics as the main-lane `server-tests` job above | |
| # (see its comment for the coverage-threshold / continue-on-error | |
| # history). KEEP THE TWO COMMANDS IN SYNC apart from --maxWorkers. | |
| run: npx nx test twenty-server --configuration=ci --maxWorkers=6 -- --passWithNoTests | |
| security-scan: | |
| name: Security scan (secrets, deps, container config) | |
| runs-on: ${{ github.actor == 'dependabot[bot]' && 'ubuntu-latest' || fromJSON('["self-hosted", "linux", "x64"]') }} | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: 'yarn' | |
| - name: Install dependencies | |
| run: yarn install --immutable | |
| # Secret scan (open-source gitleaks binary via its pinned-by-digest image; | |
| # the gitleaks GitHub Action requires a paid license for org repos, the CLI | |
| # does not). --no-git scans the current checkout. Fails closed on findings. | |
| - name: Secret scan (gitleaks) | |
| run: | | |
| docker run --rm -v "$PWD:/repo" \ | |
| ghcr.io/gitleaks/gitleaks:v8.21.2@sha256:0e99e8821643ea5b235718642b93bb32486af9c8162c8b8731f7cbdc951a7f46 \ | |
| detect --source=/repo --no-git --redact --no-banner --verbose \ | |
| --config=/repo/.gitleaks.toml | |
| # Production dependency vulnerability scan. The required gate audits only | |
| # production dependencies at CRITICAL severity; dev-dependency and HIGH | |
| # advisory signals are surfaced by the non-blocking informational step below. | |
| - name: Dependency scan (yarn npm audit, production, critical gate) | |
| run: yarn npm audit --recursive --environment production --severity critical | |
| - name: Dependency scan (yarn npm audit, production, latest high advisory signal) | |
| run: yarn npm audit --all --recursive --environment production --severity high | |
| continue-on-error: true | |
| # Container / IaC misconfiguration scan of the production Docker stack | |
| # (Dockerfile + docker-compose) AND the helm/ + k8s/ orchestration | |
| # manifests (hardened in bug be6e91fe — securityContext, non-root, | |
| # read-only rootfs, cap drops). Complements the full image vulnerability | |
| # scan run at release time (.github/workflows/release-stack-image.yml). | |
| # Fails closed on HIGH+. | |
| - name: Container config scan (Trivy) | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| with: | |
| scan-type: config | |
| scan-ref: packages/twenty-docker | |
| format: table | |
| exit-code: '1' | |
| severity: CRITICAL,HIGH |