From ebbd759c5d2de45aaa476f9626acd066d129967c Mon Sep 17 00:00:00 2001 From: HugoFara Date: Wed, 4 Nov 2026 12:38:38 +0100 Subject: [PATCH 1/2] ci: run only what a pull request can affect Every pull request waited about 11 minutes, nearly all of it on four Windows PHPUnit jobs taking about 9 minutes each against 17 seconds on Ubuntu, and then ran everything a second time when merged into develop. Pull requests now run on Ubuntu only, and each workflow runs only when its paths changed. A push to main stays the full check, Windows included. The develop push is gone, and a new push to a pull request cancels the run it replaces. PHPUnit also stops loading Xdebug: the job runs test:no-coverage, so it was only slowing the tests down. Co-Authored-By: Claude --- .github/workflows/frontend.yml | 25 ++++++++++++++++++++- .github/workflows/locales.yml | 13 ++++++++++- .github/workflows/php.yml | 33 +++++++++++++++++++++++----- .github/workflows/phpcs.yml | 13 ++++++++++- .github/workflows/security_check.yml | 15 ++++++++++++- CLAUDE.md | 2 ++ CONTRIBUTING.md | 2 +- docs-src/developer/contributing.md | 2 +- 8 files changed, 93 insertions(+), 12 deletions(-) diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 966c88ef2..027030cce 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -1,10 +1,33 @@ name: Frontend CI +# Pull requests run what the change can affect; a push to main runs everything. on: push: - branches: [ main, develop ] + branches: [ main ] pull_request: branches: [ main, develop ] + paths: + - 'src/**' + - 'tests/frontend/**' + - 'tests/fixtures/**' + - 'tests/setup.ts' + - 'tests/api.test.ts' + - 'cypress/**' + - 'scripts/**' + - 'package.json' + - 'package-lock.json' + - 'vite.config.ts' + - 'vitest.config.ts' + - 'tsconfig.json' + - 'eslint.config.ts' + - 'cypress.config.ts' + - '.github/workflows/frontend.yml' + +# A new push to a pull request replaces the run in progress. Runs on main are +# left to finish: they are the last full check before a release. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: lint-and-typecheck: diff --git a/.github/workflows/locales.yml b/.github/workflows/locales.yml index d43d06c8e..a80f4c8c7 100644 --- a/.github/workflows/locales.yml +++ b/.github/workflows/locales.yml @@ -1,10 +1,21 @@ name: Locale completion +# Pull requests run what the change can affect; a push to main runs everything. on: push: - branches: [ main, develop ] + branches: [ main ] pull_request: branches: [ main, develop ] + paths: + - 'locale/**' + - 'bin/check-locales.php' + - '.github/workflows/locales.yml' + +# A new push to a pull request replaces the run in progress. Runs on main are +# left to finish: they are the last full check before a release. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: check: diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 30a734553..045fa3c27 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -1,22 +1,42 @@ name: PHP CI +# Pull requests run what the change can affect; a push to main runs everything. on: push: - branches: [ main, develop ] + branches: [ main ] pull_request: branches: [ main, develop ] + paths: + - '**.php' + - 'src/**' + - 'locale/**' + - 'db/**' + - 'tests/backend/**' + - 'tests/fixtures/**' + - 'tests/sql/**' + - 'tests/tools/**' + - 'composer.json' + - 'composer.lock' + - 'phpunit.xml' + - '.github/workflows/php.yml' + +# A new push to a pull request replaces the run in progress. Runs on main are +# left to finish: they are the last full check before a release. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: test: name: PHPUnit Tests - runs-on: ${{ matrix.config.os }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - config: - - os: ubuntu-latest - - os: windows-latest + # Windows takes about 30 times as long as Ubuntu for the same tests, so + # it runs on main only, as the check before a release. + os: ${{ fromJSON(github.event_name == 'push' && '["ubuntu-latest", "windows-latest"]' || '["ubuntu-latest"]') }} php-version: [ '8.2', '8.3', '8.4', '8.5' ] steps: @@ -28,7 +48,8 @@ jobs: with: php-version: ${{ matrix.php-version }} extensions: mbstring, mysqli, dom, zip, pdo_sqlite - coverage: xdebug + # The job runs test:no-coverage; a loaded Xdebug only slows it down. + coverage: none - name: Validate composer.json and composer.lock run: composer validate --strict diff --git a/.github/workflows/phpcs.yml b/.github/workflows/phpcs.yml index a292667da..871e67993 100644 --- a/.github/workflows/phpcs.yml +++ b/.github/workflows/phpcs.yml @@ -1,10 +1,21 @@ name: PHP CodeSniffer +# Pull requests run what the change can affect; a push to main runs everything. on: push: - branches: [ main, develop ] + branches: [ main ] pull_request: branches: [ main, develop ] + paths: + - '**.php' + - 'phpcs.xml' + - '.github/workflows/phpcs.yml' + +# A new push to a pull request replaces the run in progress. Runs on main are +# left to finish: they are the last full check before a release. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: phpcs: diff --git a/.github/workflows/security_check.yml b/.github/workflows/security_check.yml index 2ced3a83b..19b0480de 100644 --- a/.github/workflows/security_check.yml +++ b/.github/workflows/security_check.yml @@ -1,10 +1,23 @@ name: Psalm Static Analysis +# Pull requests run what the change can affect; a push to main runs everything. on: push: - branches: [ main, develop ] + branches: [ main ] pull_request: branches: [ main, develop ] + paths: + - '**.php' + - 'composer.json' + - 'composer.lock' + - 'psalm.xml' + - '.github/workflows/security_check.yml' + +# A new push to a pull request replaces the run in progress. Runs on main are +# left to finish: they are the last full check before a release. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: psalm: diff --git a/CLAUDE.md b/CLAUDE.md index 3d31e8447..f06ba74b2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -93,6 +93,8 @@ if (!defined('LWT_TEST_DB_AVAILABLE') || !LWT_TEST_DB_AVAILABLE) { } ``` +**What CI runs:** pull requests run only the workflows their changed paths can affect, on Ubuntu; each workflow's `paths:` list says which. A push to `main` runs everything, including PHPUnit on Windows, which takes about 30 times as long. So when a new test reads a file outside a workflow's list, add that path to the list, or a pull request can skip the check that would have failed. + Prefer mocking or restructuring code to avoid DB calls in unit tests. Use the skip guard only when static/global DB calls cannot be avoided (e.g., deeply nested static method calls). Always serve the app with `npm run serve`, not a bare `php -S`: the built-in diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3f265a73c..157dd2dc6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -322,7 +322,7 @@ php bin/check-locales.php --json # Machine-readable output php bin/check-locales.php --fail-under=90 # Exit 1 if a locale drops below 90% ``` -The same script runs in CI on every push and pull request, so a missing key shows +The same script runs in CI on every push to `main` and on pull requests that touch `locale/`, so a missing key shows up in the `Locale completion` workflow before it reaches a reader. ### Improving a Translation diff --git a/docs-src/developer/contributing.md b/docs-src/developer/contributing.md index b34658fd4..e1c3121d5 100644 --- a/docs-src/developer/contributing.md +++ b/docs-src/developer/contributing.md @@ -327,7 +327,7 @@ php bin/check-locales.php --json # Machine-readable output php bin/check-locales.php --fail-under=90 # Exit 1 if a locale drops below 90% ``` -The same script runs in CI on every push and pull request, so a missing key shows +The same script runs in CI on every push to `main` and on pull requests that touch `locale/`, so a missing key shows up in the `Locale completion` workflow before it reaches a reader. ### Improving a Translation From 340f8242fd6d815460d09f5632b35a6a2503efb5 Mon Sep 17 00:00:00 2001 From: HugoFara Date: Wed, 4 Nov 2026 12:39:04 +0100 Subject: [PATCH 2/2] docs(claude): keep the CI note clear of the database guard advice Co-Authored-By: Claude --- CLAUDE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f06ba74b2..3a09ef09a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -93,10 +93,10 @@ if (!defined('LWT_TEST_DB_AVAILABLE') || !LWT_TEST_DB_AVAILABLE) { } ``` -**What CI runs:** pull requests run only the workflows their changed paths can affect, on Ubuntu; each workflow's `paths:` list says which. A push to `main` runs everything, including PHPUnit on Windows, which takes about 30 times as long. So when a new test reads a file outside a workflow's list, add that path to the list, or a pull request can skip the check that would have failed. - Prefer mocking or restructuring code to avoid DB calls in unit tests. Use the skip guard only when static/global DB calls cannot be avoided (e.g., deeply nested static method calls). +**What CI runs:** pull requests run only the workflows their changed paths can affect, on Ubuntu; each workflow's `paths:` list says which. A push to `main` runs everything, including PHPUnit on Windows, which takes about 30 times as long. So when a new test reads a file outside a workflow's list, add that path to the list, or a pull request can skip the check that would have failed. + Always serve the app with `npm run serve`, not a bare `php -S`: the built-in server is single-request unless `PHP_CLI_SERVER_WORKERS` is set, so one slow request blocks the rest and Cypress times out on pages that are only queued.