10 KiB
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']