Repository: symfony/ux
Pull request #2734 (2025-05-13 12:50:09)

[CI] Rework `tests-php` job matrix, better covers different PHP/SF versions, test all components in a single job
| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Docs?         | no <!-- required for new features -->
| Issues        | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License       | MIT

<!--
Replace this notice by a description of your feature/bugfix.
This will help reviewers and should be a good start for the documentation.

Additionally (see https://symfony.com/releases):
 - Always add tests and ensure they pass.
 - For new features, provide some code snippets to help understand usage.
 - Features and deprecations must be submitted against branch main.
 - Update/add documentation as required (we can help!)
 - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry
 - Never break backward compatibility (see https://symfony.com/bc).
-->

tl;dr:
<img width="256" alt="image" src="https://github.com/user-attachments/assets/bfd53555-f2e8-4d78-b810-c21e40b43acc" />


Following internal messages about UX CI, let's improve our CI:
- Modifying the matrix is now easier than before
- We now use PHP 8.2 too
- One "fully-working" lowest deps job (it's more explicit than before)
- The "component" matrix entry has been removed in favor of the same system used by  symfony/symfony CI for unit-tests. Now, all ~~components~~ packages tests are run in a single job, in parallel. So, we won't increase the number of jobs by X when modifying the matrix (when working on this PR and without this change, I went to ~150 jobs 😅)

https://github.com/user-attachments/assets/73f2810e-4544-4344-895b-64754274bf74



Kocal: Okay I believe we are one something nice, but some notes:
1. the `--prefer-lowest` has a **tons** of deprecations 😬 
2. `dev` jobs fail because of TwigComponent requiring an old version of WebpackEncoreBundle:
```
+ cd src/TwigComponent
+ composer config minimum-stability dev --ansi
+ composer update --no-progress --no-interaction --ansi
Loading composer repositories with package information
Restricting packages listed in "symfony/symfony" to "7.*"
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires symfony/webpack-encore-bundle ^1.15 -> satisfiable by symfony/webpack-encore-bundle[v1.15.0, ..., v1.17.2].
    - symfony/webpack-encore-bundle[v1.15.0, ..., v1.17.2] require symfony/asset ^4.4 || ^5.0 || ^6.0 -> found symfony/asset[v4.4.0-BETA1, ..., 4.4.x-dev, v5.0.0-BETA1, ..., 5.4.x-dev, v6.0.0-BETA1, ..., 6.4.x-dev] but these were not loaded, likely because it conflicts with another require.

Error: Your requirements could not be resolved to an installable set of packages.
```
stof: > 1. the `--prefer-lowest` has a **tons** of deprecations

this job should be running with deprecations allowed (lowest deps might not have solved all deprecations)
Kocal: Thanks for the advice, will try it asap :) 

Patch:
diff --git a/composer.json b/composer.json
index 271f27ec..4a24cfc1 100644
--- a/composer.json
+++ b/composer.json
@@ -5,8 +5,9 @@
         "dev"
     ],
     "require-dev": {
-        "symfony/filesystem": "^5.2|^6.0|^7.0",
-        "symfony/finder": "^5.4|^6.0|^7.0",
+        "php": ">=8.1",
+        "symfony/filesystem": "^6.4|^7.0",
+        "symfony/finder": "^6.4|^7.0",
         "php-cs-fixer/shim": "^3.62"
     }
 }


Test patch:
diff --git a/.github/workflows/test-turbo.yml b/.github/workflows/test-turbo.yml
index d3028192..cabbea8d 100644
--- a/.github/workflows/test-turbo.yml
+++ b/.github/workflows/test-turbo.yml
@@ -8,9 +8,6 @@ on:
         paths:
             - 'src/Turbo/**'
 
-env:
-    SYMFONY_REQUIRE: '>=5.4'
-
 jobs:
     phpstan:
         runs-on: ubuntu-latest
@@ -41,15 +38,23 @@ jobs:
         strategy:
            fail-fast: false
            matrix:
