diff --git a/.github/workflows/monorepo_split_dev.yml b/.github/workflows/monorepo_split_dev.yml index 6f843318..97aae18e 100644 --- a/.github/workflows/monorepo_split_dev.yml +++ b/.github/workflows/monorepo_split_dev.yml @@ -8,10 +8,10 @@ on: jobs: provide_packages_json: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 # required for matrix of packages set - uses: shivammathur/setup-php@v2 @@ -19,7 +19,7 @@ jobs: php-version: 8.2 coverage: none - - uses: "ramsey/composer-install@v1" + - uses: "ramsey/composer-install@v4" - name: Install Monorepo-Builder run: composer require symplify/monorepo-builder:11.0.8 --update-no-dev @@ -35,19 +35,19 @@ jobs: split_monorepo: needs: provide_packages_json - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: package: ${{fromJson(needs.provide_packages_json.outputs.matrix)}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 - # Uses an action in the root directory name: Monorepo Split of ${{ matrix.package }} - uses: symplify/monorepo-split-github-action@v2.3.0 + uses: symplify/monorepo-split-github-action@v2.4.5 env: GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} with: diff --git a/.github/workflows/monorepo_split_tag.yml b/.github/workflows/monorepo_split_tag.yml index a202bbc2..5593b6f0 100644 --- a/.github/workflows/monorepo_split_tag.yml +++ b/.github/workflows/monorepo_split_tag.yml @@ -7,10 +7,10 @@ on: jobs: provide_packages_json_tagged: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 # required for matrix of packages set - uses: shivammathur/setup-php@v2 @@ -18,7 +18,7 @@ jobs: php-version: 8.2 coverage: none - - uses: "ramsey/composer-install@v1" + - uses: "ramsey/composer-install@v4" - name: Install Monorepo-Builder run: composer require symplify/monorepo-builder:11.0.8 --update-no-dev @@ -35,19 +35,19 @@ jobs: split_monorepo_tagged: needs: provide_packages_json_tagged - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: package: ${{fromJson(needs.provide_packages_json_tagged.outputs.matrix)}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 - # Uses an action in the root directory name: Monorepo Split of ${{ matrix.package }} - uses: symplify/monorepo-split-github-action@v2.3.0 + uses: symplify/monorepo-split-github-action@v2.4.5 env: GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} with: diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 92662f04..727f79f4 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -4,48 +4,102 @@ on: push: branches: [ master ] pull_request: - branches: [ master ] + workflow_dispatch: + +# Cancela el run anterior cuando se hace push de nuevo al mismo PR/rama. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: - build: - runs-on: ubuntu-22.04 + # -------------------------------------------------------------------------- + # Tests deterministas (sin red). + # -------------------------------------------------------------------------- + unit: + name: Unit · PHP ${{ matrix.php }} + runs-on: ubuntu-24.04 + timeout-minutes: 15 strategy: + fail-fast: false matrix: - php: ['8.2'] - report-coverage: [false] + php: [ '7.4', '8.2', '8.4' ] include: - php: '7.4' - report-coverage: true + coverage: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: mbstring, curl, soap, dom, xsl, zip, :fileinfo + # pcov solo donde se reporta cobertura; en el resto 'none' (más rápido) + coverage: ${{ matrix.coverage && 'pcov' || 'none' }} + tools: composer:v2, psalm:5 + + - name: Validate composer.json + run: composer validate --strict - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: mbstring, curl, soap, :fileinfo + - name: Install dependencies (con caché) + uses: ramsey/composer-install@v4 + with: + composer-options: --prefer-dist --no-progress - - name: Validate composer.json - run: composer validate + - name: PHPStan + run: composer run-script lint:ci - - name: Install dependencies - run: composer install --prefer-dist --no-progress + - name: Psalm + if: ${{ matrix.coverage }} + run: psalm --shepherd --no-progress - - name: Run PHPStan - run: composer run-script lint:ci + - name: Unit tests + if: ${{ !matrix.coverage }} + run: vendor/bin/phpunit --exclude-group integration,manual - - name: Run PSalm - if: ${{ matrix.report-coverage }} - run: vendor/bin/psalm --shepherd + - name: Unit tests + coverage + if: ${{ matrix.coverage }} + run: vendor/bin/phpunit --exclude-group integration,manual --coverage-clover clover.xml + + - name: Upload coverage + if: ${{ matrix.coverage }} + uses: codecov/codecov-action@v7 + with: + files: ./clover.xml + flags: unittests + name: codecov-greenter + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false + + # -------------------------------------------------------------------------- + # Tests de integración contra SUNAT beta / GRE (nubefact). Dependen de + # servicios externos: se ejecutan aparte. + # -------------------------------------------------------------------------- + integration: + name: Integración SUNAT beta (informativo) + runs-on: ubuntu-24.04 + timeout-minutes: 20 + continue-on-error: true + # En PRs de forks no hay secrets ni sentido de golpear SUNAT; correr solo + # en push a master, PRs internos o manualmente. + if: >- + github.event_name != 'pull_request' || + github.event.pull_request.head.repo.full_name == github.repository + + steps: + - uses: actions/checkout@v7 - - name: Unit Tests - run: vendor/bin/phpunit --exclude-group manual --coverage-clover clover.xml + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: mbstring, curl, soap, dom, xsl, zip, :fileinfo + coverage: none + tools: composer:v2 - - uses: codecov/codecov-action@v1 - if: ${{ matrix.report-coverage }} - with: - file: ./clover.xml - flags: unittests - name: codecov-greenter + - name: Install dependencies (con caché) + uses: ramsey/composer-install@v4 + - name: Integration tests + run: vendor/bin/phpunit --group integration --exclude-group manual diff --git a/CHANGELOG.md b/CHANGELOG.md index de42cb8a..a909f2f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ Los cambios notables de cada lanzamiento serán documentados en este archivo. +## Unreleased +- CI: tests unitarios separados de los de integración (SUNAT beta ya no bloquea PRs); matrix PHP 7.4–8.4; actions actualizadas. +- Corregir parámetros implícitamente nullable (deprecación PHP 8.4). +- Registrar filtros y funciones Twig del reporte con instancias (compatibilidad con Psalm 5.26). + ## 5.0.0 - 2023-05-01 - #206 Agregar xml para nueva Guia de Remisión. - #209 Cambiar versión mínima de PHP a `7.4` diff --git a/composer.json b/composer.json index b25c0b9b..3305c8e4 100644 --- a/composer.json +++ b/composer.json @@ -38,8 +38,7 @@ "greenter/ubl-validator": "^2.0", "mockery/mockery": "^1.2", "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9", - "vimeo/psalm": "~5.10.0" + "phpunit/phpunit": "^9" }, "suggest": { "ext-dom": "For xml, xml-parser, cpe-validator, ws package", diff --git a/packages/report/src/Report/Extension/ReportTwigExtension.php b/packages/report/src/Report/Extension/ReportTwigExtension.php index 7d867742..0b1ac69d 100644 --- a/packages/report/src/Report/Extension/ReportTwigExtension.php +++ b/packages/report/src/Report/Extension/ReportTwigExtension.php @@ -8,6 +8,11 @@ namespace Greenter\Report\Extension; +use Greenter\Report\Filter\DocumentFilter; +use Greenter\Report\Filter\FormatFilter; +use Greenter\Report\Filter\ImageFilter; +use Greenter\Report\Filter\ResolveFilter; +use Greenter\Report\Render\QrRender; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; use Twig\TwigFunction; @@ -20,19 +25,19 @@ class ReportTwigExtension extends AbstractExtension public function getFilters() { return [ - new TwigFilter('catalog', ['Greenter\Report\Filter\DocumentFilter', 'getValueCatalog']), - new TwigFilter('image_b64', ['Greenter\Report\Filter\ImageFilter', 'toBase64']), - new TwigFilter('n_format', ['Greenter\Report\Filter\FormatFilter', 'number']), + new TwigFilter('catalog', [new DocumentFilter(), 'getValueCatalog']), + new TwigFilter('image_b64', [new ImageFilter(), 'toBase64']), + new TwigFilter('n_format', [new FormatFilter(), 'number']), ]; } public function getFunctions() { return [ - new TwigFunction('legend', ['Greenter\Report\Filter\ResolveFilter', 'getValueLegend']), - new TwigFunction('qrCode', ['Greenter\Report\Render\QrRender', 'getImage']), - new TwigFunction('qrCodeDespatch', ['Greenter\Report\Render\QrRender', 'getImageDespatch']), - new TwigFunction('qrUrl', ['Greenter\Report\Render\QrRender', 'getQrUrl']), + new TwigFunction('legend', [new ResolveFilter(), 'getValueLegend']), + new TwigFunction('qrCode', [new QrRender(), 'getImage']), + new TwigFunction('qrCodeDespatch', [new QrRender(), 'getImageDespatch']), + new TwigFunction('qrUrl', [new QrRender(), 'getQrUrl']), ]; } } diff --git a/packages/validator/src/Validator/MessageTranslator.php b/packages/validator/src/Validator/MessageTranslator.php index f4987084..5381fba5 100644 --- a/packages/validator/src/Validator/MessageTranslator.php +++ b/packages/validator/src/Validator/MessageTranslator.php @@ -59,7 +59,7 @@ public function addResource(array $items) * * @throws \InvalidArgumentException If the locale contains invalid characters */ - public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string + public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string { return $this->getValue($id); } diff --git a/packages/ws/src/Zip/DecompressInterface.php b/packages/ws/src/Zip/DecompressInterface.php index ccd03aa5..d9257808 100644 --- a/packages/ws/src/Zip/DecompressInterface.php +++ b/packages/ws/src/Zip/DecompressInterface.php @@ -23,5 +23,5 @@ interface DecompressInterface * * @return array */ - public function decompress(?string $content, callable $filter = null): ?array; + public function decompress(?string $content, ?callable $filter = null): ?array; } diff --git a/packages/ws/src/Zip/ZipDecompressDecorator.php b/packages/ws/src/Zip/ZipDecompressDecorator.php index a44682ad..a7764109 100644 --- a/packages/ws/src/Zip/ZipDecompressDecorator.php +++ b/packages/ws/src/Zip/ZipDecompressDecorator.php @@ -25,7 +25,7 @@ public function __construct(DecompressInterface $decompressor) /** * @inheritDoc */ - public function decompress(?string $content, callable $filter = null): ?array + public function decompress(?string $content, ?callable $filter = null): ?array { if (empty($content)) { return []; diff --git a/packages/ws/src/Zip/ZipFly.php b/packages/ws/src/Zip/ZipFly.php index ee5a6b0d..724770f1 100644 --- a/packages/ws/src/Zip/ZipFly.php +++ b/packages/ws/src/Zip/ZipFly.php @@ -42,7 +42,7 @@ public function compress(?string $filename, ?string $content): ?string * * @return array */ - public function decompress(?string $content, callable $filter = null): ?array + public function decompress(?string $content, ?callable $filter = null): ?array { $zipFile = new ZipFile(); $zipFile->openFromString($content); diff --git a/packages/ws/tests/Ws/Services/ConsultCdrServiceTest.php b/packages/ws/tests/Ws/Services/ConsultCdrServiceTest.php index 809bd8a4..ab8a4aee 100644 --- a/packages/ws/tests/Ws/Services/ConsultCdrServiceTest.php +++ b/packages/ws/tests/Ws/Services/ConsultCdrServiceTest.php @@ -16,6 +16,9 @@ class ConsultCdrServiceTest extends TestCase { use ConsultCdrServiceTrait; + /** + * @group integration + */ public function testGetStatusInvalidUser() { $service = $this->getConsultService(); @@ -27,6 +30,9 @@ public function testGetStatusInvalidUser() $this->assertEquals('00103', $result->getError()->getCode()); } + /** + * @group integration + */ public function testGetStatusCdrInvalidUser() { $service = $this->getConsultService(); diff --git a/packages/ws/tests/Ws/Services/FeSunatTest.php b/packages/ws/tests/Ws/Services/FeSunatTest.php index b3060443..44aac37c 100644 --- a/packages/ws/tests/Ws/Services/FeSunatTest.php +++ b/packages/ws/tests/Ws/Services/FeSunatTest.php @@ -115,6 +115,9 @@ public function testSendVoided() $this->assertEquals(13, strlen($result->getTicket())); } + /** + * @group integration + */ public function testSendVoidedSummarySender() { $nameXml = '20600995805-RA-20170719-01'; diff --git a/packages/xml-parser/src/Xml/Parser/InvoiceParser.php b/packages/xml-parser/src/Xml/Parser/InvoiceParser.php index 6b0a83ef..b2d58308 100644 --- a/packages/xml-parser/src/Xml/Parser/InvoiceParser.php +++ b/packages/xml-parser/src/Xml/Parser/InvoiceParser.php @@ -108,7 +108,7 @@ private function defNodeAttribute(DOMNodeList $nodeList, string $attribute, stri return $node->getAttribute($attribute); } - private function loadTotals(Invoice $inv, DOMXPath $xpt, DOMNode $node = null) + private function loadTotals(Invoice $inv, DOMXPath $xpt, ?DOMNode $node = null) { if (empty($node)) { return; @@ -186,7 +186,7 @@ private function getPrepayments(DOMXPath $xpt) } } - private function getLegends(DOMXPath $xpt, DOMNode $node = null) + private function getLegends(DOMXPath $xpt, ?DOMNode $node = null) { if (empty($node)) { return; diff --git a/packages/xml-parser/src/Xml/Parser/NoteParser.php b/packages/xml-parser/src/Xml/Parser/NoteParser.php index d53d3e21..869c28d4 100644 --- a/packages/xml-parser/src/Xml/Parser/NoteParser.php +++ b/packages/xml-parser/src/Xml/Parser/NoteParser.php @@ -80,7 +80,7 @@ public function parse($value): ?DocumentInterface return $note; } - private function loadTotals(Note $inv, DOMNode $node = null) + private function loadTotals(Note $inv, ?DOMNode $node = null) { if (empty($node)) { return; @@ -139,7 +139,7 @@ private function loadTributos(Note $inv) } } - private function getLegends(DOMNode $node = null) + private function getLegends(?DOMNode $node = null) { if (empty($node)) { return; diff --git a/packages/xml-parser/src/Xml/XmlReader.php b/packages/xml-parser/src/Xml/XmlReader.php index 1b7586cb..0b503532 100644 --- a/packages/xml-parser/src/Xml/XmlReader.php +++ b/packages/xml-parser/src/Xml/XmlReader.php @@ -59,7 +59,7 @@ public function getXpath() * @param string|null $def Default Value * @return string */ - public function getValue($query, DOMNode $context = null, ?string $def = ''): ?string + public function getValue($query, ?DOMNode $context = null, ?string $def = ''): ?string { $nodes = $this->xpath->query($query, $context); if ($nodes->length == 0) { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4b9bcedd..eda09c7c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,7 +10,8 @@ - api + integration + manual