From 6e970066b787d2b00a43a753240123a95ec362eb Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:55 -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 5233d84970cc652429ac03accccc7ae749bf9939 Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:55 -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 cf07400312c0910d69dfec1bc68cb110141a89f4 Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:55 -0300 Subject: [PATCH 3/5] chore: Align the tooling configuration with the ecosystem assets. --- .gitattributes | 2 -- composer.json | 1 + phpstan.neon.dist | 9 +-------- 3 files changed, 2 insertions(+), 10 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 0223633..e6b7afb 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 0632585..5dd9b4f 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -3,42 +3,35 @@ parameters: paths: - src - tests + tmpDir: reports/phpstan ignoreErrors: # DateTimeImmutable::createFromFormat returns DateTimeImmutable|false; the UNIX format 'U' always succeeds for a valid integer, so the false branch is unreachable. - identifier: method.nonObject path: src/Instant.php - # DateTimeImmutable::createFromFormat returns DateTimeImmutable|false; the recomposed wall-clock string is always well-formed, so the false branch is unreachable. - identifier: method.nonObject path: src/Internal/ZonedShift.php - # Collectible is a @template TValue interface; the promoted constructor property $timezones cannot # carry a Collectible type parameter because PHPDoc on constructors is prohibited. - identifier: missingType.generics path: src/Timezones.php - # Collectible operations surface as mixed at level max, so return.type fires on three members here: # findBy() (mixed narrowed to Timezone by the collection invariant), toStrings() (toArray() yields a # less specific iterable value type), and all() (single-pass spread of a non-generic Collectible # infers list instead of list). - identifier: return.type path: src/Timezones.php - # Collection::createFrom expects iterable; variadic packed arrays and toArray() results carry less specific keys. - identifier: argument.type path: src/Timezones.php - # PHPDoc is prohibited inside tests/ per documentation rule; suppress missing iterable value-type on data providers. - identifier: missingType.iterableValue path: tests - # PHPDoc is prohibited anywhere inside src/Internal/ per architecture rule. TextDecoder's constructor parameter $decoders is intentionally untyped; suppress missing iterable value-type plus cascading errors from iterating the now-mixed array. - identifier: missingType.iterableValue path: src/Internal - - identifier: method.nonObject path: src/Internal/TextDecoder.php - - identifier: return.type path: src/Internal/TextDecoder.php reportUnmatchedIgnoredErrors: true From 7cb37ec97567e4d94b99d5dadf0273700cb21110 Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:55 -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 3a4a7057a9d4a9ada5d648317a79380f09e7a36d Mon Sep 17 00:00:00 2001 From: Gustavo Freze Date: Wed, 19 Aug 2026 20:54:55 -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.