diff --git a/.github/workflows/.utils.sh b/.github/workflows/.utils.sh new file mode 100644 index 00000000000..78b0d277984 --- /dev/null +++ b/.github/workflows/.utils.sh @@ -0,0 +1,21 @@ +_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 diff --git a/.github/workflows/app-tests.yaml b/.github/workflows/app-tests.yaml new file mode 100644 index 00000000000..c6b5da0662c --- /dev/null +++ b/.github/workflows/app-tests.yaml @@ -0,0 +1,107 @@ +name: App Tests + +on: + push: + paths-ignore: + - 'src/*/doc/**' + - 'src/**/*.md' + - 'ux.symfony.com/**' + pull_request: + paths-ignore: + - 'src/*/doc/**' + - 'src/**/*.md' + - 'ux.symfony.com/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + encore-app: + name: "Encore (${{ matrix.name}})" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - name: Internal, from "vendor/" + ux-packages-source: php-vendor + - name: External, from "npm add" + ux-packages-source: js-packages + steps: + - uses: actions/checkout@v4 + + - run: npm i -g corepack && corepack enable + + - uses: actions/setup-node@v4 + with: + cache: 'yarn' + cache-dependency-path: | + yarn.lock + package.json + src/**/package.json + test_apps/encore-app/package.json + + - uses: shivammathur/setup-php@v2 + + - name: Install root dependencies + uses: ramsey/composer-install@v3 + with: + working-directory: ${{ github.workspace }} + + - name: Build root packages + run: php .github/build-packages.php + working-directory: ${{ github.workspace }} + + # We always install PHP deps because we of the UX Translator, which requires `var/translations` to exists + - uses: ramsey/composer-install@v3 + with: + dependency-versions: 'highest' + working-directory: test_apps/encore-app + + - if: matrix.ux-packages-source == 'php-vendor' + name: Refresh dependencies from vendor/ + working-directory: test_apps/encore-app + run: yarn + env: + YARN_ENABLE_HARDENED_MODE: 0 + YARN_ENABLE_IMMUTABLE_INSTALLS: 0 + + - if: matrix.ux-packages-source == 'js-packages' + name: Install UX JS packages with a JS package manager + working-directory: test_apps/encore-app + run: | + PACKAGES_TO_INSTALL='' + for PACKAGE in $(cd ../..; yarn workspaces list --no-private --json); do + PACKAGE_DIR=../../$(echo $PACKAGE | jq -r '.location') + PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL $PACKAGE_DIR" + done + echo "Installing packages: $PACKAGES_TO_INSTALL" + yarn add --dev $PACKAGES_TO_INSTALL + + - name: Ensure UX packages are installed from "${{ matrix.ux-packages-source == 'php-vendor' && 'vendor/symfony/ux-...' || '../../../src/**/assets' }}" + working-directory: test_apps/encore-app + run: | + for PACKAGE in $(cat package.json | jq -c '(.dependencies // {}) + (.devDependencies // {}) | to_entries[] | select(.key | startswith("@symfony/ux-")) | {name: .key, version: .value}'); do + PACKAGE_NAME=$(echo $PACKAGE | jq -r '.name') + PACKAGE_VERSION=$(echo $PACKAGE | jq -r '.version') + + echo -n "Checking $PACKAGE_NAME@$PACKAGE_VERSION..." + if [[ $PACKAGE_VERSION == $EXPECTED_PATTERN* ]]; then + echo " OK" + else + echo " KO" + echo "The package version of $PACKAGE_NAME must starts with the pattern (e.g.: $EXPECTED_PATTERN), got $PACKAGE_VERSION instead." + exit 1 + fi + done; + env: + EXPECTED_PATTERN: ${{ matrix.ux-packages-source == 'php-vendor' && 'file:vendor/symfony/*' || '../../src/*' }} + + - name: Run Encore (dev) + working-directory: test_apps/encore-app + run: yarn encore dev + + - name: Run Encore (prod) + working-directory: test_apps/encore-app + run: yarn encore production diff --git a/.github/workflows/code-quality.yaml b/.github/workflows/code-quality.yaml new file mode 100644 index 00000000000..84896b538e0 --- /dev/null +++ b/.github/workflows/code-quality.yaml @@ -0,0 +1,72 @@ +name: Code Quality + +on: + push: + paths-ignore: + - 'src/*/doc/**' + - 'src/**/*.md' + - 'ux.symfony.com/**' + pull_request: + paths-ignore: + - 'src/*/doc/**' + - '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 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npm i -g corepack && corepack enable + - uses: actions/setup-node@v4 + with: + cache: 'yarn' + - run: yarn --immutable + - run: yarn ci + + phpstan: + name: PHPStan + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + package: ${{ fromJson(needs.php-packages-matrix.outputs.packages) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Configure environment + run: | + echo COLUMNS=120 >> $GITHUB_ENV + echo COMPOSER_MIN_STAB='composer config minimum-stability stable --ansi' >> $GITHUB_ENV + echo COMPOSER_UP='composer update --no-progress --no-interaction --ansi' >> $GITHUB_ENV + echo PHPSTAN='vendor/bin/phpstan' >> $GITHUB_ENV + + # TODO: Only Turbo has PHPStan configuration, let's improve this later :) + PACKAGES=Turbo + #PACKAGES=$(find src/ -mindepth 2 -type f -name composer.json -not -path "*/vendor/*" -printf '%h\n' | sed 's/^src\///' | sort | tr '\n' ' ') + echo "Packages: $PACKAGES" + echo "PACKAGES=$PACKAGES" >> $GITHUB_ENV + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + tools: flex + + - name: Install root dependencies + run: composer install + + - name: Build root packages + run: php .github/build-packages.php + + - name: Run PHPStan on packages + run: | + source .github/workflows/.utils.sh + + echo "$PACKAGES" | xargs -n1 | parallel -j +3 "_run_task {} '(cd src/{} && $COMPOSER_MIN_STAB && $COMPOSER_UP && $PHPSTAN)'" diff --git a/.github/workflows/dist-files-unbuilt.yaml b/.github/workflows/dist-files-unbuilt.yaml new file mode 100644 index 00000000000..cd76bdaf489 --- /dev/null +++ b/.github/workflows/dist-files-unbuilt.yaml @@ -0,0 +1,42 @@ +name: Dist Files Unbuilt + +on: + push: + paths-ignore: + - 'src/*/doc/**' + - 'src/**/*.md' + - 'ux.symfony.com/**' + pull_request: + paths-ignore: + - 'src/*/doc/**' + - 'src/**/*.md' + - 'ux.symfony.com/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npm i -g corepack && corepack enable + - uses: actions/setup-node@v4 + with: + cache: 'yarn' + cache-dependency-path: | + yarn.lock + **/package.json + - run: yarn --immutable && yarn build + + - name: Check if JS dist files are current + run: | + if ! git diff --quiet; then + echo "The Git workspace is unclean! Changes detected:" + git status --porcelain + git diff + exit 1 + else + echo "The Git workspace is clean. No changes detected." + fi diff --git a/.github/workflows/test-turbo.yml b/.github/workflows/functional-tests.yml similarity index 78% rename from .github/workflows/test-turbo.yml rename to .github/workflows/functional-tests.yml index cabbea8d7bb..279901230bf 100644 --- a/.github/workflows/test-turbo.yml +++ b/.github/workflows/functional-tests.yml @@ -1,4 +1,4 @@ -name: Symfony UX Turbo +name: Functional Tests on: push: @@ -9,31 +9,7 @@ on: - 'src/Turbo/**' jobs: - phpstan: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.1' - extensions: zip - - - uses: ramsey/composer-install@v3 - with: - working-directory: src/Turbo - - - name: Install PHPUnit dependencies - working-directory: src/Turbo - run: vendor/bin/simple-phpunit --version - - - name: PHPStan - working-directory: src/Turbo - run: vendor/bin/phpstan analyse --no-progress - - tests: + turbo-tests: runs-on: ubuntu-latest strategy: fail-fast: false diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 7ee1a44516f..00000000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,236 +0,0 @@ -name: Symfony UX - -on: - push: - paths-ignore: - - 'src/*/doc/**' - - 'src/**/*.md' - - 'ux.symfony.com/**' - pull_request: - paths-ignore: - - 'src/*/doc/**' - - '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 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: npm i -g corepack && corepack enable - - uses: actions/setup-node@v4 - with: - cache: 'yarn' - - run: yarn --immutable - - run: yarn ci - - js-dist-current: - name: Check for UnBuilt JS Dist Files - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: npm i -g corepack && corepack enable - - uses: actions/setup-node@v4 - with: - cache: 'yarn' - cache-dependency-path: | - yarn.lock - **/package.json - - run: yarn --immutable && yarn build - - - name: Check if JS dist files are current - run: | - if ! git diff --quiet; then - echo "The Git workspace is unclean! Changes detected:" - git status --porcelain - git diff - exit 1 - else - echo "The Git workspace is clean. No changes detected." - fi - - tests-php: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - php-version: ['8.1', '8.2', '8.3', '8.4'] - dependency-version: [''] - symfony-version: [''] - minimum-stability: ['stable'] - include: - # 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 - - - 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 dependencies - run: composer install - - - name: Build root packages - run: php .github/build-packages.php - - - 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 - steps: - - uses: actions/checkout@v4 - - run: npm i -g corepack && corepack enable - - uses: actions/setup-node@v4 - with: - cache: 'yarn' - cache-dependency-path: | - yarn.lock - package.json - src/**/package.json - - run: yarn --immutable - - run: yarn playwright install - - run: yarn test - - test-app-encore-app: - name: "Test Apps / Encore (${{ matrix.name}})" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - name: Internal, from "vendor/" - ux-packages-source: php-vendor - - name: External, from "npm add" - ux-packages-source: js-packages - steps: - - uses: actions/checkout@v4 - - - run: npm i -g corepack && corepack enable - - - uses: actions/setup-node@v4 - with: - cache: 'yarn' - cache-dependency-path: | - yarn.lock - package.json - src/**/package.json - test_apps/encore-app/package.json - - - uses: shivammathur/setup-php@v2 - - - name: Install root dependencies - uses: ramsey/composer-install@v3 - with: - working-directory: ${{ github.workspace }} - - - name: Build root packages - run: php .github/build-packages.php - working-directory: ${{ github.workspace }} - - # We always install PHP deps because we of the UX Translator, which requires `var/translations` to exists - - uses: ramsey/composer-install@v3 - with: - dependency-versions: 'highest' - working-directory: test_apps/encore-app - - - if: matrix.ux-packages-source == 'php-vendor' - name: Refresh dependencies from vendor/ - working-directory: test_apps/encore-app - run: yarn - env: - YARN_ENABLE_HARDENED_MODE: 0 - YARN_ENABLE_IMMUTABLE_INSTALLS: 0 - - - if: matrix.ux-packages-source == 'js-packages' - name: Install UX JS packages with a JS package manager - working-directory: test_apps/encore-app - run: | - PACKAGES_TO_INSTALL='' - for PACKAGE in $(cd ../..; yarn workspaces list --no-private --json); do - PACKAGE_DIR=../../$(echo $PACKAGE | jq -r '.location') - PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL $PACKAGE_DIR" - done - echo "Installing packages: $PACKAGES_TO_INSTALL" - yarn add --dev $PACKAGES_TO_INSTALL - - - name: Ensure UX packages are installed from "${{ matrix.ux-packages-source == 'php-vendor' && 'vendor/symfony/ux-...' || '../../../src/**/assets' }}" - working-directory: test_apps/encore-app - run: | - for PACKAGE in $(cat package.json | jq -c '(.dependencies // {}) + (.devDependencies // {}) | to_entries[] | select(.key | startswith("@symfony/ux-")) | {name: .key, version: .value}'); do - PACKAGE_NAME=$(echo $PACKAGE | jq -r '.name') - PACKAGE_VERSION=$(echo $PACKAGE | jq -r '.version') - - echo -n "Checking $PACKAGE_NAME@$PACKAGE_VERSION..." - if [[ $PACKAGE_VERSION == $EXPECTED_PATTERN* ]]; then - echo " OK" - else - echo " KO" - echo "The package version of $PACKAGE_NAME must starts with the pattern (e.g.: $EXPECTED_PATTERN), got $PACKAGE_VERSION instead." - exit 1 - fi - done; - env: - EXPECTED_PATTERN: ${{ matrix.ux-packages-source == 'php-vendor' && 'file:vendor/symfony/*' || '../../src/*' }} - - - name: Run Encore (dev) - working-directory: test_apps/encore-app - run: yarn encore dev - - - name: Run Encore (prod) - working-directory: test_apps/encore-app - run: yarn encore production diff --git a/.github/workflows/toolkit-kits-cs.yaml b/.github/workflows/toolkit-kits-code-quality.yaml similarity index 95% rename from .github/workflows/toolkit-kits-cs.yaml rename to .github/workflows/toolkit-kits-code-quality.yaml index fcd5e36f3c2..0ed5ccfc968 100644 --- a/.github/workflows/toolkit-kits-cs.yaml +++ b/.github/workflows/toolkit-kits-code-quality.yaml @@ -1,4 +1,4 @@ -name: Toolkit Kits +name: Toolkit Kits Code Quality on: push: diff --git a/.github/workflows/unit-tests.yaml b/.github/workflows/unit-tests.yaml new file mode 100644 index 00000000000..f9ee2aab224 --- /dev/null +++ b/.github/workflows/unit-tests.yaml @@ -0,0 +1,90 @@ +name: Unit Tests + +on: + push: + paths-ignore: + - 'src/*/doc/**' + - 'src/**/*.md' + - 'ux.symfony.com/**' + pull_request: + paths-ignore: + - 'src/*/doc/**' + - 'src/**/*.md' + - 'ux.symfony.com/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + php: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php-version: ['8.1', '8.2', '8.3', '8.4'] + dependency-version: [''] + symfony-version: [''] + minimum-stability: ['stable'] + include: + # 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 + + - 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 dependencies + run: composer install + + - name: Build root packages + run: php .github/build-packages.php + + - name: Run packages tests + run: | + source .github/workflows/.utils.sh + + echo "$PACKAGES" | xargs -n1 | parallel -j +3 "_run_task {} '(cd src/{} && $COMPOSER_MIN_STAB && $COMPOSER_UP && $PHPUNIT)'" + + js: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npm i -g corepack && corepack enable + - uses: actions/setup-node@v4 + with: + cache: 'yarn' + cache-dependency-path: | + yarn.lock + package.json + src/**/package.json + - run: yarn --immutable + - run: yarn playwright install + - run: yarn test