-               php-version: ['8.1', '8.3', '8.4']
+               php-version: ['8.1', '8.2', '8.3', '8.4']
+               dependency-version: ['']
+               symfony-version: ['']
+               minimum-stability: ['stable']
                include:
-                  - php-version: '8.1'
-                    dependency-version: 'lowest'
-                  - php-version: '8.3'
-                    dependency-version: 'highest'
-                  - php-version: '8.4'
-                    dependency-version: 'highest'
-
+                   # dev packages (probably not needed to have multiple such jobs)
+                   -   minimum-stability: 'dev'
+                       php-version: '8.4'
+                   # lowest deps
+                   -   php-version: '8.1'
+                       dependency-version: 'lowest'
+                   # LTS version of Symfony
+                   -   php-version: '8.1'
+                       symfony-version: '6.4.*'
+
+        env:
+            SYMFONY_REQUIRE: ${{ matrix.symfony-version }}
         services:
             mercure:
                 image: dunglas/mercure
@@ -71,15 +76,13 @@ jobs:
               uses: shivammathur/setup-php@v2
               with:
                   php-version: ${{ matrix.php-version }}
-
-            - name: Install symfony/flex
-              run: composer global config allow-plugins.symfony/flex true && composer global require symfony/flex
+                  tools: flex
 
             - name: Install dependencies with composer
-              uses: ramsey/composer-install@v3
-              with:
-                working-directory: src/Turbo
-                dependency-versions: ${{ matrix.dependency-version }}
+              working-directory: src/Turbo
+              run: |
+                  composer config minimum-stability ${{ matrix.minimum-stability || 'stable' }}
+                  composer update ${{ matrix.dependency-version == 'lowest' && '--prefer-lowest' || '' }} --no-progress --no-interaction
 
             - name: Install JavaScript dependencies
               working-directory: src/Turbo/tests/app
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index a17aa41e..7ee1a445 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -12,6 +12,10 @@ on:
             - 'src/**/*.md'
             - 'ux.symfony.com/**'
 
+concurrency:
+    group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+    cancel-in-progress: true
+
 jobs:
     coding-style-js:
         name: JavaScript Coding Style
@@ -50,75 +54,81 @@ jobs:
                   echo "The Git workspace is clean. No changes detected."
                 fi
 
-    tests-php-components:
-        runs-on: ubuntu-latest
-        outputs:
-            components: ${{ steps.components.outputs.components }}
-        steps:
-            - uses: actions/checkout@v4
-
-            - id: components
-              run: |
-                components=$(find src/ -mindepth 2 -type f -name composer.json -not -path "*/vendor/*" -printf '%h\n' | jq -R -s -c 'split("\n")[:-1] | map(. | sub("^src/";"")) | sort')
-                echo "$components"
-                echo "components=$components" >> $GITHUB_OUTPUT
-
     tests-php:
         runs-on: ubuntu-latest
-        needs: tests-php-components
         strategy:
             fail-fast: false
             matrix:
-                php-version: ['8.1', '8.3', '8.4']
-                minimum-stability: ['stable', 'dev']
+                php-version: ['8.1', '8.2', '8.3', '8.4']
+                dependency-version: ['']
+                symfony-version: ['']
+                minimum-stability: ['stable']
                 include:
-                  - php-version: '8.1'
-                    dependency-version: 'lowest'
-                  - php-version: '8.3'
-                    dependency-version: 'highest'
-                  - php-version: '8.4'
-                    dependency-version: 'highest'
-                component: ${{ fromJson(needs.tests-php-components.outputs.components )}}
-                exclude:
-                  - php-version: '8.1'
-                    minimum-stability: 'dev'
-                  - php-version: '8.3'
-                    minimum-stability: 'dev'
-                  - component: Swup  # has no tests
-                  - component: Turbo # has its own workflow (test-turbo.yml)
-                  - component: Typed  # has no tests
-
+                    # dev packages (probably not needed to have multiple such jobs)
+                    -   minimum-stability: 'dev'
+                        php-version: '8.4'
+                    # lowest deps
+                    -   php-version: '8.1'
+                        dependency-version: 'lowest'
+                    # LTS version of Symfony
+                    -   php-version: '8.1'
+                        symfony-version: '6.4.*'
+
+        env:
+            SYMFONY_REQUIRE: ${{ matrix.symfony-version }}
         steps:
             - uses: actions/checkout@v4
 
