name: v3 Tests on: pull_request: branches: [ "v3" ] types: [ opened, synchronize, reopened, labeled, unlabeled ] paths: - 'src/**' - 'config/**' - '.github/workflows/tests.yml' - 'bin/**' - 'composer.json' - 'box.json' - '.php-cs-fixer.php' permissions: read-all concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: php-cs-fixer: runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: "Checkout" uses: actions/checkout@v4 - name: "Setup PHP" uses: shivammathur/setup-php@v2 with: php-version: '8.4' extensions: curl, openssl, mbstring ini-values: memory_limit=-1 tools: pecl, composer, php-cs-fixer - name: Run PHP-CS-Fixer fix run: php-cs-fixer fix --dry-run --diff --ansi phpstan: runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: "Checkout" uses: actions/checkout@v4 - name: "Setup PHP" uses: shivammathur/setup-php@v2 with: php-version: '8.4' extensions: curl, openssl, mbstring ini-values: memory_limit=-1 tools: composer env: phpts: zts - name: "Cache Composer packages" id: composer-cache uses: actions/cache@v4 with: path: vendor key: ${{ runner.os }}-phpstan-${{ hashFiles('**/composer.lock') }} restore-keys: | ${{ runner.os }}-phpstan- - name: "Install Dependencies" run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist - name: "Run phpstan" run: vendor/bin/phpstan analyse phpunit: name: "PHPUnit (PHP ${{ matrix.php }})" runs-on: ubuntu-latest timeout-minutes: 10 strategy: matrix: include: - php: '8.4' steps: - name: "Checkout" uses: actions/checkout@v4 - name: "Setup PHP" uses: shivammathur/setup-php@v2 with: php-version: "${{ matrix.php }}" tools: pecl, composer extensions: curl, openssl, mbstring ini-values: memory_limit=-1 - name: "Cache Composer packages" id: composer-cache uses: actions/cache@v4 with: path: vendor key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} restore-keys: | ${{ runner.os }}-php - name: "Install Dependencies" run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist - name: "Run PHPUnit Tests" run: vendor/bin/phpunit tests/ --no-coverage check-gate: name: "Check: need-test label" runs-on: ubuntu-latest outputs: enabled: ${{ steps.gate.outputs.enabled }} steps: - name: Check label id: gate run: | LABELS='${{ toJSON(github.event.pull_request.labels.*.name) }}' if echo "$LABELS" | grep -q '"need-test"'; then echo "enabled=true" >> "$GITHUB_OUTPUT" else echo "enabled=false" >> "$GITHUB_OUTPUT" fi test-bot: name: "Test Bot: analyze PR" needs: check-gate if: needs.check-gate.outputs.enabled == 'true' runs-on: ubuntu-latest permissions: pull-requests: write contents: read outputs: need_test: ${{ steps.bot.outputs.need_test }} gen_matrix_args: ${{ steps.bot.outputs.gen_matrix_args }} gen_matrix_args_tier2: ${{ steps.bot.outputs.gen_matrix_args_tier2 }} php_versions: ${{ steps.bot.outputs.php_versions }} tier2: ${{ steps.bot.outputs.tier2 }} steps: - uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.4' extensions: curl, openssl, mbstring ini-values: memory_limit=-1 tools: composer - name: Install dependencies run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-dev - name: Run dev:test-bot id: bot env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | BOT_JSON=$(php -d opcache.enable_cli=0 bin/spc dev:test-bot \ --pr=${{ github.event.pull_request.number }} \ --repo=${{ github.repository }} 2>/dev/null) echo "need_test=$(echo "$BOT_JSON" | jq -r '.need_test')" >> "$GITHUB_OUTPUT" echo "gen_matrix_args=$(echo "$BOT_JSON" | jq -r '.gen_matrix_args')" >> "$GITHUB_OUTPUT" echo "gen_matrix_args_tier2=$(echo "$BOT_JSON" | jq -r '.gen_matrix_args_tier2')" >> "$GITHUB_OUTPUT" echo "php_versions=$(echo "$BOT_JSON" | jq -c '.php_versions')" >> "$GITHUB_OUTPUT" echo "tier2=$(echo "$BOT_JSON" | jq -r '.tier2')" >> "$GITHUB_OUTPUT" COMMENT_BODY=$(echo "$BOT_JSON" | jq -r '.comment_body') MARKER="" # Find existing bot comment id EXISTING_ID=$(gh api \ repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments \ --jq "[.[] | select(.body | startswith(\"$MARKER\")) | .id] | first // empty") if [ -n "$EXISTING_ID" ]; then gh api --method PATCH \ repos/${{ github.repository }}/issues/comments/"$EXISTING_ID" \ -f body="$COMMENT_BODY" else gh pr comment ${{ github.event.pull_request.number }} \ --repo ${{ github.repository }} \ --body "$COMMENT_BODY" fi gen-matrix: name: "Generate test matrix" needs: test-bot if: needs.test-bot.outputs.need_test == 'true' runs-on: ubuntu-latest outputs: matrix: ${{ steps.build.outputs.matrix }} steps: - uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.4' extensions: curl, openssl, mbstring ini-values: memory_limit=-1 tools: composer - name: Install dependencies run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-dev - name: Build matrix id: build env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GEN_MATRIX_ARGS: ${{ needs.test-bot.outputs.gen_matrix_args }} GEN_MATRIX_ARGS_TIER2: ${{ needs.test-bot.outputs.gen_matrix_args_tier2 }} PHP_VERSIONS: ${{ needs.test-bot.outputs.php_versions }} TIER2: ${{ needs.test-bot.outputs.tier2 }} run: | # Tier1 matrix MATRIX1=$(bin/spc dev:gen-ext-test-matrix $GEN_MATRIX_ARGS 2>/dev/null) # Merge Tier2 if requested if [ "$TIER2" = "true" ] && [ -n "$GEN_MATRIX_ARGS_TIER2" ]; then MATRIX2=$(bin/spc dev:gen-ext-test-matrix $GEN_MATRIX_ARGS_TIER2 2>/dev/null) COMBINED=$(jq -n --argjson m1 "$MATRIX1" --argjson m2 "$MATRIX2" '$m1 + $m2') else COMBINED=$MATRIX1 fi # Expand PHP versions: cartesian product of entries × php_versions FINAL=$(echo "$COMBINED" | jq --argjson versions "$PHP_VERSIONS" \ '[.[] | . as $entry | $versions[] | $entry + {"php-version": .}]') echo "matrix=$(echo "$FINAL" | jq -c '{"combo": .}')" >> "$GITHUB_OUTPUT" ext-test: name: "Ext test: ${{ matrix.combo.extension }} (PHP ${{ matrix.combo.php-version }} · ${{ matrix.combo.os }}-${{ matrix.combo.arch }})" needs: gen-matrix runs-on: ${{ matrix.combo.runner }} timeout-minutes: 120 strategy: fail-fast: false matrix: ${{ fromJSON(needs.gen-matrix.outputs.matrix) }} steps: - uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: 8.4 extensions: curl, openssl, mbstring ini-values: memory_limit=-1 tools: composer env: phpts: nts - name: Install dependencies run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-dev - name: Build env: SPC_USE_SUDO: "yes" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | ./bin/spc doctor --auto-fix ${{ matrix.combo.build-args }} --dl-with-php=${{ matrix.combo.php-version }} # - name: Setup upterm session # if: ${{ failure() }} # uses: owenthereal/action-upterm@v1 - name: Upload logs if: always() && hashFiles('log/**') != '' uses: actions/upload-artifact@v4 with: name: logs-${{ matrix.combo.os }}-${{ matrix.combo.arch }}-${{ matrix.combo.extension }}-php${{ matrix.combo.php-version }} path: log