Files
gh-netresearch-claude-code-…/skills/typo3-testing/references/ci-cd.md
2025-11-30 08:43:13 +08:00

10 KiB

CI/CD Integration for TYPO3 Testing

Continuous Integration and Continuous Deployment workflows for automated TYPO3 extension testing.

GitHub Actions

Basic Workflow

Create .github/workflows/tests.yml:

name: Tests

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  lint:
    name: Lint PHP
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'

      - name: Install dependencies
        run: composer install --no-progress

      - name: Run linting
        run: composer ci:test:php:lint

  phpstan:
    name: PHPStan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'

      - name: Install dependencies
        run: composer install --no-progress

      - name: Run PHPStan
        run: composer ci:test:php:phpstan

  unit:
    name: Unit Tests
    runs-on: ubuntu-latest
    strategy:
      matrix:
        php: ['8.1', '8.2', '8.3', '8.4']

    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP ${{ matrix.php }}
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          coverage: xdebug

      - name: Install dependencies
        run: composer install --no-progress

      - name: Run unit tests
        run: composer ci:test:php:unit

      - name: Upload coverage
        # Upload coverage for all PHP versions
        uses: codecov/codecov-action@v3

  functional:
    name: Functional Tests
    runs-on: ubuntu-latest
    strategy:
      matrix:
        php: ['8.1', '8.2', '8.3', '8.4']
        database: ['mysqli', 'pdo_mysql', 'postgres', 'sqlite']

    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: typo3_test
        ports:
          - 3306:3306
        options: >-
          --health-cmd="mysqladmin ping"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=3

      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: typo3_test
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP ${{ matrix.php }}
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          extensions: ${{ matrix.database == 'postgres' && 'pdo_pgsql' || 'mysqli' }}

      - name: Install dependencies
        run: composer install --no-progress

      - name: Run functional tests
        run: |
          export typo3DatabaseDriver=${{ matrix.database }}
          export typo3DatabaseHost=127.0.0.1
          export typo3DatabaseName=typo3_test
          export typo3DatabaseUsername=${{ matrix.database == 'postgres' && 'postgres' || 'root' }}
          export typo3DatabasePassword=${{ matrix.database == 'postgres' && 'postgres' || 'root' }}
          composer ci:test:php:functional

Matrix Strategy

Test multiple PHP and TYPO3 versions:

strategy:
  fail-fast: false
  matrix:
    php: ['8.1', '8.2', '8.3', '8.4']
    typo3: ['12.4', '13.0']
    exclude:
      - php: '8.1'
        typo3: '13.0'  # TYPO3 v13 requires PHP 8.2+

steps:
  - name: Install TYPO3 v${{ matrix.typo3 }}
    run: |
      composer require "typo3/cms-core:^${{ matrix.typo3 }}" --no-update
      composer update --no-progress

Caching Dependencies

- name: Cache Composer dependencies
  uses: actions/cache@v3
  with:
    path: ~/.composer/cache
    key: composer-${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('composer.lock') }}
    restore-keys: |
      composer-${{ runner.os }}-${{ matrix.php }}-
      composer-${{ runner.os }}-

- name: Install dependencies
  run: composer install --no-progress --prefer-dist

Code Coverage

- name: Run tests with coverage
  run: vendor/bin/phpunit -c Build/phpunit/UnitTests.xml --coverage-clover coverage.xml

- name: Upload coverage to Codecov
  uses: codecov/codecov-action@v3
  with:
    file: ./coverage.xml
    flags: unittests
    name: codecov-umbrella

GitLab CI

Basic Pipeline

Create .gitlab-ci.yml:

variables:
  COMPOSER_CACHE_DIR: ".composer-cache"
  MYSQL_ROOT_PASSWORD: "root"
  MYSQL_DATABASE: "typo3_test"

cache:
  key: "$CI_COMMIT_REF_SLUG"
  paths:
    - .composer-cache/

stages:
  - lint
  - analyze
  - test

.php:
  image: php:${PHP_VERSION}-cli
  before_script:
    - apt-get update && apt-get install -y git zip unzip
    - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
    - composer install --no-progress

lint:
  extends: .php
  stage: lint
  variables:
    PHP_VERSION: "8.2"
  script:
    - composer ci:test:php:lint

phpstan:
  extends: .php
  stage: analyze
  variables:
    PHP_VERSION: "8.2"
  script:
    - composer ci:test:php:phpstan

cgl:
  extends: .php
  stage: analyze
  variables:
    PHP_VERSION: "8.2"
  script:
    - composer ci:test:php:cgl

unit:8.1:
  extends: .php
  stage: test
  variables:
    PHP_VERSION: "8.1"
  script:
    - composer ci:test:php:unit