-            - uses: shivammathur/setup-php@v2
+            - name: Configure environment
+              run: |
+                  echo COLUMNS=120 >> $GITHUB_ENV
+                  echo COMPOSER_MIN_STAB='composer config minimum-stability ${{ matrix.minimum-stability || 'stable' }} --ansi' >> $GITHUB_ENV
+                  echo COMPOSER_UP='composer update ${{ matrix.dependency-version == 'lowest' && '--prefer-lowest' || '' }} --no-progress --no-interaction --ansi' >> $GITHUB_ENV
+                  echo PHPUNIT='vendor/bin/simple-phpunit' >> $GITHUB_ENV
+                  [ 'lowest' = '${{ matrix.dependency-version }}' ] && export SYMFONY_DEPRECATIONS_HELPER=weak
+
+                  # Swup and Typed have no tests, Turbo has its own workflow file
+                  PACKAGES=$(find src/ -mindepth 2 -type f -name composer.json -not -path "*/vendor/*" -printf '%h\n' | sed 's/^src\///' | grep -Ev "Swup|Turbo|Typed" | sort |  tr '\n' ' ')
+                  echo "Packages: $PACKAGES"
+                  echo "PACKAGES=$PACKAGES" >> $GITHUB_ENV
+
+            - name: Setup PHP
+              uses: shivammathur/setup-php@v2
               with:
                 php-version: ${{ matrix.php-version }}
+                tools: flex
 
-            - name: Install root packages
-              uses: ramsey/composer-install@v3
-              with:
-                working-directory: ${{ github.workspace }}
-                dependency-versions: ${{ matrix.dependency-version }}
+            - name: Install root dependencies
+              run: composer install
 
             - name: Build root packages
               run: php .github/build-packages.php
-              working-directory: ${{ github.workspace }}
-
-            - name: Configure ${{ matrix.minimum-stability }} stability
-              if: ${{ matrix.minimum-stability }}
-              run: composer config minimum-stability ${{ matrix.minimum-stability }}
-              working-directory: "src/${{ matrix.component }}"
 
-            - name: Install ${{ matrix.component }} packages
-              uses: ramsey/composer-install@v3
-              with:
-                working-directory: "src/${{ matrix.component }}"
-                dependency-versions: ${{ matrix.dependency-version }}
-
-            - name: ${{ matrix.component }} Tests
-              working-directory: "src/${{ matrix.component }}"
-              run: vendor/bin/simple-phpunit
+            - name: Run packages tests
+              run: |
+                _run_task() {
+                    local ok=0
+                    local title="$1"
+                    local start=$(date -u +%s)
+                    OUTPUT=$(bash -xc "$2" 2>&1) || ok=$?
+                    local end=$(date -u +%s)
+
+                    if [[ $ok -ne 0 ]]; then
+                      printf "\n%-70s%10s\n" $title $(($end-$start))s
+                      echo "$OUTPUT"
+                      echo "Job exited with: $ok"
+                      echo -e "\n::error::KO $title\\n"
+                    else
+                      printf "::group::%-68s%10s\n" $title $(($end-$start))s
+                      echo "$OUTPUT"
+                      echo -e "\n\\e[32mOK\\e[0m $title\\n\\n::endgroup::"
+                    fi
+
+                    exit $ok
+                }
+                export -f _run_task
+
+                echo "$PACKAGES" | xargs -n1 | parallel -j +3 "_run_task {} '(cd src/{} && $COMPOSER_MIN_STAB && $COMPOSER_UP && $PHPUNIT)'"
 
     tests-js:
         runs-on: ubuntu-latest