From 73f199af2720f7ad56796a45c83bc2942f4f9c0b Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 31 Aug 2026 14:54:06 +0200 Subject: [PATCH 1/5] synchronize CI pipeline --- .github/workflows/main.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cf05073..33e5c87 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: run: "composer validate --strict" php: - name: "PHP ${{ matrix.php-version }} (${{ matrix.dependencies }}) - lint, PHPStan, PHPCS" + name: "PHP ${{ matrix.php-version }} (${{ matrix.dependencies }})" needs: "composer" runs-on: "ubuntu-latest" timeout-minutes: 15 @@ -62,8 +62,6 @@ jobs: - name: "audit dependencies for known security vulnerabilities" if: "matrix.php-version == '8.1'" run: "composer audit" - - name: "check PHP version" - run: "php -v" - name: "lint PHP files" run: "find src -type f -name '*.php' -print0 | xargs -0 -n1 php -l" - name: "run PHPStan" From a256b8bc470fd15810c9df6fa9f012075d110ad5 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 1 Sep 2026 11:35:39 +0200 Subject: [PATCH 2/5] add dependabot.yml --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..f357059 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + + - package-ecosystem: "composer" + directory: "/" + schedule: + interval: "weekly" From 33862f65bc0b3cd0b1c9a027d0ce295a32d729bc Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 1 Sep 2026 11:36:00 +0200 Subject: [PATCH 3/5] synchronize composer dependencies --- composer.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 8984e6f..11b332c 100644 --- a/composer.json +++ b/composer.json @@ -16,12 +16,12 @@ "php": "^8.1", "ext-json": "*", "phpunit/phpunit": "^9.6.33", - "php-sap/interfaces": "^5.1.4", - "php-sap/common": "^6.1.3", - "php-sap/datetime": "^1.5.1" + "php-sap/interfaces": "^5.1.6", + "php-sap/common": "^6.2.0", + "php-sap/datetime": "^1.5.2" }, "require-dev": { - "phpstan/phpstan": "^2.2", + "phpstan/phpstan": "^2.2.3", "squizlabs/php_codesniffer": "^4.0" }, "autoload": { From bc21c32d86deb6f07fc597504212346450a10cf6 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 1 Sep 2026 13:19:31 +0200 Subject: [PATCH 4/5] add Makefile --- .gitattributes | 1 + Makefile | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 Makefile diff --git a/.gitattributes b/.gitattributes index dcf26a4..a89cdd7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,6 +4,7 @@ .gitignore export-ignore AGENTS.md export-ignore composer.* export-ignore +Makefile export-ignore phpcs.xml export-ignore phpstan.neon export-ignore README.md export-ignore diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..da61301 --- /dev/null +++ b/Makefile @@ -0,0 +1,91 @@ +SHELL := /bin/sh +.DEFAULT_GOAL := help + +COMPOSER_IMAGE := composer:2 +COMPOSER_CACHE_DIR := $(HOME)/.cache/composer +DOCKER_USER := --user "$$(id -u)":"$$(id -g)" +DOCKER_MOUNT := --volume "$$(pwd)":/app --workdir /app + +# --prefer-lowest only has an effect on "composer update", not "composer +# install" (which just reproduces composer.lock) - switch commands so the +# flag actually does something, matching the CI "lowest" matrix job. +ifdef DEPENDENCIES_LOWEST +COMPOSER_INSTALL_CMD := update --prefer-lowest +else +COMPOSER_INSTALL_CMD := install +endif + +# Optional: set CA_CERT_FILE to a PEM file (e.g. a corporate proxy root CA) +# to make it trusted for HTTPS network access inside the containers used by +# "install" and "audit" (e.g. 'make install PHP_VERSION=8.1 CA_CERT_FILE=/path/to/ca.pem'). +ifdef CA_CERT_FILE +CA_MOUNT := --volume "$(CA_CERT_FILE)":/tmp/extra-ca.crt:ro +CA_TRUST_CMD := cat /etc/ssl/certs/ca-certificates.crt /tmp/extra-ca.crt > /tmp/ca-bundle.pem && export CURL_CA_BUNDLE=/tmp/ca-bundle.pem SSL_CERT_FILE=/tmp/ca-bundle.pem && +else +CA_MOUNT := +CA_TRUST_CMD := +endif + +.PHONY: help clean check-php-version install lint analyze beautify sniff audit validate + +help: ## Show this help + @grep -E '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) | sort | \ + awk 'BEGIN {FS = ":.*## "}; {printf " \033[36m%-10s\033[0m %s\n", $$1, $$2}' + +clean: ## Remove vendor/ and composer.lock (reset to a fresh checkout) + rm -rf vendor composer.lock + +check-php-version: + @if [ -z "$(PHP_VERSION)" ]; then \ + echo "Error: PHP_VERSION must be set, e.g. 'make $(MAKECMDGOALS) PHP_VERSION=8.1'." >&2; \ + exit 1; \ + fi + +install: check-php-version ## Install composer dependencies for PHP_VERSION (set DEPENDENCIES_LOWEST for --prefer-lowest, CA_CERT_FILE for a corporate proxy CA) + @mkdir -p "$(COMPOSER_CACHE_DIR)" + docker run --rm -t --init $(DOCKER_USER) \ + --env HTTP_PROXY --env HTTPS_PROXY --env NO_PROXY \ + --env COMPOSER_CACHE_DIR=/tmp/composer-cache \ + --volume "$(COMPOSER_CACHE_DIR)":/tmp/composer-cache \ + $(CA_MOUNT) \ + $(DOCKER_MOUNT) \ + $(COMPOSER_IMAGE) sh -c '\ + $(CA_TRUST_CMD) \ + composer config platform.php "$(PHP_VERSION)" && \ + composer $(COMPOSER_INSTALL_CMD) --prefer-dist --no-interaction --no-progress; \ + status=$$?; \ + composer config --unset platform.php; \ + composer config --unset platform 2>/dev/null; \ + composer config --unset config 2>/dev/null; \ + if [ $$status -eq 0 ]; then \ + composer update --lock --no-interaction --no-progress; \ + status=$$?; \ + fi; \ + exit $$status \ + ' + +lint: check-php-version ## Syntax-check every .php file in src/ for PHP_VERSION + docker run --rm --init $(DOCKER_USER) $(DOCKER_MOUNT) \ + "php:$(PHP_VERSION)-cli" sh -c "find src -type f -name '*.php' -print0 | xargs -0 -n1 php -l" + +analyze: check-php-version ## Run PHPStan for PHP_VERSION + docker run --rm -t --init $(DOCKER_USER) $(DOCKER_MOUNT) \ + "php:$(PHP_VERSION)-cli" php vendor/bin/phpstan analyse --memory-limit=-1 + +beautify: check-php-version ## Run PHPCBF (auto-fix code style) for PHP_VERSION + docker run --rm --init $(DOCKER_USER) $(DOCKER_MOUNT) \ + "php:$(PHP_VERSION)-cli" php vendor/bin/phpcbf + +sniff: check-php-version ## Run PHPCS (code style check) for PHP_VERSION + docker run --rm --init $(DOCKER_USER) $(DOCKER_MOUNT) \ + "php:$(PHP_VERSION)-cli" php vendor/bin/phpcs + +audit: ## Run composer audit (checks dependencies for known vulnerabilities; CA_CERT_FILE for a corporate proxy CA) + docker run --rm -t --init $(DOCKER_USER) \ + --env HTTP_PROXY --env HTTPS_PROXY --env NO_PROXY \ + $(CA_MOUNT) $(DOCKER_MOUNT) \ + $(COMPOSER_IMAGE) sh -c '$(CA_TRUST_CMD) composer audit' + +validate: ## Run composer validate --strict + docker run --rm -t $(DOCKER_USER) $(DOCKER_MOUNT) \ + $(COMPOSER_IMAGE) composer validate --strict From 512570463a6330325c0a173d3984c13f91bf2d24 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 1 Sep 2026 13:19:50 +0200 Subject: [PATCH 5/5] update README.md and AGENTS.md to use Makefile --- AGENTS.md | 81 ++++++++++++++++++++++++++++--------------------------- README.md | 10 +++++++ 2 files changed, 51 insertions(+), 40 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ae83cf6..9c80fcf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -49,50 +49,48 @@ about a specific extension's behavior belong in the connector repo consuming it ## Developer Workflows -All commands run inside official PHP Docker images so the host machine does not need a -local PHP installation. Use PHP 8.1, 8.2, and 8.3 (matching the CI matrix in -`.github/workflows/main.yml`) for anything version-sensitive (PHPStan, PHP lint). -If you are behind a proxy, forward `HTTP_PROXY`/`HTTPS_PROXY`/`NO_PROXY` into the -container whenever the command needs network access (e.g. `composer install`). +All commands run through the `Makefile` via Docker, so the host machine does not need a +local PHP installation. Run `make help` for the full target list. Use PHP 8.1, 8.2, and +8.3 (matching the CI matrix in `.github/workflows/main.yml`) for anything +version-sensitive (PHPStan, PHP lint). If you are behind a proxy, `install` and `audit` +already forward `HTTP_PROXY`/`HTTPS_PROXY`/`NO_PROXY`; pass `CA_CERT_FILE=/path/to/ca.pem` +to trust a corporate proxy root CA inside the container. ```bash -# Install/update dependencies (needs network access -> forward proxy settings) -docker run --rm --init --interactive --tty \ - --user "$(id -u)":"$(id -g)" \ - --env HTTP_PROXY --env HTTPS_PROXY --env NO_PROXY \ - --volume "$(pwd)":/app --workdir /app \ - composer:2 install - -# Run commands from the repository root. PHPUnit is installed (vendor/bin/phpunit), but -# running it here without a target only shows usage: this package ships reusable abstract -# tests, not a local suite (no network access needed) -docker run --rm --init \ - --user "$(id -u)":"$(id -g)" \ - --volume "$(pwd)":/app --workdir /app \ - php:8.1-cli php vendor/bin/phpunit - -# Fix code style (run first, uses phpcs.xml, PSR-12 for src/; no network access needed) -docker run --rm --init \ - --user "$(id -u)":"$(id -g)" \ - --volume "$(pwd)":/app --workdir /app \ - php:8.1-cli php vendor/bin/phpcbf - -# Check remaining style issues (no network access needed) -docker run --rm --init \ - --user "$(id -u)":"$(id -g)" \ - --volume "$(pwd)":/app --workdir /app \ - php:8.1-cli php vendor/bin/phpcs - -# Run static analysis for every supported PHP version (no network access needed; -# --memory-limit=-1 works around the image's low default memory_limit) -for PHP_VERSION in 8.1 8.2 8.3; do - docker run --rm --init \ - --user "$(id -u)":"$(id -g)" \ - --volume "$(pwd)":/app --workdir /app \ - "php:${PHP_VERSION}-cli" php vendor/bin/phpstan analyse --no-progress --memory-limit=-1 -done +# Install/update dependencies for a given PHP version (set DEPENDENCIES_LOWEST=1 for +# --prefer-lowest, matching the CI "lowest" matrix job) +make install PHP_VERSION=8.1 + +# Syntax-check every .php file in src/, matches CI +make lint PHP_VERSION=8.1 + +# Run PHPStan +make analyze PHP_VERSION=8.1 + +# Auto-fix code style (run this before "sniff") +make beautify PHP_VERSION=8.1 + +# Check code style (uses phpcs.xml, PSR-12 for src/) +make sniff PHP_VERSION=8.1 + +# Check dependencies for known vulnerabilities +make audit + +# Run composer validate --strict +make validate ``` +There is no `test` Makefile target: PHPUnit is installed (`vendor/bin/phpunit`), but +running it here without a target only shows usage, since this package ships reusable +abstract tests, not a local suite. Consumer repositories run the tests via their own +`make test`. + +**Always use these Makefile targets instead of inventing ad-hoc `docker run`/`composer`/ +`php` commands.** If a task needs something the Makefile doesn't expose directly (e.g. +PHPCS on a single file), take the exact `docker run` invocation from the matching +Makefile target (image, `DOCKER_USER`, `DOCKER_MOUNT`, env forwarding) and only append +the extra arguments — don't build the command from scratch. + PHPStan runs at **level 9** (`phpstan.neon`, scans `src/`). ## Conventions @@ -110,3 +108,6 @@ PHPStan runs at **level 9** (`phpstan.neon`, scans `src/`). - Before changing a mock name or module template expectation, trace all related abstract methods and the `SapRfcModuleMocks::validateId()` path. - Before changing JSON fixtures, inspect the matching assertions in `AbstractSapRfcTestCase.php` so types still align with expected PHP values (`DateTime`, `DateInterval`, arrays, decoded hex values). - Write documentation, comments, and new code in English to match the repository style. +- Always run QA/build commands through the `Makefile` targets, not self-invented `docker run` + commands. For one-off variants (a single file), base the invocation on the relevant + Makefile target and only append the extra arguments. diff --git a/README.md b/README.md index 4295f75..81ad569 100644 --- a/README.md +++ b/README.md @@ -4,5 +4,15 @@ This repository contains tests common to all [PHP/SAP][phpsap] implementations. +## Development + +All development commands (install, lint, analyze, beautify, sniff, audit, validate) +run via Docker through the `Makefile`, so no local PHP installation is needed. Run +`make help` to list all targets. Most targets require `PHP_VERSION`, e.g.: + +```sh +make install PHP_VERSION=8.1 +``` + [phpsap]: https://php-sap.github.io [license-mit]: https://img.shields.io/badge/license-MIT-blue.svg