name: Tests on: pull_request: push: jobs: unit: name: Unit (required) # Match the labels exposed by the Coolify-managed GitHub runner. runs-on: [self-hosted, Linux, X64, default] steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 22 - name: Check AI workflow sync run: node scripts/sync-ai-workflow.mjs --check - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.2' extensions: mysqli, curl, openssl, json, redis, xdebug coverage: xdebug ini-values: variables_order=EGPCS,xdebug.mode=coverage - name: Resolve dependencies working-directory: services/nginx/app run: composer update --no-interaction --prefer-dist - name: Run unit tests working-directory: services/nginx/app run: composer test:unit - name: Generate coverage report working-directory: services/nginx/app run: composer test:coverage - name: Upload coverage artifact if: ${{ github.event_name == 'pull_request' }} continue-on-error: true uses: actions/upload-artifact@v4 with: name: unit-coverage-clover path: services/nginx/app/build/logs/clover.xml if-no-files-found: warn retention-days: 1 edge-agent: name: Edge Agent (required) runs-on: [self-hosted, Linux, X64, default] steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 22 cache: npm cache-dependency-path: services/edge-agent/package-lock.json - name: Install dependencies working-directory: services/edge-agent run: npm ci - name: Run edge agent tests working-directory: services/edge-agent run: npm test edge-broker: name: Edge Broker (required) runs-on: [self-hosted, Linux, X64, default] steps: - name: Checkout uses: actions/checkout@v4 - name: Materialize compose env files env: COMPOSE_ENV: ${{ secrets.COMPOSE_ENV }} COMPOSE_ENV_STAGING: ${{ secrets.COMPOSE_ENV_STAGING }} run: | set -euo pipefail if [ -z "${COMPOSE_ENV}" ]; then echo "Required GitHub secret COMPOSE_ENV is not configured." >&2 exit 1 fi if [ -z "${COMPOSE_ENV_STAGING}" ]; then echo "Required GitHub secret COMPOSE_ENV_STAGING is not configured." >&2 exit 1 fi printf '%s\n' "$COMPOSE_ENV" > .env printf '%s\n' "$COMPOSE_ENV_STAGING" > .env.staging - name: Validate compose contracts run: | docker compose -f docker-compose.yml -f docker-compose.prod.yml config > /dev/null docker compose -f docker-compose.example.yml config > /dev/null - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 22 cache: npm cache-dependency-path: services/edge-broker/package-lock.json - name: Install dependencies working-directory: services/edge-broker run: npm ci - name: Run edge broker tests working-directory: services/edge-broker run: npm test edge-gateway-backend: name: Edge Gateway Backend (required) runs-on: [self-hosted, Linux, X64, default] steps: - name: Checkout uses: actions/checkout@v4 - name: Materialize compose env files env: COMPOSE_ENV: ${{ secrets.COMPOSE_ENV }} COMPOSE_ENV_STAGING: ${{ secrets.COMPOSE_ENV_STAGING }} run: | set -euo pipefail if [ -z "${COMPOSE_ENV}" ]; then echo "Required GitHub secret COMPOSE_ENV is not configured." >&2 exit 1 fi if [ -z "${COMPOSE_ENV_STAGING}" ]; then echo "Required GitHub secret COMPOSE_ENV_STAGING is not configured." >&2 exit 1 fi printf '%s\n' "$COMPOSE_ENV" > .env printf '%s\n' "$COMPOSE_ENV_STAGING" > .env.staging - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 22 - name: Boot local stack run: docker compose up -d traefik redis mysql-debug edge-broker php1 caddy - name: Run edge gateway API tests run: docker compose exec -T php1 sh -lc "cd /var/www/html && composer test:api:edge" - name: Run edge gateway integration tests run: docker compose exec -T php1 sh -lc "cd /var/www/html && composer test:integration:edge" - name: Run edge gateway E2E smoke run: node scripts/edge-gateway-e2e.mjs - name: Tear down local stack if: always() run: docker compose down -v integration: name: Integration (advisory) runs-on: [self-hosted, Linux, X64, default] continue-on-error: true services: redis: image: redis:7 ports: - 6379:6379 mysql: image: mysql:8 env: MYSQL_DATABASE: app_test MYSQL_ROOT_PASSWORD: root ports: - 3306:3306 options: >- --health-cmd="mysqladmin ping -h 127.0.0.1 -proot" --health-interval=10s --health-timeout=5s --health-retries=10 steps: - name: Checkout uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.2' extensions: mysqli, curl, openssl, json, redis ini-values: variables_order=EGPCS - name: Resolve dependencies working-directory: services/nginx/app run: composer update --no-interaction --prefer-dist - name: Run integration tests working-directory: services/nginx/app env: RUN_INTEGRATION_TESTS: '1' USE_ENV: 'true' DEBUG: '0' ENCRYPTION_KEY: test-key CORS: '*' CONFIG_TIMEZONE: Europe/Copenhagen ECONOMIC_API_APP_ACCESS_GRANT: test ECONOMIC_API_APP_ACCESS_GRANT2: test ECONOMIC_API_APP_SECRET_TOKEN: test WORDPRESS_STATIC_TOKEN: '' EMAIL_WASH_CERTIFICATE_TOKEN: '' WORDPRESS_API_URL: http://localhost MINIO_ENDPOINT: '' MINIO_ACCESS_KEY: '' MINIO_SECRET_KEY: '' SLACK_DEFAULT_WEBHOOK: '' REDIS_CONFIG_HOST: 127.0.0.1 REDIS_CONFIG_DATABASE: '0' REDIS_CONFIG_PASSWORD: '' REDIS_CONFIG_PORT: '6379' CONFIG_DB_HOST: 127.0.0.1 CONFIG_DB_USER: root CONFIG_DB_PASSWORD: root CONFIG_DB_DATABASE: app_test CONFIG_DB_PORT: '3306' run: composer test:integration api: name: API (advisory) runs-on: [self-hosted, Linux, X64, default] continue-on-error: true services: redis: image: redis:7 ports: - 6379:6379 mysql: image: mysql:8 env: MYSQL_DATABASE: app_test MYSQL_ROOT_PASSWORD: root ports: - 3306:3306 options: >- --health-cmd="mysqladmin ping -h 127.0.0.1 -proot" --health-interval=10s --health-timeout=5s --health-retries=10 steps: - name: Checkout uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.2' extensions: mysqli, curl, openssl, json, redis ini-values: variables_order=EGPCS - name: Resolve dependencies working-directory: services/nginx/app run: composer update --no-interaction --prefer-dist - name: Run API tests working-directory: services/nginx/app env: RUN_API_TESTS: '1' API_TEST_BOOTSTRAP_SCHEMA: '1' USE_ENV: 'true' DEBUG: '0' ENCRYPTION_KEY: test-key CORS: '*' CONFIG_TIMEZONE: Europe/Copenhagen ECONOMIC_API_APP_ACCESS_GRANT: test ECONOMIC_API_APP_ACCESS_GRANT2: test ECONOMIC_API_APP_SECRET_TOKEN: test WORDPRESS_STATIC_TOKEN: '' EMAIL_WASH_CERTIFICATE_TOKEN: '' WORDPRESS_API_URL: http://localhost MINIO_ENDPOINT: '' MINIO_ACCESS_KEY: '' MINIO_SECRET_KEY: '' SLACK_DEFAULT_WEBHOOK: '' REDIS_CONFIG_HOST: 127.0.0.1 REDIS_CONFIG_DATABASE: '0' REDIS_CONFIG_PASSWORD: '' REDIS_CONFIG_PORT: '6379' CONFIG_DB_HOST: 127.0.0.1 CONFIG_DB_USER: root CONFIG_DB_PASSWORD: root CONFIG_DB_DATABASE: app_test CONFIG_DB_PORT: '3306' run: composer test:api