Repository navigation
Restyle Pinakes and complete mobile collections and catalogue fixes #719
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: Deep Regression Gate | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: [main] | |
| schedule: | |
| - cron: '17 2 * * *' | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| regression: | |
| name: Browser regression shard ${{ matrix.shard }}/4 | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 120 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [1, 2, 3, 4] | |
| services: | |
| mysql: | |
| image: mysql:8.0@sha256:7dcddc01f13bab2f15cde676d44d01f61fc9f99fe7785e86196dfc07d358ae2b | |
| env: | |
| MYSQL_ROOT_PASSWORD: root | |
| MYSQL_DATABASE: pinakes_test | |
| ports: | |
| - 3306:3306 | |
| options: >- | |
| --health-cmd="mysqladmin ping -h 127.0.0.1" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=10 | |
| mailpit: | |
| image: axllent/mailpit:v1.21@sha256:81370195cd4a0eab9604d17c2617a7525b0486f9365555253b6c5376c6350f1a | |
| ports: | |
| - 1025:1025 | |
| - 8025:8025 | |
| env: | |
| E2E_BASE_URL: http://localhost:8081 | |
| APP_URL: http://localhost:8081 | |
| E2E_ADMIN_EMAIL: admin@pinakes.test | |
| E2E_ADMIN_PASS: Test1234! | |
| E2E_DB_HOST: 127.0.0.1 | |
| E2E_DB_PORT: 3306 | |
| E2E_DB_USER: root | |
| E2E_DB_PASS: root | |
| E2E_DB_NAME: pinakes_test | |
| E2E_INSTALL_ROOT: ${{ github.workspace }} | |
| MAILPIT_API: http://127.0.0.1:8025/api/v1 | |
| E2E_PHP_UPLOAD_MAX_BYTES: 8388608 | |
| E2E_PHP_POST_MAX_BYTES: 10485760 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - name: Install Apache, PHP module, MySQL client and mail transport | |
| run: | | |
| # This job never installs Google Chrome. Remove its hosted-runner | |
| # apt source before the first refresh so mirror syncs cannot break CI. | |
| sudo rm -f /etc/apt/sources.list.d/google-chrome.list | |
| sudo apt-get update -q | |
| # php-apcu: the app's page cache must run on its production backend | |
| # (APCu shared memory) under Apache/mod_php, not the file fallback. | |
| sudo apt-get install -y apache2 libapache2-mod-php php-apcu default-mysql-client msmtp-mta | |
| sudo a2enmod rewrite headers env | |
| php_module="$(find /etc/apache2/mods-available -maxdepth 1 -name 'php*.load' -printf '%f\n' | sed 's/\.load$//' | sort -V | tail -n1)" | |
| [ -z "${php_module}" ] || sudo a2enmod "${php_module}" | |
| sudo a2dissite 000-default || true | |
| sudo tee /etc/msmtprc >/dev/null <<'EOF' | |
| defaults | |
| account default | |
| host 127.0.0.1 | |
| port 1025 | |
| tls off | |
| from pinakes-ci@localhost | |
| EOF | |
| sudo chmod 644 /etc/msmtprc | |
| while IFS= read -r conf_dir; do | |
| sudo tee "${conf_dir}/99-pinakes-ci.ini" >/dev/null <<'EOF' | |
| sendmail_path = "/usr/bin/msmtp -t" | |
| upload_max_filesize = 8M | |
| post_max_size = 10M | |
| apc.enable=1 | |
| apc.enable_cli=1 | |
| EOF | |
| done < <(find /etc/php -type d -path '*/conf.d' | sort -u) | |
| - name: Setup PHP 8.2 | |
| uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 | |
| with: | |
| php-version: '8.2' | |
| extensions: mysqli, mbstring, json, curl, openssl, zip, gd, intl, xml, apcu | |
| ini-values: apc.enable=1, apc.enable_cli=1 | |
| coverage: none | |
| - name: Setup Node 22 | |
| uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| - name: Install locked dependencies and Chromium | |
| run: | | |
| composer install --no-interaction --prefer-dist --no-dev --optimize-autoloader | |
| npm ci --silent | |
| npx playwright install chromium --with-deps | |
| - name: Route legacy MySQL test clients to the service container | |
| run: echo "${GITHUB_WORKSPACE}/scripts/ci-bin" >> "${GITHUB_PATH}" | |
| - name: Verify test coverage policy | |
| run: npm run test:ci-policy | |
| - name: Configure Apache on port 8081 | |
| env: | |
| WORKSPACE: ${{ github.workspace }} | |
| run: | | |
| sudo tee /etc/apache2/sites-available/pinakes.conf >/dev/null <<EOF | |
| Listen 8081 | |
| <VirtualHost *:8081> | |
| ServerName localhost | |
| DocumentRoot ${WORKSPACE}/public | |
| SetEnv PINAKES_E2E_BYPASS_RATE_LIMIT 1 | |
| SetEnv PINAKES_E2E_SCRAPER_STUB 1 | |
| # E2E only — arms GET /_e2e/flush-cache so specs that write to the | |
| # DB directly can invalidate the page cache; 404s when unset. | |
| SetEnv PINAKES_E2E_CACHE_FLUSH 1 | |
| <Directory "${WORKSPACE}/public"> | |
| Options -Indexes +FollowSymLinks | |
| AllowOverride All | |
| Require all granted | |
| </Directory> | |
| ErrorLog \${APACHE_LOG_DIR}/pinakes-error.log | |
| CustomLog \${APACHE_LOG_DIR}/pinakes-access.log combined | |
| </VirtualHost> | |
| EOF | |
| sudo a2ensite pinakes | |
| sudo apachectl configtest | |
| - name: Grant runtime permissions and start Apache | |
| env: | |
| WORKSPACE: ${{ github.workspace }} | |
| run: | | |
| path="${WORKSPACE}" | |
| while [ "${path}" != "/" ]; do | |
| sudo chmod o+x "${path}" | |
| path="$(dirname "${path}")" | |
| done | |
| sudo chmod 777 "${WORKSPACE}" | |
| sudo chmod -R 777 "${WORKSPACE}/storage" | |
| sudo mkdir -p "${WORKSPACE}/public/uploads" | |
| sudo chmod -R 777 "${WORKSPACE}/public/uploads" | |
| sudo systemctl start apache2 | |
| for _ in $(seq 1 30); do | |
| curl -sf -o /dev/null http://localhost:8081/installer/ && exit 0 | |
| sleep 1 | |
| done | |
| sudo cat /var/log/apache2/pinakes-error.log || true | |
| exit 1 | |
| - name: Bootstrap a complete fresh installation | |
| env: | |
| PLAYWRIGHT_JSON_OUTPUT_FILE: test-results/bootstrap-${{ matrix.shard }}.json | |
| PLAYWRIGHT_HTML_OUTPUT_DIR: playwright-report-bootstrap-${{ matrix.shard }} | |
| run: npx playwright test tests/full-test.spec.js --config=tests/playwright.ci.config.js --workers=1 | |
| - name: Audit bootstrap failures, flakes and suspicious skips | |
| if: always() | |
| env: | |
| RESULT_FILE: test-results/bootstrap-${{ matrix.shard }}.json | |
| run: node scripts/ci-audit-playwright-results.js "$RESULT_FILE" | |
| - name: Seed deterministic cross-suite fixtures | |
| env: | |
| E2E_RUN_SEED: '1' | |
| E2E_OFFLINE_SEED: '1' | |
| PLAYWRIGHT_JSON_OUTPUT_FILE: test-results/setup-${{ matrix.shard }}.json | |
| PLAYWRIGHT_HTML_OUTPUT_DIR: playwright-report-setup-${{ matrix.shard }} | |
| run: | | |
| npx playwright test \ | |
| tests/interop-00-activate-plugins.spec.js \ | |
| tests/archives-seed-50.spec.js \ | |
| tests/seed-catalog.spec.js \ | |
| tests/persistent-seed-crud.spec.js \ | |
| --config=tests/playwright.ci.config.js \ | |
| --workers=1 | |
| # Apache/PHP may recreate runtime subdirectories with its own umask | |
| # while seeding. The later CLI cron tests need the same shared tree. | |
| sudo chmod -R 777 "${GITHUB_WORKSPACE}/storage" | |
| sudo chmod -R 777 "${GITHUB_WORKSPACE}/public/uploads" | |
| # Installer deliberately protects .env from Apache users. CLI-level | |
| # integration harnesses run as the ephemeral GitHub runner and need | |
| # to read the same throwaway CI credentials. | |
| sudo chmod 640 "${GITHUB_WORKSPACE}/.env" | |
| sudo chgrp "$(id -gn)" "${GITHUB_WORKSPACE}/.env" | |
| - name: Audit setup fixtures | |
| if: always() | |
| env: | |
| RESULT_FILE: test-results/setup-${{ matrix.shard }}.json | |
| run: node scripts/ci-audit-playwright-results.js "$RESULT_FILE" | |
| - name: Run every deep-regression spec in shard ${{ matrix.shard }} | |
| id: deep-regression | |
| env: | |
| SHARD: ${{ matrix.shard }} | |
| PLAYWRIGHT_JSON_OUTPUT_FILE: test-results/shard-${{ matrix.shard }}.json | |
| PLAYWRIGHT_HTML_OUTPUT_DIR: playwright-report-shard-${{ matrix.shard }} | |
| run: | | |
| mapfile -t spec_files < <(node scripts/ci-playwright-policy.js shard "$SHARD" 4) | |
| [ "${#spec_files[@]}" -gt 0 ] || { echo "No specs selected for shard"; exit 1; } | |
| printf 'Running %s deep specs in shard %s/4\n' "${#spec_files[@]}" "$SHARD" | |
| npx playwright test "${spec_files[@]}" \ | |
| --config=tests/playwright.ci.config.js \ | |
| --workers=1 | |
| - name: Audit failures, flakes and suspicious skips | |
| if: always() && steps.deep-regression.outcome != 'skipped' | |
| env: | |
| RESULT_FILE: test-results/shard-${{ matrix.shard }}.json | |
| run: node scripts/ci-audit-playwright-results.js "$RESULT_FILE" | |
| - name: Upload browser evidence | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 | |
| if: always() | |
| with: | |
| name: deep-regression-shard-${{ matrix.shard }}-${{ github.run_id }} | |
| path: | | |
| playwright-report-shard-${{ matrix.shard }}/ | |
| playwright-report-bootstrap-${{ matrix.shard }}/ | |
| playwright-report-setup-${{ matrix.shard }}/ | |
| test-results/ | |
| storage/logs/app.log | |
| /var/log/apache2/pinakes-error.log | |
| /var/log/apache2/pinakes-access.log | |
| retention-days: 14 | |
| if-no-files-found: warn | |
| installer-locales: | |
| name: Fresh installer (${{ matrix.locale }}) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| locale: [it_IT, en_US, de_DE, fr_FR, da_DK] | |
| services: | |
| mysql: | |
| image: mysql:8.0@sha256:7dcddc01f13bab2f15cde676d44d01f61fc9f99fe7785e86196dfc07d358ae2b | |
| env: | |
| MYSQL_ROOT_PASSWORD: root | |
| MYSQL_DATABASE: pinakes_locale_test | |
| ports: | |
| - 3306:3306 | |
| options: >- | |
| --health-cmd="mysqladmin ping -h 127.0.0.1" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=10 | |
| env: | |
| E2E_BASE_URL: http://localhost:8081 | |
| E2E_ADMIN_EMAIL: locale-admin@pinakes.test | |
| E2E_ADMIN_PASS: Test1234! | |
| E2E_DB_HOST: 127.0.0.1 | |
| E2E_DB_PORT: 3306 | |
| E2E_DB_USER: root | |
| E2E_DB_PASS: root | |
| E2E_DB_NAME: pinakes_locale_test | |
| E2E_INSTALL_ROOT: ${{ github.workspace }} | |
| E2E_RUN_INSTALLER_SPECS: '1' | |
| E2E_LOCALE: ${{ matrix.locale }} | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| persist-credentials: false | |
| - name: Install Apache and PHP module | |
| run: | | |
| # This job never installs Google Chrome. Remove its hosted-runner | |
| # apt source before the first refresh so mirror syncs cannot break CI. | |
| sudo rm -f /etc/apt/sources.list.d/google-chrome.list | |
| sudo apt-get update -q | |
| sudo apt-get install -y apache2 libapache2-mod-php default-mysql-client | |
| sudo a2enmod rewrite headers env | |
| php_module="$(find /etc/apache2/mods-available -maxdepth 1 -name 'php*.load' -printf '%f\n' | sed 's/\.load$//' | sort -V | tail -n1)" | |
| [ -z "${php_module}" ] || sudo a2enmod "${php_module}" | |
| sudo a2dissite 000-default || true | |
| - name: Setup PHP and Node | |
| uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 | |
| with: | |
| php-version: '8.2' | |
| extensions: mysqli, mbstring, curl, zip, gd, intl, xml | |
| coverage: none | |
| - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| - name: Install locked dependencies and Chromium | |
| run: | | |
| composer install --no-interaction --prefer-dist --no-dev --optimize-autoloader | |
| npm ci --silent | |
| npx playwright install chromium --with-deps | |
| - name: Configure and start isolated application | |
| env: | |
| WORKSPACE: ${{ github.workspace }} | |
| run: | | |
| sudo tee /etc/apache2/sites-available/pinakes.conf >/dev/null <<EOF | |
| Listen 8081 | |
| <VirtualHost *:8081> | |
| ServerName localhost | |
| DocumentRoot ${WORKSPACE}/public | |
| SetEnv PINAKES_E2E_BYPASS_RATE_LIMIT 1 | |
| <Directory "${WORKSPACE}/public"> | |
| Options -Indexes +FollowSymLinks | |
| AllowOverride All | |
| Require all granted | |
| </Directory> | |
| ErrorLog \${APACHE_LOG_DIR}/pinakes-error.log | |
| </VirtualHost> | |
| EOF | |
| sudo a2ensite pinakes | |
| path="${WORKSPACE}" | |
| while [ "${path}" != "/" ]; do sudo chmod o+x "${path}"; path="$(dirname "${path}")"; done | |
| sudo chmod 777 "${WORKSPACE}" | |
| sudo chmod -R 777 "${WORKSPACE}/storage" | |
| sudo mkdir -p "${WORKSPACE}/public/uploads" | |
| sudo chmod -R 777 "${WORKSPACE}/public/uploads" | |
| sudo apachectl configtest | |
| sudo systemctl start apache2 | |
| for _ in $(seq 1 30); do | |
| curl -sf -o /dev/null http://localhost:8081/installer/ && exit 0 | |
| sleep 1 | |
| done | |
| exit 1 | |
| - name: Install and verify locale ${{ matrix.locale }} | |
| env: | |
| PLAYWRIGHT_JSON_OUTPUT_FILE: test-results/installer-${{ matrix.locale }}.json | |
| PLAYWRIGHT_HTML_OUTPUT_DIR: playwright-report-installer-${{ matrix.locale }} | |
| run: | | |
| npx playwright test tests/multilang-install-i18n.spec.js \ | |
| --config=tests/playwright.ci.config.js \ | |
| --workers=1 | |
| - name: Audit installer result | |
| if: always() | |
| env: | |
| RESULT_FILE: test-results/installer-${{ matrix.locale }}.json | |
| run: node scripts/ci-audit-playwright-results.js "$RESULT_FILE" | |
| - name: Upload installer evidence | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 | |
| if: always() | |
| with: | |
| name: installer-${{ matrix.locale }}-${{ github.run_id }} | |
| path: | | |
| playwright-report-installer-${{ matrix.locale }}/ | |
| test-results/ | |
| /var/log/apache2/pinakes-error.log | |
| retention-days: 14 | |
| if-no-files-found: warn |