FEATURE: Atomic events (commitAll) and simplifies locking (removes content stream closing)
#8640
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: [ '[0-9]+.[0-9]' ] | |
| pull_request: | |
| branches: [ '[0-9]+.[0-9]' ] | |
| permissions: {} | |
| env: | |
| FLOW_CONTEXT: Testing | |
| NEOS_TARGET_VERSION: 9.0 | |
| NEOS_DIST_FOLDER: neos-development-distribution | |
| NEOS_FOLDER: neos-development-collection | |
| jobs: | |
| static-analysis: | |
| permissions: | |
| contents: read # to fetch code (actions/checkout) | |
| if: "!contains(github.event.head_commit.message, '[skip ci]')" | |
| name: "Static analysis (PHP ${{ matrix.php }})" | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| php: ['8.4', '8.5'] | |
| defaults: | |
| run: | |
| working-directory: ${{ env.NEOS_DIST_FOLDER }} | |
| steps: | |
| # Local composite actions are resolved from the workspace root, so the | |
| # workflow's own repository must be checked out before `prepare-neos` runs. | |
| - name: Checkout workflow repository | |
| uses: actions/checkout@v5 | |
| - uses: ./.github/actions/prepare-neos | |
| with: | |
| php-version: ${{ matrix.php }} | |
| dependencies: ${{ matrix.dependencies || 'highest' }} | |
| collection-path: ${{ env.NEOS_FOLDER }} | |
| distribution-path: ${{ env.NEOS_DIST_FOLDER }} | |
| - name: Static analysis (phpcs + phpstan + distributionintegrity) | |
| run: | | |
| cd Packages/Neos | |
| composer lint | |
| unit-tests: | |
| permissions: | |
| contents: read # to fetch code (actions/checkout) | |
| if: "!contains(github.event.head_commit.message, '[skip ci]')" | |
| name: "Unit tests (PHP ${{ matrix.php }}, deps: ${{ matrix.dependencies || 'highest' }})" | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| php: ['8.4', '8.5'] | |
| services: | |
| redis: | |
| image: redis:alpine | |
| ports: | |
| - "6379:6379" | |
| options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 | |
| memcached: | |
| image: memcached:alpine | |
| ports: | |
| - "11211:11211" | |
| defaults: | |
| run: | |
| working-directory: ${{ env.NEOS_DIST_FOLDER }} | |
| steps: | |
| - name: Checkout workflow repository | |
| uses: actions/checkout@v5 | |
| - uses: ./.github/actions/prepare-neos | |
| with: | |
| php-version: ${{ matrix.php }} | |
| dependencies: ${{ matrix.dependencies || 'highest' }} | |
| collection-path: ${{ env.NEOS_FOLDER }} | |
| distribution-path: ${{ env.NEOS_DIST_FOLDER }} | |
| - name: Run unit tests | |
| run: bin/phpunit --colors -c Build/BuildEssentials/PhpUnit/UnitTests.xml --verbose | |
| functional-tests: | |
| permissions: | |
| contents: read # to fetch code (actions/checkout) | |
| if: "!contains(github.event.head_commit.message, '[skip ci]')" | |
| name: "Functional tests (PHP ${{ matrix.php }}, ${{ matrix.db.image }})" | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| php: ['8.4', '8.5'] | |
| db: | |
| - { engine: mysql, image: 'mariadb:10.8', port: 3306, options: '--health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3' } | |
| - { engine: pgsql, image: 'postgres:18.3', port: 5432, options: '--health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3' } | |
| include: | |
| # Additional MySQL engines on the most-supported PHP version. | |
| - { php: '8.4', db: { engine: mysql, image: 'mysql:8.0', port: 3306, options: '--health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| - { php: '8.4', db: { engine: mysql, image: 'mysql:8.4', port: 3306, options: '--health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| # Bleeding-edge engines. | |
| - { php: '8.5', db: { engine: mysql, image: 'mariadb:12.2', port: 3306, options: '--health-cmd="healthcheck.sh --connect --innodb_initialized" --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| - { php: '8.5', db: { engine: pgsql, image: 'postgres:18-alpine', port: 5432, options: '--health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| services: | |
| database: | |
| image: ${{ matrix.db.image }} | |
| env: | |
| MYSQL_USER: neos | |
| MYSQL_PASSWORD: neos | |
| MYSQL_DATABASE: flow_functional_testing | |
| MYSQL_ROOT_PASSWORD: neos | |
| POSTGRES_USER: neos | |
| POSTGRES_PASSWORD: neos | |
| POSTGRES_DB: flow_functional_testing | |
| ports: | |
| - "${{ matrix.db.port }}:${{ matrix.db.port }}" | |
| options: ${{ matrix.db.options }} | |
| redis: | |
| image: redis:alpine | |
| ports: | |
| - "6379:6379" | |
| options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 | |
| memcached: | |
| image: memcached:alpine | |
| ports: | |
| - "11211:11211" | |
| defaults: | |
| run: | |
| working-directory: ${{ env.NEOS_DIST_FOLDER }} | |
| steps: | |
| - name: Checkout workflow repository | |
| uses: actions/checkout@v5 | |
| - uses: ./.github/actions/prepare-neos | |
| with: | |
| php-version: ${{ matrix.php }} | |
| dependencies: ${{ matrix.dependencies || 'highest' }} | |
| collection-path: ${{ env.NEOS_FOLDER }} | |
| distribution-path: ${{ env.NEOS_DIST_FOLDER }} | |
| - uses: ./.github/actions/configure-neos | |
| with: | |
| db-engine: ${{ matrix.db.engine }} | |
| db-port: ${{ matrix.db.port }} | |
| working-directory: ${{ env.NEOS_DIST_FOLDER }} | |
| flow-context: ${{ env.FLOW_CONTEXT }} | |
| - name: Run migrations to test if they work | |
| run: FLOW_CONTEXT=Testing ./flow doctrine:migrate | |
| - name: Run functional tests | |
| # Postgres skips the CR-specific functional tests (CR is mysql-only in 9.0). | |
| run: ${{ matrix.db.engine == 'pgsql' && 'SKIP_CR_POSTGRESQL_TESTS=1' || '' }} bin/phpunit --colors --stop-on-failure -c Build/BuildEssentials/PhpUnit/FunctionalTests.xml --testsuite "Neos tests" --verbose | |
| parallel-tests: | |
| permissions: | |
| contents: read # to fetch code (actions/checkout) | |
| if: "!contains(github.event.head_commit.message, '[skip ci]')" | |
| name: "Parallel tests (PHP ${{ matrix.php }}, ${{ matrix.db.image }})" | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| php: ['8.4', '8.5'] | |
| db: | |
| - { engine: mysql, image: 'mariadb:10.8', port: 3306, options: '--health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3' } | |
| # TODO: enable parallel tests also for Postgres | |
| # - { engine: pgsql, image: 'postgres:18.3', port: 5432, options: '--health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3' } | |
| include: | |
| # Additional MySQL engines on the most-supported PHP version. | |
| - { php: '8.4', db: { engine: mysql, image: 'mysql:8.0', port: 3306, options: '--health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| - { php: '8.4', db: { engine: mysql, image: 'mysql:8.4', port: 3306, options: '--health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| # Bleeding-edge engines. | |
| - { php: '8.5', db: { engine: mysql, image: 'mariadb:12.2', port: 3306, options: '--health-cmd="healthcheck.sh --connect --innodb_initialized" --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| services: | |
| database: | |
| image: ${{ matrix.db.image }} | |
| env: | |
| MYSQL_USER: neos | |
| MYSQL_PASSWORD: neos | |
| MYSQL_DATABASE: flow_functional_testing | |
| MYSQL_ROOT_PASSWORD: neos | |
| POSTGRES_USER: neos | |
| POSTGRES_PASSWORD: neos | |
| POSTGRES_DB: flow_functional_testing | |
| POSTGRES_ROOT_PASSWORD: neos | |
| ports: | |
| - "${{ matrix.db.port }}:${{ matrix.db.port }}" | |
| options: ${{ matrix.db.options }} | |
| # Postgres behavioral tests still need a mariadb instance because the | |
| # DoctrineDbalAdapter content graph projection only supports mysql today. | |
| mariadb: | |
| image: mariadb:10.8 | |
| env: | |
| MYSQL_USER: neos | |
| MYSQL_PASSWORD: neos | |
| MYSQL_DATABASE: flow_functional_testing | |
| MYSQL_ROOT_PASSWORD: neos | |
| ports: | |
| - "3307:3306" | |
| options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 | |
| redis: | |
| image: redis:alpine | |
| ports: | |
| - "6379:6379" | |
| options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 | |
| memcached: | |
| image: memcached:alpine | |
| ports: | |
| - "11211:11211" | |
| defaults: | |
| run: | |
| working-directory: ${{ env.NEOS_DIST_FOLDER }} | |
| steps: | |
| - name: Checkout workflow repository | |
| uses: actions/checkout@v5 | |
| - uses: ./.github/actions/prepare-neos | |
| with: | |
| php-version: ${{ matrix.php }} | |
| dependencies: ${{ matrix.dependencies || 'highest' }} | |
| collection-path: ${{ env.NEOS_FOLDER }} | |
| distribution-path: ${{ env.NEOS_DIST_FOLDER }} | |
| - uses: ./.github/actions/configure-behavioral-tests | |
| with: | |
| working-directory: ${{ env.NEOS_DIST_FOLDER }} | |
| - name: Run Parallel Tests for the ES CR | |
| id: paralleltests | |
| timeout-minutes: 30 | |
| continue-on-error: true | |
| run: | | |
| cd Packages/Neos | |
| composer test:parallel | |
| - name: Fail pipeline if Parallel Tests broke | |
| if: matrix.db.engine == 'mysql' && steps.paralleltests.outcome != 'success' | |
| shell: bash | |
| run: | | |
| cd Packages/Neos | |
| cat Neos.ContentRepository.BehavioralTests/Tests/Parallel/log.txt | |
| echo "\n\nDumping last 100 events\n\n" | |
| mysql -u neos -pneos -h 127.0.0.1 -P ${{ matrix.db.port }} flow_functional_testing --table < <(echo "SELECT * FROM cr_test_parallel_events ORDER BY sequenceNumber DESC LIMIT 100") | |
| exit 1 | |
| behavioral-tests: | |
| permissions: | |
| contents: read # to fetch code (actions/checkout) | |
| if: "!contains(github.event.head_commit.message, '[skip ci]')" | |
| name: "Behavioral tests (PHP ${{ matrix.php }}, ${{ matrix.db.image }})" | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| php: ['8.4', '8.5'] | |
| db: | |
| - { engine: mysql, image: 'mariadb:10.8', port: 3306, options: '--health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3' } | |
| include: | |
| # Additional MySQL engines on the most-supported PHP version. | |
| - { php: '8.4', db: { engine: mysql, image: 'mysql:8.0', port: 3306, options: '--health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| - { php: '8.4', db: { engine: mysql, image: 'mysql:8.4', port: 3306, options: '--health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| - { php: '8.4', db: { engine: pgsql, image: 'postgres:18.3', port: 5432, options: '--health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| # Bleeding-edge engines. | |
| - { php: '8.5', db: { engine: mysql, image: 'mariadb:12.2', port: 3306, options: '--health-cmd="healthcheck.sh --connect --innodb_initialized" --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| - { php: '8.5', db: { engine: pgsql, image: 'postgres:18-alpine', port: 5432, options: '--health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3' } } | |
| services: | |
| database: | |
| image: ${{ matrix.db.image }} | |
| env: | |
| MYSQL_USER: neos | |
| MYSQL_PASSWORD: neos | |
| MYSQL_DATABASE: flow_functional_testing | |
| MYSQL_ROOT_PASSWORD: neos | |
| POSTGRES_USER: neos | |
| POSTGRES_PASSWORD: neos | |
| POSTGRES_DB: flow_functional_testing | |
| POSTGRES_ROOT_PASSWORD: neos | |
| ports: | |
| - "${{ matrix.db.port }}:${{ matrix.db.port }}" | |
| options: ${{ matrix.db.options }} | |
| # Postgres behavioral tests still need a mariadb instance because the | |
| # DoctrineDbalAdapter content graph projection only supports mysql today. | |
| mariadb: | |
| image: mariadb:10.8 | |
| env: | |
| MYSQL_USER: neos | |
| MYSQL_PASSWORD: neos | |
| MYSQL_DATABASE: flow_functional_testing | |
| MYSQL_ROOT_PASSWORD: neos | |
| ports: | |
| - "3307:3306" | |
| options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 | |
| redis: | |
| image: redis:alpine | |
| ports: | |
| - "6379:6379" | |
| options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 | |
| memcached: | |
| image: memcached:alpine | |
| ports: | |
| - "11211:11211" | |
| defaults: | |
| run: | |
| working-directory: ${{ env.NEOS_DIST_FOLDER }} | |
| steps: | |
| - name: Checkout workflow repository | |
| uses: actions/checkout@v5 | |
| - uses: ./.github/actions/prepare-neos | |
| with: | |
| php-version: ${{ matrix.php }} | |
| dependencies: ${{ matrix.dependencies || 'highest' }} | |
| collection-path: ${{ env.NEOS_FOLDER }} | |
| distribution-path: ${{ env.NEOS_DIST_FOLDER }} | |
| - uses: ./.github/actions/configure-behavioral-tests | |
| with: | |
| working-directory: ${{ env.NEOS_DIST_FOLDER }} | |
| - name: Run Behavioral Tests (ES CR && Neos.Neos) | |
| id: escrtests | |
| # Continue on error so we always reach the DB-dump upload step below. | |
| continue-on-error: true | |
| run: | | |
| mkdir -p ${{ github.workspace }}/Data/DebugDatabaseDumps | |
| touch ${{ github.workspace }}/Data/DebugDatabaseDumps/keep | |
| export FLOW_CONTEXT=${{ matrix.db.engine == 'pgsql' && 'Testing/Behat/Postgres' || 'Testing/Behat' }} | |
| ./flow package:list --loading-order | |
| ./flow doctrine:migrate --quiet | |
| cd Packages/Neos | |
| # Don't exit early — we want to reach the DB-dump step on failure. | |
| set +e | |
| ( | |
| set -e | |
| composer test:behavioral -- -vvv --stop-on-failure | |
| ${{ matrix.db.engine == 'mysql' && 'composer run test:behavioral-maria-mysql -- -vvv --stop-on-failure' || 'true' }} | |
| ) | |
| retVal=$? | |
| # automatically search for race conditions | |
| cd ../../ | |
| ./flow raceConditionTracker:analyzeTrace --store-trace ${{ github.workspace }}/Data/DebugDatabaseDumps/race-trace.ndjson || true | |
| set -e | |
| if [ $retVal -ne 0 ]; then | |
| echo "DUMPING POSTGRES AND MYSQL DATABASE (because of error)" | |
| echo "copying logs" | |
| cp -R Data/Logs ${{ github.workspace }}/Data/DebugDatabaseDumps/Logs | |
| sudo DEBIAN_FRONTEND=noninteractive apt -y remove mysql-client libmysqlclient-dev mysql-server | |
| sudo DEBIAN_FRONTEND=noninteractive apt -y autoremove | |
| sudo DEBIAN_FRONTEND=noninteractive apt -y autoclean | |
| sudo apt-get update | |
| sudo apt-get install -y postgresql-client mariadb-client | |
| echo "writing PW file" | |
| touch ~/.pgpass | |
| echo "127.0.0.1:5432:flow_functional_testing:neos:neos" > ~/.pgpass | |
| chmod 600 ~/.pgpass | |
| if [ "${{ matrix.db.engine }}" == "pgsql" ]; then | |
| echo "starting pg_dump" | |
| pg_dump --file=${{ github.workspace }}/Data/DebugDatabaseDumps/pg_dump.sql --format=plain --no-owner --dbname=flow_functional_testing --host=127.0.0.1 --username=neos --no-password | |
| echo "pg_dump finished" | |
| fi | |
| echo "starting mysqldump" | |
| mysqldump --force --host=127.0.0.1 -u neos -pneos flow_functional_testing > ${{ github.workspace }}/Data/DebugDatabaseDumps/mysqldump.sql | |
| fi | |
| exit $retVal | |
| - name: Upload Postgres/Mysql DB dump | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: database-dumps-${{ matrix.php }}-${{ matrix.db.engine }} | |
| path: Data/DebugDatabaseDumps | |
| - name: Fail pipeline if ES CR tests broke (after uploading artifacts) | |
| if: steps.escrtests.outcome != 'success' | |
| # Surface failure here so the upload-artifact step has a chance to run. | |
| # See https://stackoverflow.com/a/58003436/4921449 | |
| run: | | |
| echo '${{ toJSON(steps) }}' | |
| exit 1 | |
| buildall: | |
| if: "!contains(github.event.head_commit.message, '[skip ci]')" | |
| runs-on: ubuntu-latest | |
| name: CI build (matrix) | |
| needs: [static-analysis, unit-tests, functional-tests, parallel-tests, behavioral-tests] | |
| steps: | |
| - name: Check matrix status | |
| if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} | |
| run: exit 1 |