From 3df6cfb9df409d2c5144f1d50fdf7bbd61792ab9 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 11:52:00 +0200 Subject: [PATCH 01/10] Update CI workflow to latest generation --- .github/workflows/ci.yml | 194 +++++++++++++++++++++++++++++---------- 1 file changed, 145 insertions(+), 49 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a95593..8c162cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,84 +1,180 @@ name: Continuous Integration on: push: + branches: + - 'main' + - 'master' + - 'refs/heads/v[0-9]+.[0-9]+.[0-9]+' pull_request: jobs: - generate-checks-strategy: - name: Generate Checks + package-name: + name: Package Name runs-on: ubuntu-latest + needs: + - lint-json + outputs: + package-name: ${{ steps.package-name.outputs.package-name }} + steps: + - uses: actions/checkout@v3 + - id: package-name + run: | + printf "::set-output name=package-name::[\"%s\"]" $(docker run --rm -v "`pwd`:`pwd`" jess/jq jq -r -c '.name' "${GITHUB_WORKSPACE}/composer.json") + supported-versions-matrix: + name: Supported Versions Matrix + runs-on: ubuntu-latest + needs: + - lint-yaml + - lint-json + outputs: + version: ${{ steps.supported-versions-matrix.outputs.version }} + upcoming: ${{ steps.supported-versions-matrix.outputs.upcoming }} + steps: + - uses: actions/checkout@v3 + - id: supported-versions-matrix + uses: WyriHaximus/github-action-composer-php-versions-in-range@v1 + with: + upcomingReleases: true + supported-checks-matrix: + name: Supported Checks Matrix + runs-on: ubuntu-latest + needs: + - lint-yaml outputs: - check: ${{ steps.generate-checks-strategy.outputs.check }} + check: ${{ steps.supported-checks-matrix.outputs.check }} steps: - - uses: actions/checkout@v1 - - id: generate-checks-strategy + - uses: actions/checkout@v3 + - id: supported-checks-matrix name: Generate check run: | printf "Checks found: %s\r\n" $(make task-list-ci) printf "::set-output name=check::%s" $(make task-list-ci) - lint: - runs-on: ubuntu-latest - steps: - - name: Lint Code Base - uses: docker://github/super-linter:v2.2.0 - composer-install: + can-require: + name: Test we can require "${{ matrix.package-name }}" on PHP ${{ matrix.php }} strategy: fail-fast: false matrix: - php: ["8.0", 8.1] - composer: [lowest, current, highest] - needs: lint + php: ${{ fromJson(needs.supported-versions-matrix.outputs.version) }} + package-name: ${{ fromJson(needs.package-name.outputs.package-name) }} + needs: + - lint-yaml + - lint-json + - package-name + - supported-versions-matrix runs-on: ubuntu-latest container: - image: ghcr.io/wyrihaximusnet/php:${{ matrix.php }}-nts-alpine-dev-root + image: ghcr.io/wyrihaximusnet/php:${{ matrix.php }}-nts-buster-dev-root steps: - - uses: actions/checkout@v1 - - name: Cache composer packages - uses: actions/cache@v1 + - uses: actions/checkout@v2 with: - path: ./vendor/ - key: ${{ matrix.composer }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} - - name: Install Dependencies - run: composer update --prefer-lowest --no-progress --ansi --no-interaction --prefer-dist -o - if: matrix.composer == 'lowest' - - name: Install Dependencies - run: composer install --ansi --no-progress --no-interaction --prefer-dist -o - if: matrix.composer == 'current' - - name: Install Dependencies - run: composer update --ansi --no-progress --no-interaction --prefer-dist -o - if: matrix.composer == 'highest' + path: checked_out_package + - name: Set Up composer.json + run: | + echo "{\"repositories\": [{\"name\": \"${{ matrix.package-name }}\",\"type\": \"path\",\"url\": \"./checked_out_package\"}]}" > composer.json + - name: Require package + if: needs.supported-versions-matrix.outputs.upcoming != matrix.php + run: | + composer require "${{ matrix.package-name }}:dev-${GITHUB_SHA}" --no-progress --ansi --no-interaction --prefer-dist -o || composer require "${{ matrix.package-name }}:dev-${GITHUB_REF_NAME}" --no-progress --ansi --no-interaction --prefer-dist -o qa: + name: Run ${{ matrix.check }} on PHP ${{ matrix.php }} with ${{ matrix.composer }} dependency preference strategy: fail-fast: false matrix: - php: ["8.0", 8.1] - composer: [lowest, current, highest] - check: ${{ fromJson(needs.generate-checks-strategy.outputs.check) }} + php: ${{ fromJson(needs.supported-versions-matrix.outputs.version) }} + composer: [lowest, locked, highest] + check: ${{ fromJson(needs.supported-checks-matrix.outputs.check) }} needs: - - composer-install - - generate-checks-strategy + - lint-yaml + - lint-json + - supported-checks-matrix + - supported-versions-matrix runs-on: ubuntu-latest container: - image: ghcr.io/wyrihaximusnet/php:${{ matrix.php }}-nts-alpine-dev-root + image: ghcr.io/wyrihaximusnet/php:${{ matrix.php }}-nts-buster-dev-root steps: - - uses: actions/checkout@v1 - - name: Cache composer packages - uses: actions/cache@v1 + - uses: actions/checkout@v3 + - uses: ramsey/composer-install@v2 with: - path: ./vendor/ - key: ${{ matrix.composer }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} - - name: Install Dependencies - run: (test -f vendor && true ) || composer update --prefer-lowest --no-progress --ansi --no-interaction --prefer-dist -o - if: matrix.composer == 'lowest' - - name: Install Dependencies - run: (test -f vendor && true ) || composer install --ansi --no-progress --no-interaction --prefer-dist -o - if: matrix.composer == 'current' - - name: Install Dependencies - run: (test -f vendor && true ) || composer update --ansi --no-progress --no-interaction --prefer-dist -o - if: matrix.composer == 'highest' + dependency-versions: ${{ matrix.composer }} - name: Fetch Tags run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true if: matrix.check == 'backward-compatibility-check' + - run: make ${{ matrix.check }} || true + if: needs.supported-versions-matrix.outputs.upcoming == matrix.php + env: + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + COVERALLS_RUN_LOCALLY: ${{ secrets.COVERALLS_RUN_LOCALLY }} - run: make ${{ matrix.check }} + if: needs.supported-versions-matrix.outputs.upcoming != matrix.php env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} COVERALLS_RUN_LOCALLY: ${{ secrets.COVERALLS_RUN_LOCALLY }} + tests-directly-on-os: + name: Run tests on PHP ${{ matrix.php }} with ${{ matrix.composer }} dependency preference (${{ matrix.os }}) + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + php: ${{ fromJson(needs.supported-versions-matrix.outputs.version) }} + composer: [lowest, locked, highest] + needs: + - lint-yaml + - lint-json + - supported-checks-matrix + - supported-versions-matrix + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: pcov + extensions: intl, sodium + - uses: ramsey/composer-install@v2 + with: + dependency-versions: ${{ matrix.composer }} + - run: make unit-testing-raw || true + if: needs.supported-versions-matrix.outputs.upcoming == matrix.php + env: + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + COVERALLS_RUN_LOCALLY: ${{ secrets.COVERALLS_RUN_LOCALLY }} + - run: make unit-testing-raw + if: needs.supported-versions-matrix.outputs.upcoming != matrix.php + env: + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + COVERALLS_RUN_LOCALLY: ${{ secrets.COVERALLS_RUN_LOCALLY }} + lint-yaml: + name: Lint YAML + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: yaml-lint + uses: ibiqlik/action-yamllint@v3 + with: + config_data: | + extends: default + ignore: | + /.git/ + rules: + line-length: disable + document-start: disable + truthy: disable + lint-json: + name: Lint JSON + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: json-syntax-check + uses: limitusus/json-syntax-check@v1 + with: + pattern: "\\.json$" + check-mark: + name: ✔️ + needs: + - lint-yaml + - lint-json + - can-require + - qa + - tests-directly-on-os + runs-on: ubuntu-latest + steps: + - run: echo "✔️" From 4902e0d4681d73540510751c063279eed6bd7236 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 13:55:40 +0200 Subject: [PATCH 02/10] Fix YAML files --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 9c4f1ea..6396afc 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: WyriHaximus \ No newline at end of file +github: WyriHaximus From 1be55376fd75fc9c70e40bb5a471567c6b0349b0 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 14:02:53 +0200 Subject: [PATCH 03/10] Update Makefile to latest generation --- Makefile | 53 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index b6d2d8a..580e9a1 100644 --- a/Makefile +++ b/Makefile @@ -3,26 +3,32 @@ SHELL=bash .PHONY: * -DOCKER_CGROUP:=$(shell cat /proc/1/cgroup | grep docker | wc -l) -COMPOSER_CACHE_DIR:=$(shell composer config --global cache-dir -q || echo ${HOME}/.composer/cache) - -ifneq ("$(wildcard /.dockerenv)","") - IN_DOCKER:=TRUE -else ifneq ("$(DOCKER_CGROUP)","0") - IN_DOCKER:=TRUE +COMPOSER_SHOW_EXTENSION_LIST=$(shell composer show -t | grep -o "\-\-\(ext-\).\+" | sort | uniq | cut -d- -f4- | tr -d '\n' | grep . | sed '/^$$/d' | xargs | sed -e 's/ /, /g' | tr -cd '[:alnum:],' | sed 's/.$$//') +SLIM_DOCKER_IMAGE=$(shell php -r 'echo count(array_intersect(["gd", "vips"], explode(",", "${COMPOSER_SHOW_EXTENSION_LIST}"))) > 0 ? "" : "-slim";') +COMPOSER_CACHE_DIR=$(shell composer config --global cache-dir -q || echo ${HOME}/.composer-php/cache) +PHP_VERSION:=$(shell docker run --rm -v "`pwd`:`pwd`" jess/jq jq -r -c '.config.platform.php' "`pwd`/composer.json" | php -r "echo str_replace('|', '.', explode('.', implode('|', explode('.', stream_get_contents(STDIN), 2)), 2)[0]);") +COMPOSER_CONTAINER_CACHE_DIR=$(shell docker run --rm -it "ghcr.io/wyrihaximusnet/php:${PHP_VERSION}-nts-alpine${SLIM_DOCKER_IMAGE}-dev" composer config --global cache-dir -q || echo ${HOME}/.composer-php/cache) + +ifneq ("$(wildcard /.you-are-in-a-wyrihaximus.net-php-docker-image)","") + IN_DOCKER=TRUE else - IN_DOCKER:=FALSE + IN_DOCKER=FALSE endif ifeq ("$(IN_DOCKER)","TRUE") DOCKER_RUN:= else - PHP_VERSION:=$(shell docker run --rm -v "`pwd`:`pwd`" jess/jq jq -r -c '.config.platform.php' "`pwd`/composer.json" | php -r "echo str_replace('|', '.', explode('.', implode('|', explode('.', stream_get_contents(STDIN), 2)), 2)[0]);") DOCKER_RUN:=docker run --rm -it \ -v "`pwd`:`pwd`" \ - -v "${COMPOSER_CACHE_DIR}:/home/app/.composer/cache" \ + -v "${COMPOSER_CACHE_DIR}:${COMPOSER_CONTAINER_CACHE_DIR}" \ -w "`pwd`" \ - "ghcr.io/wyrihaximusnet/php:${PHP_VERSION}-nts-alpine-dev" + "ghcr.io/wyrihaximusnet/php:${PHP_VERSION}-nts-alpine${SLIM_DOCKER_IMAGE}-dev" +endif + +ifneq (,$(findstring icrosoft,$(shell cat /proc/version))) + THREADS=1 +else + THREADS=$(shell nproc) endif all: ## Runs everything ### @@ -32,32 +38,45 @@ syntax-php: ## Lint PHP syntax $(DOCKER_RUN) vendor/bin/parallel-lint --exclude vendor . cs-fix: ## Fix any automatically fixable code style issues - $(DOCKER_RUN) vendor/bin/phpcbf --parallel=$(shell nproc) --cache=./var/.phpcs.cache.json --standard=./etc/qa/phpcs.xml || $(DOCKER_RUN) vendor/bin/phpcbf --parallel=$(shell nproc) --cache=./var/.phpcs.cache.json --standard=./etc/qa/phpcs.xml + $(DOCKER_RUN) vendor/bin/phpcbf --parallel=$(THREADS) --cache=./var/.phpcs.cache.json --standard=./etc/qa/phpcs.xml || $(DOCKER_RUN) vendor/bin/phpcbf --parallel=$(THREADS) --cache=./var/.phpcs.cache.json --standard=./etc/qa/phpcs.xml || $(DOCKER_RUN) vendor/bin/phpcbf --parallel=$(THREADS) --cache=./var/.phpcs.cache.json --standard=./etc/qa/phpcs.xml -vvvv cs: ## Check the code for code style issues - $(DOCKER_RUN) vendor/bin/phpcs --parallel=$(shell nproc) --cache=./var/.phpcs.cache.json --standard=./etc/qa/phpcs.xml + $(DOCKER_RUN) vendor/bin/phpcs --parallel=$(THREADS) --cache=./var/.phpcs.cache.json --standard=./etc/qa/phpcs.xml stan: ## Run static analysis (PHPStan) $(DOCKER_RUN) vendor/bin/phpstan analyse src tests --level max --ansi -c ./etc/qa/phpstan.neon psalm: ## Run static analysis (Psalm) - $(DOCKER_RUN) vendor/bin/psalm --threads=$(shell nproc) --shepherd --stats --config=./psalm.xml + $(DOCKER_RUN) vendor/bin/psalm --threads=$(THREADS) --shepherd --stats --config=./etc/qa/psalm.xml unit-testing: ## Run tests $(DOCKER_RUN) vendor/bin/phpunit --colors=always -c ./etc/qa/phpunit.xml --coverage-text --coverage-html ./var/tests-unit-coverage-html --coverage-clover ./var/tests-unit-clover-coverage.xml $(DOCKER_RUN) test -n "$(COVERALLS_REPO_TOKEN)" && test -n "$(COVERALLS_RUN_LOCALLY)" && test -f ./var/tests-unit-clover-coverage.xml && vendor/bin/php-coveralls -v --coverage_clover ./build/logs/clover.xml --json_path ./var/tests-unit-clover-coverage-upload.json || true +unit-testing-raw: ## Run tests ### + php vendor/phpunit/phpunit/phpunit --colors=always -c ./etc/qa/phpunit.xml --coverage-text --coverage-html ./var/tests-unit-coverage-html --coverage-clover ./var/tests-unit-clover-coverage.xml + test -n "$(COVERALLS_REPO_TOKEN)" && test -n "$(COVERALLS_RUN_LOCALLY)" && test -f ./var/tests-unit-clover-coverage.xml && ./vendor/bin/php-coveralls -v --coverage_clover ./build/logs/clover.xml --json_path ./var/tests-unit-clover-coverage-upload.json || true + mutation-testing: ## Run mutation testing - $(DOCKER_RUN) vendor/bin/roave-infection-static-analysis-plugin --ansi --min-msi=100 --min-covered-msi=100 --threads=$(shell nproc) --ignore-msi-with-no-mutations + $(DOCKER_RUN) vendor/bin/roave-infection-static-analysis-plugin --ansi --log-verbosity=all --threads=$(THREADS) --psalm-config etc/qa/psalm.xml || (cat ./var/infection.log && false) + +mutation-testing-raw: ## Run mutation testing ### + php vendor/roave/infection-static-analysis-plugin/bin/roave-infection-static-analysis-plugin --ansi --log-verbosity=all --threads=$(THREADS) --psalm-config etc/qa/psalm.xml || (cat ./var/infection.log && false) composer-require-checker: ## Ensure we require every package used in this package directly $(DOCKER_RUN) vendor/bin/composer-require-checker --ignore-parse-errors --ansi -vvv --config-file=./etc/qa/composer-require-checker.json composer-unused: ## Ensure we don't require any package we don't use in this package directly - $(DOCKER_RUN) composer unused --ansi + $(DOCKER_RUN) vendor/bin/composer-unused --ansi + +composer-install: ## Install dependencies + $(DOCKER_RUN) composer install --no-progress --ansi --no-interaction --prefer-dist -o backward-compatibility-check: ## Check code for backwards incompatible changes - $(DOCKER_RUN) vendor/bin/roave-backward-compatibility-check || true + $(MAKE) backward-compatibility-check-raw || true + +backward-compatibility-check-raw: ## Check code for backwards incompatible changes, doesn't ignore the failure ### + $(DOCKER_RUN) vendor/bin/roave-backward-compatibility-check shell: ## Provides Shell access in the expected environment ### $(DOCKER_RUN) ash From 44f8629b3641d1369ae85cf50c8099b25be00eb8 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 15:11:03 +0200 Subject: [PATCH 04/10] Raise minimum PHP version to 8.1 --- composer.json | 8 +++++--- composer.lock | 30 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/composer.json b/composer.json index 2793478..911906b 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ } ], "require": { - "php": "^8", + "php": "^8.1", "ext-json": "*", "api-clients/rx": "^2.2", "evenement/evenement": "^3.0", @@ -39,10 +39,12 @@ "infection/extension-installer": true, "dealerdirect/phpcodesniffer-composer-installer": true, "icanhazstring/composer-unused": true, - "ergebnis/composer-normalize": true + "ergebnis/composer-normalize": true, + "ocramius/package-versions": true, + "localheinz/composer-normalize": true }, "platform": { - "php": "8.0.12" + "php": "8.1.12" }, "sort-packages": true }, diff --git a/composer.lock b/composer.lock index c54cd7e..7d3767e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ddcb6721afcc14c1bda9121bb5f4a08c", + "content-hash": "a01f08bb98ac6983b54eda829bfe2ac1", "packages": [ { "name": "api-clients/rx", @@ -31,13 +31,13 @@ }, "type": "library", "autoload": { - "psr-4": { - "ApiClients\\Tools\\Rx\\": "src/" - }, "files": [ "src/functions_include.php", "src/bootstrap.php" - ] + ], + "psr-4": { + "ApiClients\\Tools\\Rx\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5888,12 +5888,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "React\\Promise\\Stream\\": "src/" - }, "files": [ "src/functions_include.php" - ] + ], + "psr-4": { + "React\\Promise\\Stream\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -9752,12 +9752,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "WyriHaximus\\React\\": "src/" - }, "files": [ "src/functions_include.php" - ] + ], + "psr-4": { + "WyriHaximus\\React\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -9790,12 +9790,12 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^8", + "php": "^8.1", "ext-json": "*" }, "platform-dev": [], "platform-overrides": { - "php": "8.0.12" + "php": "8.1.12" }, "plugin-api-version": "2.3.0" } From 09bdc5ebaeb322c1ff495a8b63db95359a48860d Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 17:47:30 +0200 Subject: [PATCH 05/10] Move api-clients/rx to dev dependencies --- composer.json | 2 +- composer.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 911906b..cc4aa2c 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,6 @@ "require": { "php": "^8.1", "ext-json": "*", - "api-clients/rx": "^2.2", "evenement/evenement": "^3.0", "react/promise": "^2.7", "react/stream": "^1.1.0", @@ -19,6 +18,7 @@ "thecodingmachine/safe": "^1.3" }, "require-dev": { + "api-clients/rx": "^2.2", "react/promise-stream": "^1.2", "wyrihaximus/async-test-utilities": "^4.2 || ^5.0", "wyrihaximus/ticking-promise": "^3" diff --git a/composer.lock b/composer.lock index 7d3767e..4b77647 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a01f08bb98ac6983b54eda829bfe2ac1", + "content-hash": "e1c5866ec893164b55172a0360124901", "packages": [ { "name": "api-clients/rx", From 1a638137885e6d3aaadf4612aa6222c63936be82 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 17:54:48 +0200 Subject: [PATCH 06/10] Add missing PSalm configuration --- etc/qa/psalm.xml | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 etc/qa/psalm.xml diff --git a/etc/qa/psalm.xml b/etc/qa/psalm.xml new file mode 100644 index 0000000..82fe126 --- /dev/null +++ b/etc/qa/psalm.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f410a0d623a46a7e80eaf69ecd32b4a0d75957cc Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 17:55:08 +0200 Subject: [PATCH 07/10] Add link checker configuration --- etc/ci/markdown-link-checker.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 etc/ci/markdown-link-checker.json diff --git a/etc/ci/markdown-link-checker.json b/etc/ci/markdown-link-checker.json new file mode 100644 index 0000000..15fb56f --- /dev/null +++ b/etc/ci/markdown-link-checker.json @@ -0,0 +1,10 @@ +{ + "httpHeaders": [ + { + "urls": ["https://docs.github.com/"], + "headers": { + "Accept-Encoding": "zstd, br, gzip, deflate" + } + } + ] +} From b55a19f40b1885d3cdd25d43a36a2469df10c385 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 17:55:28 +0200 Subject: [PATCH 08/10] Update gitignore with phpunit result cache ignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 35df634..03ad991 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -etc/qa/.phpunit.result.cache var/* !var/.gitkeep vendor/ +etc/qa/.phpunit.result.cache From 156aa5a0afb8a1c404e25f66099afc5426285f3d Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 17:55:37 +0200 Subject: [PATCH 09/10] Update QA configuration files --- etc/qa/composer-require-checker.json | 2 +- etc/qa/phpcs.xml | 4 ++-- etc/qa/phpstan.neon | 5 +++-- etc/qa/phpunit.xml | 3 +++ 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/etc/qa/composer-require-checker.json b/etc/qa/composer-require-checker.json index 2b86534..ed67ee5 100644 --- a/etc/qa/composer-require-checker.json +++ b/etc/qa/composer-require-checker.json @@ -3,7 +3,7 @@ "null", "true", "false", "static", "self", "parent", "array", "string", "int", "float", "bool", "iterable", "callable", "void", "object", "mixed", - "WyriHaximus\\Constants\\Boolean\\TRUE_", "WyriHaximus\\Constants\\Boolean\\FALSE_" + "Safe\\json_encode" ], "php-core-extensions" : [ "Core", diff --git a/etc/qa/phpcs.xml b/etc/qa/phpcs.xml index 3fe7079..f6c11d9 100644 --- a/etc/qa/phpcs.xml +++ b/etc/qa/phpcs.xml @@ -6,8 +6,8 @@ - ../../src/ - ../../tests/ + ../../src + ../../tests diff --git a/etc/qa/phpstan.neon b/etc/qa/phpstan.neon index aac1dd2..aac816e 100644 --- a/etc/qa/phpstan.neon +++ b/etc/qa/phpstan.neon @@ -1,8 +1,9 @@ parameters: + checkGenericClassInNonGenericObjectType: false ergebnis: classesAllowedToBeExtended: - - Evenement\EventEmitter - - WyriHaximus\React\Stream\Json\AbstractBufferingStream + - WyriHaximus\React\PSR3\Loggly\AbstractLogglyLogger + - Psr\Log\AbstractLogger includes: - ../../vendor/wyrihaximus/async-test-utilities/rules.neon diff --git a/etc/qa/phpunit.xml b/etc/qa/phpunit.xml index 426c660..5207296 100644 --- a/etc/qa/phpunit.xml +++ b/etc/qa/phpunit.xml @@ -10,4 +10,7 @@ ../../src/ + + + From 866d4e591209f46d17fe7119f699f4b692645df7 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 8 Aug 2022 19:52:20 +0200 Subject: [PATCH 10/10] Fix psalm and phpstan issues --- etc/qa/phpstan.neon | 4 +-- psalm.xml | 53 --------------------------------- src/AbstractBufferingStream.php | 6 ++-- src/JsonStream.php | 52 ++++++++++++++++---------------- tests/JsonStreamTest.php | 30 +++++++++---------- 5 files changed, 46 insertions(+), 99 deletions(-) delete mode 100644 psalm.xml diff --git a/etc/qa/phpstan.neon b/etc/qa/phpstan.neon index aac816e..6e86a24 100644 --- a/etc/qa/phpstan.neon +++ b/etc/qa/phpstan.neon @@ -2,8 +2,8 @@ parameters: checkGenericClassInNonGenericObjectType: false ergebnis: classesAllowedToBeExtended: - - WyriHaximus\React\PSR3\Loggly\AbstractLogglyLogger - - Psr\Log\AbstractLogger + - WyriHaximus\React\Stream\Json\AbstractBufferingStream + - Evenement\EventEmitter includes: - ../../vendor/wyrihaximus/async-test-utilities/rules.neon diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index 9e4f5c3..0000000 --- a/psalm.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/AbstractBufferingStream.php b/src/AbstractBufferingStream.php index ed0d2f8..3c938b5 100644 --- a/src/AbstractBufferingStream.php +++ b/src/AbstractBufferingStream.php @@ -9,10 +9,8 @@ abstract class AbstractBufferingStream implements BufferingStreamInterface { private ReadableStreamInterface $stream; - private string $buffer = ''; - - private bool $isDone = false; + private bool $isDone = false; final protected function setUp(ReadableStreamInterface $stream): void { @@ -24,7 +22,7 @@ final protected function setUp(ReadableStreamInterface $stream): void /** * @internal */ - final public function onData(mixed $data): void + final public function onData(string $data): void { $this->buffer .= $data; } diff --git a/src/JsonStream.php b/src/JsonStream.php index 6c65e76..53334fd 100644 --- a/src/JsonStream.php +++ b/src/JsonStream.php @@ -15,6 +15,7 @@ use Rx\ObservableInterface; use SplQueue; +use function array_keys; use function is_array; use function is_string; use function React\Promise\resolve; @@ -37,27 +38,16 @@ final class JsonStream extends EventEmitter implements ReadableStreamInterface /** @var SplQueue */ private SplQueue $queue; - - private ?int $currentId = null; - - private bool $closing = false; - - private bool $first = true; - + private ?int $currentId = null; + private bool $closing = false; + private bool $first = true; private bool $typeDetected = false; - - private int $i = 0; - - private string $beginning = self::OBJECT_BEGINNING; - - private string $ending = self::OBJECT_ENDING; - - private bool $readable = true; - - private bool $paused = false; - - private string $buffer = ''; - + private int $i = 0; + private string $beginning = self::OBJECT_BEGINNING; + private string $ending = self::OBJECT_ENDING; + private bool $readable = true; + private bool $paused = false; + private string $buffer = ''; private int $encodeFlags; /** @@ -66,7 +56,10 @@ final class JsonStream extends EventEmitter implements ReadableStreamInterface public function __construct(int $encodeFlags = self::DEFAULT_ENCODE_FLAGS) { $this->encodeFlags = $encodeFlags; - $this->queue = new SplQueue(); + /** + * @psalm-suppress MixedPropertyTypeCoercion + */ + $this->queue = new SplQueue(); } public static function createArray(): JsonStream @@ -95,6 +88,9 @@ public function write(string $key, mixed $value): void $id = $this->i++; + /** + * @psalm-suppress MixedAssignment + */ $value = $this->wrapValue($value); $this->queue->enqueue([ @@ -114,6 +110,9 @@ public function writeValue(mixed $value): void $id = $this->i++; + /** + * @psalm-suppress MixedAssignment + */ $value = $this->wrapValue($value); $this->queue->enqueue([ @@ -129,7 +128,7 @@ public function writeValue(mixed $value): void * This method can't be changed to accepting variadic because it needs to detect if it needs to be written out * as an array or object in JSON * - * @param array $values + * @param array $values */ public function writeArray(array $values): void { @@ -139,6 +138,9 @@ public function writeArray(array $values): void $this->objectOrArray($values); + /** + * @psalm-suppress MixedAssignment + */ foreach ($values as $key => $value) { if (is_string($key)) { $this->write($key, $value); @@ -246,7 +248,7 @@ private function objectOrArray(array $values): void return; } - foreach ($values as $key => $value) { + foreach (array_keys($values) as $key) { if (is_string($key)) { return; } @@ -359,7 +361,7 @@ private function handleObservable(Observable $value): PromiseInterface $this->emitData('['); $first = true; - return new Promise(function (callable $resolve, callable $reject) use ($value, &$first): void { + return new Promise(function (callable $resolve) use ($value, &$first): void { /** * @psalm-suppress MissingClosureParamType */ @@ -395,7 +397,7 @@ private function handleJsonStream(BufferingStreamInterface $bufferingStream): Pr /** * @psalm-suppress MissingClosureParamType */ - $stream->on('data', function ($data): void { + $stream->on('data', function (string $data): void { $this->emitData($data); }); $deferred = new Deferred(); diff --git a/tests/JsonStreamTest.php b/tests/JsonStreamTest.php index a37c21b..0ddd47d 100644 --- a/tests/JsonStreamTest.php +++ b/tests/JsonStreamTest.php @@ -583,7 +583,7 @@ public function testEncodeFlags(): void self::assertSame('["<\'&\"&\'>"]', $buffer); $json = json_decode($buffer, true); /** @phpstan-ignore-line */ self::assertSame(JSON_ERROR_NONE, json_last_error()); - self::assertSame(['<\'&"&\'>'], $json); + self::assertSame(['<\'&"&\'>'], $json); /** @phpstan-ignore-line */ } public function testObjectOrArrayObject(): void @@ -692,7 +692,7 @@ public function testDoubleKeys(): void self::assertSame('{"a":true,"a":false}', $buffer); $json = json_decode($buffer, true); /** @phpstan-ignore-line */ self::assertSame(JSON_ERROR_NONE, json_last_error()); - self::assertSame(['a' => false], $json); + self::assertSame(['a' => false], $json); /** @phpstan-ignore-line */ } public function testNoMoreWriteAfterEnd(): void @@ -710,7 +710,7 @@ public function testNoMoreWriteAfterEnd(): void self::assertSame('{"a":true}', $buffer); $json = json_decode($buffer, true); /** @phpstan-ignore-line */ self::assertSame(JSON_ERROR_NONE, json_last_error()); - self::assertSame(['a' => true], $json); + self::assertSame(['a' => true], $json); /** @phpstan-ignore-line */ } public function testNoMoreWriteValueAfterEnd(): void @@ -728,7 +728,7 @@ public function testNoMoreWriteValueAfterEnd(): void self::assertSame('{"a":true}', $buffer); $json = json_decode($buffer, true); /** @phpstan-ignore-line */ self::assertSame(JSON_ERROR_NONE, json_last_error()); - self::assertSame(['a' => true], $json); + self::assertSame(['a' => true], $json); /** @phpstan-ignore-line */ } public function testNoMoreWriteArrayAfterEnd(): void @@ -746,7 +746,7 @@ public function testNoMoreWriteArrayAfterEnd(): void self::assertSame('{"a":true}', $buffer); $json = json_decode($buffer, true); /** @phpstan-ignore-line */ self::assertSame(JSON_ERROR_NONE, json_last_error()); - self::assertSame(['a' => true], $json); + self::assertSame(['a' => true], $json); /** @phpstan-ignore-line */ } public function testNoMoreEndAfterEnd(): void @@ -764,7 +764,7 @@ public function testNoMoreEndAfterEnd(): void self::assertSame('{"a":true}', $buffer); $json = json_decode($buffer, true); /** @phpstan-ignore-line */ self::assertSame(JSON_ERROR_NONE, json_last_error()); - self::assertSame(['a' => true], $json); + self::assertSame(['a' => true], $json); /** @phpstan-ignore-line */ } public function testPauseResume(): void @@ -788,28 +788,28 @@ public function testPauseResume(): void $stream->write('key', 'value'); - self::assertSame(0, $shouldntBeCalledCount); - self::assertSame(0, $shouldBeCalledCount); + self::assertSame(0, $shouldntBeCalledCount); /** @phpstan-ignore-line */ + self::assertSame(0, $shouldBeCalledCount); /** @phpstan-ignore-line */ $stream->removeListener('data', $shouldntBeCalled); $stream->on('data', $shouldBeCalled); - self::assertSame(0, $shouldntBeCalledCount); - self::assertSame(0, $shouldBeCalledCount); + self::assertSame(0, $shouldntBeCalledCount); /** @phpstan-ignore-line */ + self::assertSame(0, $shouldBeCalledCount); /** @phpstan-ignore-line */ $stream->resume(); - self::assertSame(0, $shouldntBeCalledCount); + self::assertSame(0, $shouldntBeCalledCount); /** @phpstan-ignore-line */ self::assertSame(1, $shouldBeCalledCount); /** @phpstan-ignore-line */ $stream->write('key', 'value'); - self::assertSame(0, $shouldntBeCalledCount); - self::assertSame(4, $shouldBeCalledCount); /** @phpstan-ignore-line */ + self::assertSame(0, $shouldntBeCalledCount); /** @phpstan-ignore-line */ + self::assertSame(4, $shouldBeCalledCount); $stream->end(); - self::assertSame(0, $shouldntBeCalledCount); - self::assertSame(5, $shouldBeCalledCount); /** @phpstan-ignore-line */ + self::assertSame(0, $shouldntBeCalledCount); /** @phpstan-ignore-line */ + self::assertSame(5, $shouldBeCalledCount); } }