unit:8.2:
  extends: .php
  stage: test
  variables:
    PHP_VERSION: "8.2"
  script:
    - composer ci:test:php:unit
  coverage: '/^\s*Lines:\s*\d+.\d+\%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml

functional:8.2:
  extends: .php
  stage: test
  variables:
    PHP_VERSION: "8.2"
    typo3DatabaseDriver: "mysqli"
    typo3DatabaseHost: "mysql"
    typo3DatabaseName: "typo3_test"
    typo3DatabaseUsername: "root"
    typo3DatabasePassword: "root"
  services:
    - mysql:8.0
  script:
    - composer ci:test:php:functional

Multi-Database Testing

.functional:
  extends: .php
  stage: test
  variables:
    PHP_VERSION: "8.2"
  script:
    - composer ci:test:php:functional

functional:mysql:
  extends: .functional
  variables:
    typo3DatabaseDriver: "mysqli"
    typo3DatabaseHost: "mysql"
    typo3DatabaseName: "typo3_test"
    typo3DatabaseUsername: "root"
    typo3DatabasePassword: "root"
  services:
    - mysql:8.0

functional:postgres:
  extends: .functional
  variables:
    typo3DatabaseDriver: "pdo_pgsql"
    typo3DatabaseHost: "postgres"
    typo3DatabaseName: "typo3_test"
    typo3DatabaseUsername: "postgres"
    typo3DatabasePassword: "postgres"
  services:
    - postgres:15
  before_script:
    - apt-get update && apt-get install -y libpq-dev
    - docker-php-ext-install pdo_pgsql

functional:sqlite:
  extends: .functional
  variables:
    typo3DatabaseDriver: "pdo_sqlite"

Best Practices

1. Fast Feedback Loop

Order jobs by execution time (fastest first):

stages:
  - lint        # ~30 seconds
  - analyze     # ~1-2 minutes (PHPStan, CGL)
  - unit        # ~2-5 minutes
  - functional  # ~5-15 minutes
  - acceptance  # ~15-30 minutes

2. Fail Fast

strategy:
  fail-fast: true  # Stop on first failure
  matrix:
    php: ['8.1', '8.2', '8.3', '8.4']

3. Parallel Execution

# GitHub Actions - parallel jobs
jobs:
  lint: ...
  phpstan: ...
  unit: ...
  # All run in parallel

# GitLab CI - parallel jobs
test:
  parallel:
    matrix:
      - PHP_VERSION: ['8.1', '8.2', '8.3']

4. Cache Dependencies

GitHub Actions:

- uses: actions/cache@v3
  with:
    path: ~/.composer/cache
    key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}

GitLab CI:

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .composer-cache/

5. Matrix Testing

Test critical combinations:

strategy:
  matrix:
    include:
      # Minimum supported versions
      - php: '8.1'
        typo3: '12.4'

      # Current stable
      - php: '8.2'
        typo3: '12.4'

      # Latest versions
      - php: '8.3'
        typo3: '13.0'

6. Artifacts and Reports

- name: Archive test results
  if: failure()
  uses: actions/upload-artifact@v3
  with:
    name: test-results
    path: |
      var/log/
      typo3temp/var/tests/

7. Notifications

GitHub Actions:

- name: Slack Notification
  if: failure()
  uses: rtCamp/action-slack-notify@v2
  env:
    SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

Quality Gates

Required Checks

Define which checks must pass:

GitHub:

# .github/branch-protection.json
{
  "required_status_checks": {
    "strict": true,
    "contexts": [
      "lint",
      "phpstan",
      "unit (8.2)",
      "functional (8.2, mysqli)"
    ]
  }
}

GitLab:

# .gitlab-ci.yml
unit:8.2:
  only:
    - merge_requests
  allow_failure: false  # Required check

Coverage Requirements

- name: Check code coverage
  run: |
    coverage=$(vendor/bin/phpunit --coverage-text | grep "Lines:" | awk '{print $2}' | sed 's/%//')
    if (( $(echo "$coverage < 80" | bc -l) )); then
      echo "Coverage $coverage% is below 80%"
      exit 1
    fi

Environment-Specific Configuration

Development Branch

on:
  push:
    branches: [ develop ]

# Run all checks, allow failures
jobs:
  experimental:
    continue-on-error: true
    strategy:
      matrix:
        php: ['8.4']  # Experimental PHP version

Production Branch

on:
  push:
    branches: [ main ]

# Strict checks only
jobs:
  tests:
    strategy:
      fail-fast: true
      matrix:
        php: ['8.2']  # LTS version only

Pull Requests

on:
  pull_request:

# Full test matrix
jobs:
  tests:
    strategy:
      matrix:
        php: ['8.1', '8.2', '8.3', '8.4']
        database: ['mysqli', 'postgres']

Resources