From d92468ca265fd7454c001638516c1eec3e30c389 Mon Sep 17 00:00:00 2001 From: Nora <46890129+rainbowdashlabs@users.noreply.github.com> Date: Thu, 7 May 2026 03:05:20 +0200 Subject: [PATCH 1/4] Update Renovate configuration for PHP version management --- .github/renovate.json | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index efc0ea3f..6d040fed 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -14,7 +14,25 @@ "configMigration": true, "dependencyDashboard": true, "rangeStrategy": "bump", + "customManagers": [ + { + "customType": "regex", + "description": "Keep PHP version in .github/workflows/php-verify.yml in sync with the Dockerfile", + "managerFilePatterns": ["/^\\.github/workflows/php-verify\\.ya?ml$/"], + "matchStrings": [ + "# renovate: datasource=(?.*?) depName=(?.*?)\\s+php-version:\\s*\\['(?[^']+)'\\]" + ], + "versioningTemplate": "docker" + } + ], "packageRules": [ + { + "description": "Group PHP version bumps across Dockerfile and the verify workflow into one update", + "matchPackageNames": ["php"], + "matchDatasources": ["docker"], + "groupName": "php version", + "commitMessageTopic": "PHP" + }, { "description": "Auto-merge non-major PHP (composer) updates without opening a PR", "matchManagers": ["composer"], @@ -57,10 +75,10 @@ "minimumReleaseAge": "14 days" }, { - "description": "Group PHP runtime image updates with PHP language updates in Dockerfile", + "description": "Group PHP runtime image updates across both Dockerfile and debug.Dockerfile", "matchManagers": ["dockerfile"], - "matchPackageNames": ["php", "php-fpm", "php-cli", "php-apache"], - "groupName": "php docker images" + "matchPackageNames": ["php"], + "groupName": "php version" }, { "description": "Do not pin Docker image digests - keep tags as major.minor only", From 2fb22cca5796d36187107f20a71c11732dfc2492 Mon Sep 17 00:00:00 2001 From: Nora <46890129+rainbowdashlabs@users.noreply.github.com> Date: Thu, 7 May 2026 03:08:48 +0200 Subject: [PATCH 2/4] Refactor GitHub Actions workflow for verification --- .github/workflows/verify.yml | 128 +++++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 6 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index c1185ace..b65a3c27 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -1,13 +1,129 @@ name: Verify -on: [push, pull_request] +on: + push: + branches: [main] + pull_request: + # Renovate creates branches like "renovate/*" - run on those too so + # branch-mode auto-merge gates on this workflow's success + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: - build-docker: + verify: + name: Verify PHP ${{ matrix.php-version }} runs-on: ubuntu-latest - name: Docker build + strategy: + matrix: + # PHP version is kept in sync with the Dockerfile by Renovate. + # See the customManagers rule in renovate.json - do not edit this + # line by hand, Renovate will bump it together with the Dockerfile. + # renovate: datasource=docker depName=php + php-version: ['8.4'] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + # Match the extensions installed in the Dockerfile + extensions: mbstring, pdo, pdo_mysql, mysqli, gd + coverage: none + tools: composer:v2 + + - name: Validate composer.json and composer.lock + run: composer validate --strict --no-check-publish + + - name: Get Composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT" + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-php${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php${{ matrix.php-version }}-composer- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress --no-interaction + + - name: Lint all PHP files (syntax check) + run: | + find php public -type f -name "*.php" -print0 \ + | xargs -0 -n1 -P4 php -l > /tmp/lint.log 2>&1 \ + || (cat /tmp/lint.log && exit 1) + + - name: Static analysis (PHPStan) + # No phpstan in composer.json yet - install ad-hoc to catch breaking + # changes from dependency updates. Level 0 catches removed/renamed + # symbols without complaining about pre-existing untyped code. + run: | + composer require --dev --no-progress --no-interaction phpstan/phpstan + vendor/bin/phpstan analyse \ + --no-progress \ + --error-format=github \ + --level=0 \ + php public + + - name: Run tests (PHPUnit) + # Currently no tests in this repo - this step is a no-op until added. + run: | + if [ -f vendor/bin/phpunit ]; then + vendor/bin/phpunit --no-coverage + else + echo "::notice::No PHPUnit configured - skipping tests." + fi + + docker-build: + name: Verify Docker image builds + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Build as Docker image - run: docker build . + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build production image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: false + load: true + tags: devmarkt:ci + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Build debug image + uses: docker/build-push-action@v6 + with: + context: . + file: ./debug.Dockerfile + push: false + load: true + tags: devmarkt:ci-debug + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Smoke-test container starts and PHP works + run: | + # Boot the container, confirm PHP can parse the app's entry points + # without throwing. Catches breaking changes that only show up + # under the actual base image's PHP version. + docker run --rm --entrypoint php devmarkt:ci -v + docker run --rm --entrypoint php devmarkt:ci -m + docker run --rm --entrypoint sh devmarkt:ci -c \ + 'find /var/www -name "*.php" -not -path "*/vendor/*" -print0 | xargs -0 -n1 php -l > /dev/null' From ec70493e29a86c94297af19d8ec4f4c7d00faeb3 Mon Sep 17 00:00:00 2001 From: Nora <46890129+rainbowdashlabs@users.noreply.github.com> Date: Thu, 7 May 2026 03:11:24 +0200 Subject: [PATCH 3/4] Update PHP Verify workflow and dependencies versions --- .github/workflows/verify.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index b65a3c27..b344b34f 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -1,4 +1,4 @@ -name: Verify +name: PHP Verify on: push: @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up PHP uses: shivammathur/setup-php@v2 @@ -42,14 +42,18 @@ jobs: tools: composer:v2 - name: Validate composer.json and composer.lock - run: composer validate --strict --no-check-publish + # --no-check-publish: this is an application, not a library on Packagist + # No --strict: tolerate `"*"` constraints and missing optional fields + # (description, license, etc.) which are fine for an internal project. + # The important checks - valid JSON and lockfile in sync - still run. + run: composer validate --no-check-publish --no-check-all - name: Get Composer cache directory id: composer-cache run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT" - name: Cache Composer dependencies - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-php${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.lock') }} @@ -91,7 +95,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 From 6ad32d2365ad1f444ba2073508020b7f493e6bea Mon Sep 17 00:00:00 2001 From: Nora <46890129+rainbowdashlabs@users.noreply.github.com> Date: Thu, 7 May 2026 03:14:11 +0200 Subject: [PATCH 4/4] Modify PHPStan setup in verify.yml Updated the PHPStan installation command to include jetbrains/phpstorm-attributes and added a composer update step. --- .github/workflows/verify.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index b344b34f..62bdc473 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -73,8 +73,16 @@ jobs: # No phpstan in composer.json yet - install ad-hoc to catch breaking # changes from dependency updates. Level 0 catches removed/renamed # symbols without complaining about pre-existing untyped code. + # + # jetbrains/phpstorm-attributes provides stub classes for PhpStorm's + # IDE hint attributes (#[Pure], #[Immutable], etc.) that the codebase + # uses. PHP ignores unknown attributes at runtime, but PHPStan flags + # them as undefined classes - this package makes them resolvable. run: | - composer require --dev --no-progress --no-interaction phpstan/phpstan + composer require --dev --no-progress --no-interaction --no-update \ + phpstan/phpstan jetbrains/phpstorm-attributes + composer update --no-progress --no-interaction \ + phpstan/phpstan jetbrains/phpstorm-attributes vendor/bin/phpstan analyse \ --no-progress \ --error-format=github \