# external call not yet setup, only copy to repo at the moment name: PHP Static Checks and Tests Matrix Workflow run-name: ${{ github.actor}} runs PHP-MATRIX-CI on: workflow_call: inputs: php-version: type: string required: false default: '8.5' description: 'PHP versions to use for the checks and tests, default is 8.4 and 8.5, can be a comma-separated list of versions' phpunit-version: type: string required: false default: '^13' description: 'PHPUnit versions to use for the tests, default is ^13, can be a comma-separated list of versions' operating-system: type: string required: false default: 'ubuntu-latest' description: 'Operating systems to run the tests on, default is ubuntu-latest, can be a comma-separated list of operating systems' disable-phan: type: boolean default: false required: false description: 'Set to "true" to skip running phan' composer-directory: type: string required: false default: './' description: 'Directory where composer.json is located, relative to the repository root' source-directory: type: string required: false default: './src' description: 'Directory where the PHP source code is located, relative to the repository root' secrets: opj-package-user: required: true description: 'Username for private package repository' opj-package-api-key: required: true description: 'API key for private package repository' jobs: setup: runs-on: ubuntu-latest outputs: php-version: ${{ steps.set-matrix.outputs.php-version }} phpunit-version: ${{ steps.set-matrix.outputs.phpunit-version }} operating-system: ${{ steps.set-matrix.outputs.operating-system }} steps: - name: Set matrix values id: set-matrix run: | echo "php-version=$(echo '${{ inputs.php-version }}' | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | jq -R . | jq -cs .)" >> $GITHUB_OUTPUT echo "phpunit-version=$(echo '${{ inputs.phpunit-version }}' | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | jq -R . | jq -cs .)" >> $GITHUB_OUTPUT echo "operating-system=$(echo '${{ inputs.operating-system }}' | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | jq -R . | jq -cs .)" >> $GITHUB_OUTPUT php-check-and-test-matrix: needs: setup runs-on: ${{ matrix.operating-system }} strategy: matrix: operating-system: ${{fromJSON(needs.setup.outputs.operating-system)}} php-version: ${{fromJSON(needs.setup.outputs.php-version)}} phpunit-version: ${{fromJSON(needs.setup.outputs.phpunit-version)}} # include: # - operating-system: ubuntu-latest # php-version: '8.4' # phpunit-version: '^13' steps: - name: Checkout code uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} extensions: mbstring, intl, sqlite, pdo_sqlite # ini-values: post_max_size=256M, max_execution_time=180 tools: composer, ${{ inputs.disable-phan == false && 'phan, ' || '' }}phpstan, phpcs, phpunit:${{ matrix.phpunit-version }}, cs2pr # coverage: pcov coverage: xdebug # env: # # Does not work, hast to be set in dependencies step, see below in "install dependencies" # COMPOSER_AUTH: | # { # "http-basic": { # "packages.omnicomproduction.jp": { # "username": "${{ secrets.OPJ_PACKAGE_USER }}", # "password": "${{ secrets.OPJ_PACKAGE_API_KEY }}" # } # } # } - name: Check Tools setup id: check-tools run: | REQUIRED_TOOLS=("composer" "phpunit" "phpstan" ${{ inputs.disable-phan == false && '"phan" ' || '' }}"phpcs" "cs2pr") SKIP_IF_FAILED=("phan") for tool in "${REQUIRED_TOOLS[@]}"; do if ! command -v "$tool" &> /dev/null; then if [[ " ${SKIP_IF_FAILED[@]} " =~ " ${tool} " ]]; then echo "⚠️ Warning: $tool is not installed, but it's optional. Skipping..." echo "${tool}=skip" >> $GITHUB_OUTPUT continue fi echo "❌ Error: $tool failed to load!" exit 1 else # the tool path does not have "setup-php/tools/ inside tool_path=$(which "$tool") if [[ "$tool_path" != */setup-php/tools/* ]]; then if [[ " ${SKIP_IF_FAILED[@]} " =~ " ${tool} " ]]; then echo "⚠️ Warning: $tool installation check failed, but it's optional. Skipping..." echo "${tool}=skip" >> $GITHUB_OUTPUT continue fi echo "❌ Error: $tool path lookup failed!" exit 1 fi tool_version=$("$tool" --version 2>&1) echo "✅ $tool loaded successfully: $tool_version ($(which $tool))" echo "${tool}=ok" >> $GITHUB_OUTPUT fi done - name: Check source folder and composer.json setup run: | if [ ! -d "${{ inputs.source-directory }}" ]; then echo "❌ Error: Source directory '${{ inputs.source-directory }}' does not exist!" exit 1 fi if [ ! -f "${{ inputs.composer-directory }}/composer.json" ]; then echo "❌ Error: composer.json not found in '${{ inputs.composer-directory }}'!" exit 1 fi - name: Setup problem matchers for PHP run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - name: Setup problem matchers for PHPUnit run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - name: Get composer cache directory id: composer-cache run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT working-directory: ${{ inputs.composer-directory }} - name: Cache dependencies uses: actions/cache@v5 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer- - name: Install dependencies run: | composer config http-basic.packages.omnicomproduction.jp "${{ secrets.opj-package-user }}" "${{ secrets.opj-package-api-key }}" composer install --prefer-dist working-directory: ${{ inputs.composer-directory }} - name: Run composer audit id: run-composer-audit run: composer audit --format=json --no-scripts --no-plugins --no-interaction > composer-audit-output.json # some post action with the composer output format file working-directory: ${{ inputs.composer-directory }} - name: Run phpcs id: run-phpcs run: phpcs -q --report=checkstyle --standard=phpcs.xml --ignore=vendor/ ${{ inputs.source-directory }} | cs2pr - name: Run phan id: run-phan if: ${{ ! inputs.disable-phan && steps.check-tools.outputs.phan == 'ok' }} run: phan --analyze-twice --no-progress-bar --config-file=./.phan/config.php # Must have "./tmp" directory set in configuration # if we have "./tmp/phpstan" or anything different adjust the path below - name: "Restore result cache" uses: actions/cache/restore@v5 with: path: ./tmp key: "result-cache-${{ github.run_id }}" restore-keys: | result-cache-v1- - name: Run PHPStan id: run-phpstan run: phpstan analyse --no-progress --configuration=phpstan.neon - name: "Save result cache" uses: actions/cache/save@v5 if: always() with: path: ./tmp key: "result-cache-${{ github.run_id }}" - name: Test with phpunit id: run-phpunit run: | # if we are older than 12 there is no openclover # version can start with ^ and then have numbers, so we need to remove the ^ and then compare the version numbers phpunit_version="${{ matrix.phpunit-version }}" phpunit_version="${phpunit_version#^}" phpunit_version="${phpunit_version%%.*}" if [ "$phpunit_version" -lt 12 ]; then phpunit --colors=never \ --no-coverage \ --coverage-text=phpunit-coverage.txt \ --coverage-clover=phpunit-openclover.xml else phpunit --colors=never \ --no-coverage \ --coverage-text=phpunit-coverage.txt \ --only-summary-for-coverage-text \ --coverage-openclover=phpunit-openclover.xml fi; - name: Code Coverage Summary Report uses: saschanowak/CloverCodeCoverageSummary@1.1.1 with: filename: phpunit-openclover.xml - name: Summary if: always() env: COMPOSER_AUDIT_RESULT: ${{ steps.run-composer-audit.outcome }} COMPOSER_AUDIT_FILE: ${{ inputs.composer-directory }}/composer-audit-output.json PHPCS_RESULT: ${{ steps.run-phpcs.outcome }} PHAN_RESULT: ${{ steps.run-phan.outcome }} PHPSTAN_RESULT: ${{ steps.run-phpstan.outcome }} PHPUNIT_RESULT: ${{ steps.run-phpunit.outcome }} run: | icon() { if [[ "$1" == "success" ]]; then echo "✅"; elif [[ "$1" == "skipped" ]]; then echo "⏭️"; else echo "❌"; fi; } row() { echo "
| Check | Status |
|---|