PHP Classes

File: .github/workflows/ci.yml

Recommend this page to a friend!
  Packages of Mohamed Abdulalim   Persistence   .github/workflows/ci.yml   Download  
File: .github/workflows/ci.yml
Role: Example script
Content type: text/plain
Description: Example script
Class: Persistence
Retrieve database table records by a given order
Author: By
Last change:
Date: 20 days ago
Size: 17,223 bytes
 

Contents

Class file image Download
name: CI on: pull_request: branches: - main push: branches: - main workflow_dispatch: permissions: contents: read concurrency: group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: workflow-lint: name: Workflow lint runs-on: ubuntu-24.04 timeout-minutes: 5 steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install and run actionlint shell: bash run: | set -euo pipefail curl --fail --location --silent --show-error \ --output actionlint.tar.gz \ https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz printf '%s %s\n' '8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8' 'actionlint.tar.gz' | sha256sum --check tar -xzf actionlint.tar.gz actionlint ./actionlint -color quality: name: Quality (PHP 8.2) runs-on: ubuntu-24.04 timeout-minutes: 15 steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Setup PHP uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 with: php-version: '8.2' extensions: pdo, pdo_mysql coverage: none tools: composer:2.10.2 - name: Print tool versions shell: bash run: | set -euo pipefail php -v composer --version - name: Validate and resolve dependencies shell: bash run: | set -euo pipefail composer validate --strict composer update \ --no-interaction \ --prefer-dist \ --no-progress composer check-platform-reqs composer audit \ --no-interaction \ --abandoned=fail - name: PHP syntax check shell: bash run: | set -euo pipefail shopt -s globstar nullglob files=(src/**/*.php tests/**/*.php .php-cs-fixer.php) if [[ -d examples ]]; then files+=(examples/**/*.php) fi for file in "${files[@]}"; do php -l "$file" done - name: PHPStan shell: bash run: | set -euo pipefail vendor/bin/phpstan analyse -c phpstan.neon --no-progress - name: Code style shell: bash run: | set -euo pipefail vendor/bin/php-cs-fixer fix --dry-run --diff - name: Repository integrity shell: bash run: | set -euo pipefail git diff --exit-code unit-regression: name: Unit/Regression (PHP ${{ matrix.php }}) runs-on: ubuntu-24.04 timeout-minutes: 15 strategy: fail-fast: false matrix: php: - '8.2' - '8.3' - '8.4' - '8.5' steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Setup PHP uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 with: php-version: ${{ matrix.php }} extensions: pdo, pdo_mysql coverage: none tools: composer:2.10.2 - name: Print tool versions shell: bash run: | set -euo pipefail php -v composer --version - name: Validate and resolve dependencies shell: bash run: | set -euo pipefail composer validate --strict composer update \ --no-interaction \ --prefer-dist \ --no-progress composer check-platform-reqs composer audit \ --no-interaction \ --abandoned=fail - name: Run Unit and Regression suites shell: bash run: | set -euo pipefail vendor/bin/phpunit --testsuite unit vendor/bin/phpunit --testsuite regression - name: Repository integrity shell: bash run: | set -euo pipefail git diff --exit-code lowest-dependencies: name: Lowest dependencies (PHP 8.2, MySQL 8.4.10) runs-on: ubuntu-24.04 timeout-minutes: 25 services: mysql: image: mysql:8.4.10 env: MYSQL_DATABASE: maatify_persistence_test MYSQL_USER: maatify_persistence MYSQL_PASSWORD: persistence_ci_password MYSQL_ROOT_PASSWORD: root_ci_password ports: - 3306:3306 options: >- --health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -proot_ci_password" --health-interval=10s --health-timeout=5s --health-retries=30 env: PERSISTENCE_TEST_MYSQL_DSN: mysql:host=127.0.0.1;port=3306;dbname=maatify_persistence_test;charset=utf8mb4 PERSISTENCE_TEST_MYSQL_USER: maatify_persistence PERSISTENCE_TEST_MYSQL_PASSWORD: persistence_ci_password steps: - name: Checkout id: checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Setup PHP id: setup-php uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 with: php-version: '8.2' extensions: pdo, pdo_mysql coverage: none tools: composer:2.10.2 - name: Print tool versions shell: bash run: | set -euo pipefail php -v composer --version - name: Validate and resolve lowest dependencies shell: bash run: | set -euo pipefail composer validate --strict composer update \ --prefer-lowest \ --prefer-stable \ --no-interaction \ --prefer-dist \ --no-progress composer check-platform-reqs composer audit \ --no-interaction \ --abandoned=fail - name: Static analysis and code style shell: bash run: | set -euo pipefail vendor/bin/phpstan analyse -c phpstan.neon --no-progress vendor/bin/php-cs-fixer fix --dry-run --diff - name: Configure MySQL trigger creation policy shell: bash run: | set -euo pipefail container_id='${{ job.services.mysql.id }}' value="$(docker exec \ -e MYSQL_PWD=root_ci_password \ "$container_id" \ mysql \ --user=root \ --batch \ --skip-column-names \ --execute=" SET GLOBAL log_bin_trust_function_creators = 1; SELECT @@GLOBAL.log_bin_trust_function_creators; ")" if [[ "$value" != "1" ]]; then echo "Expected @@GLOBAL.log_bin_trust_function_creators to be 1, got: $value" exit 1 fi - name: Run test suites shell: bash run: | set -euo pipefail vendor/bin/phpunit --testsuite unit vendor/bin/phpunit --testsuite regression vendor/bin/phpunit --testsuite integration vendor/bin/phpunit --testsuite integration vendor/bin/phpunit - name: Verify MySQL residue if: ${{ always() && !cancelled() && steps.setup-php.outcome == 'success' }} shell: bash run: | set -euo pipefail php <<'PHP' <?php declare(strict_types=1); $dsn = getenv('PERSISTENCE_TEST_MYSQL_DSN'); $user = getenv('PERSISTENCE_TEST_MYSQL_USER'); $password = getenv('PERSISTENCE_TEST_MYSQL_PASSWORD'); if (!is_string($dsn) || $dsn === '' || !is_string($user) || $user === '' || !is_string($password)) { fwrite(STDERR, "Missing MySQL test environment configuration.\n"); exit(1); } $pdo = new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); $schema = (string) $pdo->query('SELECT DATABASE()')->fetchColumn(); $tables = [ 'maa_persistence_test_global_ordering', 'maa_persistence_test_scoped_ordering', 'maa_persistence_test_pagination_items', ]; $triggers = [ 'maa_persistence_test_fail_global_target_update', 'maa_persistence_test_fail_scoped_target_update', ]; $tableStatement = $pdo->prepare( 'SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME IN (?, ?, ?) ORDER BY TABLE_NAME' ); $tableStatement->execute([$schema, ...$tables]); $remainingTables = $tableStatement->fetchAll(PDO::FETCH_COLUMN); $triggerStatement = $pdo->prepare( 'SELECT TRIGGER_NAME FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = ? AND TRIGGER_NAME IN (?, ?) ORDER BY TRIGGER_NAME' ); $triggerStatement->execute([$schema, ...$triggers]); $remainingTriggers = $triggerStatement->fetchAll(PDO::FETCH_COLUMN); if ($remainingTables !== [] || $remainingTriggers !== []) { fwrite(STDERR, "MySQL residue detected.\n"); if ($remainingTables !== []) { fwrite(STDERR, 'Remaining tables: ' . implode(', ', $remainingTables) . "\n"); } if ($remainingTriggers !== []) { fwrite(STDERR, 'Remaining triggers: ' . implode(', ', $remainingTriggers) . "\n"); } exit(1); } echo "MySQL residue verification passed: no package test tables or triggers remain.\n"; PHP - name: Repository integrity if: ${{ always() && !cancelled() && steps.checkout.outcome == 'success' }} shell: bash run: | set -euo pipefail git diff --exit-code integration: name: Integration (PHP ${{ matrix.php }}, MySQL 8.4.10) runs-on: ubuntu-24.04 timeout-minutes: 25 strategy: fail-fast: false matrix: php: - '8.2' - '8.5' services: mysql: image: mysql:8.4.10 env: MYSQL_DATABASE: maatify_persistence_test MYSQL_USER: maatify_persistence MYSQL_PASSWORD: persistence_ci_password MYSQL_ROOT_PASSWORD: root_ci_password ports: - 3306:3306 options: >- --health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -proot_ci_password" --health-interval=10s --health-timeout=5s --health-retries=30 env: PERSISTENCE_TEST_MYSQL_DSN: mysql:host=127.0.0.1;port=3306;dbname=maatify_persistence_test;charset=utf8mb4 PERSISTENCE_TEST_MYSQL_USER: maatify_persistence PERSISTENCE_TEST_MYSQL_PASSWORD: persistence_ci_password steps: - name: Checkout id: checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Setup PHP id: setup-php uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 with: php-version: ${{ matrix.php }} extensions: pdo, pdo_mysql coverage: none tools: composer:2.10.2 - name: Print tool versions shell: bash run: | set -euo pipefail php -v composer --version - name: Validate and resolve dependencies shell: bash run: | set -euo pipefail composer validate --strict composer update \ --no-interaction \ --prefer-dist \ --no-progress composer check-platform-reqs composer audit \ --no-interaction \ --abandoned=fail - name: Configure MySQL trigger creation policy shell: bash run: | set -euo pipefail container_id='${{ job.services.mysql.id }}' value="$(docker exec \ -e MYSQL_PWD=root_ci_password \ "$container_id" \ mysql \ --user=root \ --batch \ --skip-column-names \ --execute=" SET GLOBAL log_bin_trust_function_creators = 1; SELECT @@GLOBAL.log_bin_trust_function_creators; ")" if [[ "$value" != "1" ]]; then echo "Expected @@GLOBAL.log_bin_trust_function_creators to be 1, got: $value" exit 1 fi - name: Run Integration and full suites shell: bash run: | set -euo pipefail vendor/bin/phpunit --testsuite integration vendor/bin/phpunit --testsuite integration vendor/bin/phpunit - name: Verify MySQL residue if: ${{ always() && !cancelled() && steps.setup-php.outcome == 'success' }} shell: bash run: | set -euo pipefail php <<'PHP' <?php declare(strict_types=1); $dsn = getenv('PERSISTENCE_TEST_MYSQL_DSN'); $user = getenv('PERSISTENCE_TEST_MYSQL_USER'); $password = getenv('PERSISTENCE_TEST_MYSQL_PASSWORD'); if (!is_string($dsn) || $dsn === '' || !is_string($user) || $user === '' || !is_string($password)) { fwrite(STDERR, "Missing MySQL test environment configuration.\n"); exit(1); } $pdo = new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); $schema = (string) $pdo->query('SELECT DATABASE()')->fetchColumn(); $tables = [ 'maa_persistence_test_global_ordering', 'maa_persistence_test_scoped_ordering', 'maa_persistence_test_pagination_items', ]; $triggers = [ 'maa_persistence_test_fail_global_target_update', 'maa_persistence_test_fail_scoped_target_update', ]; $tableStatement = $pdo->prepare( 'SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME IN (?, ?, ?) ORDER BY TABLE_NAME' ); $tableStatement->execute([$schema, ...$tables]); $remainingTables = $tableStatement->fetchAll(PDO::FETCH_COLUMN); $triggerStatement = $pdo->prepare( 'SELECT TRIGGER_NAME FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = ? AND TRIGGER_NAME IN (?, ?) ORDER BY TRIGGER_NAME' ); $triggerStatement->execute([$schema, ...$triggers]); $remainingTriggers = $triggerStatement->fetchAll(PDO::FETCH_COLUMN); if ($remainingTables !== [] || $remainingTriggers !== []) { fwrite(STDERR, "MySQL residue detected.\n"); if ($remainingTables !== []) { fwrite(STDERR, 'Remaining tables: ' . implode(', ', $remainingTables) . "\n"); } if ($remainingTriggers !== []) { fwrite(STDERR, 'Remaining triggers: ' . implode(', ', $remainingTriggers) . "\n"); } exit(1); } echo "MySQL residue verification passed: no package test tables or triggers remain.\n"; PHP - name: Repository integrity if: ${{ always() && !cancelled() && steps.checkout.outcome == 'success' }} shell: bash run: | set -euo pipefail git diff --exit-code ci-gate: name: CI Gate runs-on: ubuntu-24.04 timeout-minutes: 5 needs: - workflow-lint - quality - unit-regression - lowest-dependencies - integration if: ${{ always() }} steps: - name: Check required job results shell: bash env: WORKFLOW_LINT_RESULT: ${{ needs.workflow-lint.result }} QUALITY_RESULT: ${{ needs.quality.result }} UNIT_REGRESSION_RESULT: ${{ needs.unit-regression.result }} LOWEST_DEPENDENCIES_RESULT: ${{ needs.lowest-dependencies.result }} INTEGRATION_RESULT: ${{ needs.integration.result }} run: | set -euo pipefail declare -A results=( [workflow-lint]="$WORKFLOW_LINT_RESULT" [quality]="$QUALITY_RESULT" [unit-regression]="$UNIT_REGRESSION_RESULT" [lowest-dependencies]="$LOWEST_DEPENDENCIES_RESULT" [integration]="$INTEGRATION_RESULT" ) failed=0 for job in workflow-lint quality unit-regression lowest-dependencies integration; do result="${results[$job]}" echo "$job: $result" if [[ "$result" != "success" ]]; then failed=1 fi done if [[ "$failed" -ne 0 ]]; then echo "CI Gate failed because at least one required job did not conclude with success." exit 1 fi echo "CI Gate passed: all required jobs concluded with success."