From 2d63f8bd91025ee0eacc1bda479aeb3fdf143eb2 Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:54 -0300 Subject: [PATCH 1/5] build: Pin the PHP tooling image in the Makefile. --- Makefile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 90ab50d..6915324 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,12 @@ endif TTY := $(shell [ -t 0 ] && echo -it) -DOCKER_RUN = docker run ${PLATFORM} --rm ${TTY} --net=host -v ${PWD}:/app -w /app gustavofreze/php:8.5-alpine +PHP_VERSION := $(shell sed -n 's/.*"php": *"^\([0-9]*\.[0-9]*\)".*/\1/p' composer.json) +IMAGE_VERSION := 1.0.0 +PHP_IMAGE := gustavofreze/php:${PHP_VERSION}-cli-${IMAGE_VERSION} +WORKSPACE := /var/www/html + +DOCKER_RUN = docker run ${PLATFORM} --rm ${TTY} --net=host -v ${PWD}:${WORKSPACE} ${PHP_IMAGE} RESET := \033[0m GREEN := \033[0;32m @@ -44,6 +49,10 @@ show-reports: ## Open coverage and mutation reports in the browser show-outdated: ## Show outdated direct dependencies @${DOCKER_RUN} composer outdated --direct +.PHONY: show-image +show-image: ## Show the pinned PHP tooling image + @echo ${PHP_IMAGE} + .PHONY: clean clean: ## Remove dependencies and generated artifacts @sudo chown -R ${USER}:${USER} ${PWD} @@ -66,7 +75,7 @@ help: ## Display this help message | awk 'BEGIN {FS = ":.*?## "}; {printf "$(YELLOW)%-25s$(RESET) %s\n", $$1, $$2}' @echo "" @echo "$$(printf '$(GREEN)')Reports$$(printf '$(RESET)')" - @grep -E '^(show-reports|show-outdated):.*?## .*$$' $(MAKEFILE_LIST) \ + @grep -E '^(show-reports|show-outdated|show-image):.*?## .*$$' $(MAKEFILE_LIST) \ | awk 'BEGIN {FS = ":.*?## "}; {printf "$(YELLOW)%-25s$(RESET) %s\n", $$1, $$2}' @echo "" @echo "$$(printf '$(GREEN)')Cleanup$$(printf '$(RESET)')" From 8bf3c5ca2c5e4a65262b8f662c706a237f18265a Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:54 -0300 Subject: [PATCH 2/5] ci: Resolve the tooling image from the Makefile. --- .github/workflows/ci.yml | 49 ++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b401ca6..1b5f8ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,42 +11,39 @@ permissions: contents: read jobs: - resolve-php-version: - name: Resolve PHP version + resolve-tooling-image: + name: Resolve tooling image runs-on: ubuntu-latest timeout-minutes: 5 outputs: - php-version: ${{ steps.config.outputs.php-version }} + php-image: ${{ steps.config.outputs.php-image }} steps: - name: Checkout uses: actions/checkout@v7 - - name: Resolve PHP version from composer.json + - name: Resolve tooling image from the Makefile id: config - run: | - version=$(jq -r '.require.php' composer.json | grep -oP '\d+\.\d+' | head -1) - echo "php-version=$version" >> "$GITHUB_OUTPUT" + run: echo "php-image=$(make show-image)" >> "$GITHUB_OUTPUT" build: name: Build - needs: resolve-php-version + needs: resolve-tooling-image runs-on: ubuntu-latest timeout-minutes: 15 + env: + image: ${{ needs.resolve-tooling-image.outputs.php-image }} + workspace: /var/www/html steps: - name: Checkout uses: actions/checkout@v7 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - tools: composer:2 - php-version: ${{ needs.resolve-php-version.outputs.php-version }} - - name: Validate composer.json - run: composer validate --no-interaction + run: docker run --rm -v "${PWD}":${{ env.workspace }} ${{ env.image }} composer validate --no-interaction - name: Install dependencies - run: composer install --no-progress --optimize-autoloader --prefer-dist --no-interaction + run: > + docker run --rm -v "${PWD}":${{ env.workspace }} ${{ env.image }} + composer install --no-progress --optimize-autoloader --prefer-dist --no-interaction - name: Upload vendor and composer.lock as artifact uses: actions/upload-artifact@v7 @@ -58,19 +55,13 @@ jobs: auto-review: name: Auto review - needs: [resolve-php-version, build] + needs: [resolve-tooling-image, build] runs-on: ubuntu-latest timeout-minutes: 15 steps: - name: Checkout uses: actions/checkout@v7 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - tools: composer:2 - php-version: ${{ needs.resolve-php-version.outputs.php-version }} - - name: Download vendor artifact from build uses: actions/download-artifact@v8 with: @@ -78,23 +69,17 @@ jobs: path: . - name: Run review - run: composer review + run: make review tests: name: Tests - needs: [resolve-php-version, auto-review] + needs: [resolve-tooling-image, auto-review] runs-on: ubuntu-latest timeout-minutes: 15 steps: - name: Checkout uses: actions/checkout@v7 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - tools: composer:2 - php-version: ${{ needs.resolve-php-version.outputs.php-version }} - - name: Download vendor artifact from build uses: actions/download-artifact@v8 with: @@ -102,4 +87,4 @@ jobs: path: . - name: Run tests - run: composer tests + run: make tests From 6c31c908210c380b94d250d674a7972c5d179b62 Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:54 -0300 Subject: [PATCH 3/5] chore: Align the tooling configuration with the ecosystem assets. --- .gitattributes | 2 -- composer.json | 1 + phpstan.neon.dist | 10 +--------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/.gitattributes b/.gitattributes index f044953..cc4d0f6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,8 +2,6 @@ *.php text diff=php -# Keep Claude tooling scripts out of GitHub's language statistics - # Dev-only, excluded from the Packagist tarball /.github export-ignore /tests export-ignore diff --git a/composer.json b/composer.json index 5feaae4..b219174 100644 --- a/composer.json +++ b/composer.json @@ -60,6 +60,7 @@ "ergebnis/composer-normalize": true, "infection/extension-installer": true }, + "process-timeout": 0, "sort-packages": true }, "scripts": { diff --git a/phpstan.neon.dist b/phpstan.neon.dist index bc284d3..91d3dd8 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -3,6 +3,7 @@ parameters: paths: - src - tests + tmpDir: reports/phpstan ignoreErrors: # PHPDoc cannot express iterable value types inside src/Internal/ and tests/, nor on the public # constructor parameters Mapper::$mappings and Configuration::$omittedFields (PHPDoc on @@ -15,46 +16,38 @@ parameters: path: src/Mapper.php - identifier: missingType.iterableValue path: src/Configuration.php - # PHPDoc cannot express generic class types inside src/Internal/ and tests/. - identifier: missingType.generics path: src/Internal/ - identifier: missingType.generics path: tests/ - # Reflection-driven mapping reads mixed values from untyped sources inside src/Internal/ and tests/. - identifier: argument.type path: src/Internal/ - identifier: argument.type path: tests/ - # Reflection-driven mapping returns concrete types PHPStan cannot infer from mixed input, both # inside src/Internal/ and on the public facade that forwards engine results (Mapper). - identifier: return.type path: src/Internal/ - identifier: return.type path: src/Mapper.php - # Subtype and Layout mappings forward a class name resolved at runtime (from an untyped source # or the target type string) into the generic reflectionRead, so PHPStan cannot bind the # template type T. The forwarded value is always a valid class-string. - identifier: argument.templateType path: src/Internal/ - # Reflection-driven hydration casts values typed as mixed into the property's declared scalar type. - identifier: cast.string path: src/Internal/ - # Reflection-driven mapping accesses offsets of sources whose runtime shape is mixed. - identifier: offsetAccess.invalidOffset path: src/Internal/ - # Reflection-driven mapping invokes methods on values resolved at runtime from mixed. - identifier: method.nonObject path: src/Internal/ - identifier: instanceof.invalidExprType path: src/Internal/ - # The scalar-codec list on the class descriptor cannot carry its value type (PHPDoc on the # src/Internal/ concrete descriptor is prohibited), so reading the decode and encode method # names off each ScalarCodec is seen as property access on mixed. @@ -62,7 +55,6 @@ parameters: path: src/Internal/Deserialization/Resolvers/ScalarCodecResolver.php - identifier: property.nonObject path: src/Internal/Serialization/Encoders/ScalarCodecEncoder.php - # Late static binding in the Refunds test fixture mirrors tiny-blocks/collection's extension-point shape. - identifier: new.static path: tests/Models/Refunds.php From 3c37f791cbdc7cd1c1a98afb448089abf8d03586 Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:54 -0300 Subject: [PATCH 4/5] docs: Standardize the Copilot instructions. --- .github/copilot-instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index de1576d..e34c801 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -6,7 +6,7 @@ PHP library in the tiny-blocks ecosystem. ## Mandatory pre-task step -Before starting any task, read and strictly follow `CLAUDE.md` and every rule file in +Before starting any task, read and strictly follow `.claude/CLAUDE.md` and every rule file in `.claude/rules/`. These files are the absolute source of truth for code generation. Apply every rule strictly. Do not deviate from the patterns, folder structure, or naming conventions defined in them. From 42190c1644d8f646b7999d04f48a2551b68f3871 Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:54 -0300 Subject: [PATCH 5/5] docs: Run the pull request checklist through the Makefile. --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7a2c836..e9cc769 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -12,5 +12,5 @@ Closes #... - [ ] Tests added or updated. - [ ] Documentation updated when applicable. -- [ ] `composer review` passes. -- [ ] `composer tests` passes. +- [ ] `make review` passes. +- [ ] `make tests` passes.