From 1d703bf980e340c27db430c91b58b628bf4103b2 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sat, 1 Nov 2025 14:48:28 +0100 Subject: [PATCH 1/8] fix psalm error --- src/Exception/DomainException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exception/DomainException.php b/src/Exception/DomainException.php index 690bd2b..ae74b8c 100644 --- a/src/Exception/DomainException.php +++ b/src/Exception/DomainException.php @@ -3,6 +3,6 @@ namespace Innmind\IP\Exception; -class DomainException extends \DomainException implements Exception +final class DomainException extends \DomainException implements Exception { } From 1e33c3446d37cda5bebefcd57e25c8a7f5ef538a Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sat, 1 Nov 2025 14:53:44 +0100 Subject: [PATCH 2/8] replace phpunit by blackbox --- .gitattributes | 1 - .github/workflows/ci.yml | 70 ++++------------------------------------ blackbox.php | 27 ++++++++++++++++ composer.json | 8 ++--- phpunit.xml.dist | 17 ---------- tests/IPv4Test.php | 9 +++--- tests/IPv6Test.php | 9 +++--- 7 files changed, 46 insertions(+), 95 deletions(-) create mode 100644 blackbox.php delete mode 100644 phpunit.xml.dist diff --git a/.gitattributes b/.gitattributes index 4160131..05f17e3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ /.gitattributes export-ignore /.gitignore export-ignore -/phpunit.xml.dist export-ignore /tests export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index feba0f6..779f162 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,68 +3,12 @@ name: CI on: [push, pull_request] jobs: - phpunit: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macOS-latest] - php-version: ['8.2', '8.3'] - dependencies: ['lowest', 'highest'] - name: 'PHPUnit' - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: mbstring, intl - coverage: xdebug - - name: Composer - uses: "ramsey/composer-install@v2" - with: - dependency-versions: ${{ matrix.dependencies }} - - name: PHPUnit - run: vendor/bin/phpunit --coverage-clover=coverage.clover - - uses: codecov/codecov-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} + blackbox: + uses: innmind/github-workflows/.github/workflows/black-box-matrix.yml@next + coverage: + uses: innmind/github-workflows/.github/workflows/coverage-matrix.yml@next + secrets: inherit psalm: - runs-on: ubuntu-latest - strategy: - matrix: - php-version: ['8.2', '8.3'] - dependencies: ['lowest', 'highest'] - name: 'Psalm' - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: mbstring, intl - - name: Composer - uses: "ramsey/composer-install@v2" - with: - dependency-versions: ${{ matrix.dependencies }} - - name: Psalm - run: vendor/bin/psalm --shepherd + uses: innmind/github-workflows/.github/workflows/psalm-matrix.yml@next cs: - runs-on: ubuntu-latest - strategy: - matrix: - php-version: ['8.2'] - name: 'CS' - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: mbstring, intl - - name: Composer - uses: "ramsey/composer-install@v2" - - name: CS - run: vendor/bin/php-cs-fixer fix --diff --dry-run + uses: innmind/github-workflows/.github/workflows/cs.yml@next diff --git a/blackbox.php b/blackbox.php new file mode 100644 index 0000000..0eb49cf --- /dev/null +++ b/blackbox.php @@ -0,0 +1,27 @@ +when( + \getenv('ENABLE_COVERAGE') !== false, + static fn(Application $app) => $app + ->scenariiPerProof(1) + ->codeCoverage( + CodeCoverage::of( + __DIR__.'/src/', + __DIR__.'/tests/', + ) + ->dumpTo('coverage.clover') + ->enableWhen(true), + ), + ) + ->tryToProve(Load::directory(__DIR__.'/tests/')) + ->exit(); diff --git a/composer.json b/composer.json index 42c4d1e..91a1135 100644 --- a/composer.json +++ b/composer.json @@ -15,8 +15,8 @@ "issues": "http://github.com/Innmind/IP/issues" }, "require": { - "php": "~8.2", - "innmind/immutable": "~4.1|~5.0" + "php": "~8.4", + "innmind/immutable": "dev-next" }, "autoload": { "psr-4": { @@ -29,8 +29,8 @@ } }, "require-dev": { - "phpunit/phpunit": "~9.0", - "vimeo/psalm": "~5.6", + "innmind/static-analysis": "^1.2.1", + "innmind/black-box": "~6.5", "innmind/coding-standard": "~2.0" } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 1b3432d..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - . - - - ./tests - ./vendor - - - - - ./tests - - - diff --git a/tests/IPv4Test.php b/tests/IPv4Test.php index 159037a..fc42a7f 100644 --- a/tests/IPv4Test.php +++ b/tests/IPv4Test.php @@ -8,13 +8,12 @@ IP, Exception\DomainException, }; -use PHPUnit\Framework\TestCase; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; class IPv4Test extends TestCase { - /** - * @dataProvider addresses - */ + #[DataProvider('addresses')] public function testInterface($address) { $this->assertInstanceOf(IP::class, IPv4::of($address)); @@ -64,7 +63,7 @@ public function testMaybeReturnNothingForInvalidAddress() )); } - public function addresses(): array + public static function addresses(): array { return [ ['0.0.0.0'], diff --git a/tests/IPv6Test.php b/tests/IPv6Test.php index df68417..df0dbb5 100644 --- a/tests/IPv6Test.php +++ b/tests/IPv6Test.php @@ -8,13 +8,12 @@ IP, Exception\DomainException, }; -use PHPUnit\Framework\TestCase; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; class IPv6Test extends TestCase { - /** - * @dataProvider addresses - */ + #[DataProvider('addresses')] public function testInterface($address) { $this->assertInstanceOf(IP::class, IPv6::of($address)); @@ -64,7 +63,7 @@ public function testMaybeReturnNothingForInvalidAddress() )); } - public function addresses(): array + public static function addresses(): array { return [ ['0:0:0:0:0:0:0:1'], From b79bb7a6f30569c4500ff2400ef0cb6497bbcbf5 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sat, 1 Nov 2025 14:56:22 +0100 Subject: [PATCH 3/8] add workflow to create releases --- .github/workflows/release.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b25ad8a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,11 @@ +name: Create release + +on: + push: + tags: + - '*' + +jobs: + release: + uses: innmind/github-workflows/.github/workflows/release.yml@main + secrets: inherit From 5fa8f6464e5d2953c6c568279669e14b6fb12f39 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sat, 1 Nov 2025 14:56:58 +0100 Subject: [PATCH 4/8] update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e63001..62ad10d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased] + +### Changed + +- Require PHP `8.4` + ## 3.2.0 - 2023-09-16 ### Added From 28b2663803200b3be90536e54979d041a5a4f08d Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sat, 1 Nov 2025 14:57:45 +0100 Subject: [PATCH 5/8] add ::attempt() named constructors --- CHANGELOG.md | 5 +++++ src/IPv4.php | 23 +++++++++++++++-------- src/IPv6.php | 23 +++++++++++++++-------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62ad10d..9a8e562 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## [Unreleased] +### Added + +- `Innmind\IP\IPv4::attempt()` +- `Innmind\IP\IPv6::attempt()` + ### Changed - Require PHP `8.4` diff --git a/src/IPv4.php b/src/IPv4.php index 9a3018c..8d6dc44 100644 --- a/src/IPv4.php +++ b/src/IPv4.php @@ -3,8 +3,10 @@ namespace Innmind\IP; -use Innmind\IP\Exception\DomainException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\{ + Maybe, + Attempt, +}; /** * @psalm-immutable @@ -34,11 +36,16 @@ public static function localhost(): self */ public static function maybe(string $address): Maybe { - try { - return Maybe::just(self::of($address)); - } catch (DomainException $e) { - /** @var Maybe */ - return Maybe::nothing(); - } + return self::attempt($address)->maybe(); + } + + /** + * @psalm-pure + * + * @return Attempt + */ + public static function attempt(string $address): Attempt + { + return Attempt::of(static fn() => self::of($address)); } } diff --git a/src/IPv6.php b/src/IPv6.php index df51983..034a826 100644 --- a/src/IPv6.php +++ b/src/IPv6.php @@ -3,8 +3,10 @@ namespace Innmind\IP; -use Innmind\IP\Exception\DomainException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\{ + Maybe, + Attempt, +}; /** * @psalm-immutable @@ -34,11 +36,16 @@ public static function localhost(): self */ public static function maybe(string $address): Maybe { - try { - return Maybe::just(self::of($address)); - } catch (DomainException $e) { - /** @var Maybe */ - return Maybe::nothing(); - } + return self::attempt($address)->maybe(); + } + + /** + * @psalm-pure + * + * @return Attempt + */ + public static function attempt(string $address): Attempt + { + return Attempt::of(static fn() => self::of($address)); } } From aeeca8e2632ebc06672cb1e0f2fea5d865fd96b9 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sat, 1 Nov 2025 15:00:23 +0100 Subject: [PATCH 6/8] use native php exceptions --- CHANGELOG.md | 5 +++++ src/Exception/DomainException.php | 8 -------- src/Exception/Exception.php | 8 -------- src/IP.php | 6 ++---- tests/IPv4Test.php | 5 ++--- tests/IPv6Test.php | 5 ++--- 6 files changed, 11 insertions(+), 26 deletions(-) delete mode 100644 src/Exception/DomainException.php delete mode 100644 src/Exception/Exception.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a8e562..4f5131e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ - Require PHP `8.4` +### Removed + +- `Innmind\IP\Exception\Exception` +- `Innmind\IP\Exception\DomainException` + ## 3.2.0 - 2023-09-16 ### Added diff --git a/src/Exception/DomainException.php b/src/Exception/DomainException.php deleted file mode 100644 index ae74b8c..0000000 --- a/src/Exception/DomainException.php +++ /dev/null @@ -1,8 +0,0 @@ -expectException(DomainException::class); + $this->expectException(\DomainException::class); $this->expectExceptionMessage('localhost'); IPv4::of('localhost'); @@ -49,7 +48,7 @@ public function testThrowWhenInvalidFormat() public function testThrowWhenOutOfBound() { - $this->expectException(DomainException::class); + $this->expectException(\DomainException::class); $this->expectExceptionMessage('256.0.0.1'); IPv4::of('256.0.0.1'); diff --git a/tests/IPv6Test.php b/tests/IPv6Test.php index df0dbb5..abffa06 100644 --- a/tests/IPv6Test.php +++ b/tests/IPv6Test.php @@ -6,7 +6,6 @@ use Innmind\IP\{ IPv6, IP, - Exception\DomainException, }; use Innmind\BlackBox\PHPUnit\Framework\TestCase; use PHPUnit\Framework\Attributes\DataProvider; @@ -41,7 +40,7 @@ public function testLocalhost() public function testThrowWhenInvalidFormat() { - $this->expectException(DomainException::class); + $this->expectException(\DomainException::class); $this->expectExceptionMessage('localhost'); IPv6::of('localhost'); @@ -49,7 +48,7 @@ public function testThrowWhenInvalidFormat() public function testThrowWhenOutOfBound() { - $this->expectException(DomainException::class); + $this->expectException(\DomainException::class); $this->expectExceptionMessage('::z'); IPv6::of('::z'); From 7171f027e6b36d5b9688bfa4207a41424413419c Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 18 Jan 2026 15:20:38 +0100 Subject: [PATCH 7/8] tag dependencies --- .github/workflows/ci.yml | 8 ++++---- composer.json | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 779f162..2f3eecb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,11 +4,11 @@ on: [push, pull_request] jobs: blackbox: - uses: innmind/github-workflows/.github/workflows/black-box-matrix.yml@next + uses: innmind/github-workflows/.github/workflows/black-box-matrix.yml@main coverage: - uses: innmind/github-workflows/.github/workflows/coverage-matrix.yml@next + uses: innmind/github-workflows/.github/workflows/coverage-matrix.yml@main secrets: inherit psalm: - uses: innmind/github-workflows/.github/workflows/psalm-matrix.yml@next + uses: innmind/github-workflows/.github/workflows/psalm-matrix.yml@main cs: - uses: innmind/github-workflows/.github/workflows/cs.yml@next + uses: innmind/github-workflows/.github/workflows/cs.yml@main diff --git a/composer.json b/composer.json index 91a1135..29538ab 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ }, "require": { "php": "~8.4", - "innmind/immutable": "dev-next" + "innmind/immutable": "~6.0" }, "autoload": { "psr-4": { @@ -29,7 +29,7 @@ } }, "require-dev": { - "innmind/static-analysis": "^1.2.1", + "innmind/static-analysis": "~1.3", "innmind/black-box": "~6.5", "innmind/coding-standard": "~2.0" } From 53ee8bd38c6d82d140caf1f9eea7a02f6044d08e Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 18 Jan 2026 15:25:58 +0100 Subject: [PATCH 8/8] fix readme --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 58e89c5..fd611d7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # IP -[![Build Status](https://github.com/innmind/IP/workflows/CI/badge.svg?branch=master)](https://github.com/innmind/IP/actions?query=workflow%3ACI) +[![CI](https://github.com/Innmind/IP/actions/workflows/ci.yml/badge.svg)](https://github.com/Innmind/IP/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/innmind/IP/branch/develop/graph/badge.svg)](https://codecov.io/gh/innmind/IP) [![Type Coverage](https://shepherd.dev/github/innmind/IP/coverage.svg)](https://shepherd.dev/github/innmind/IP) @@ -19,9 +19,11 @@ use Innmind\IP\{ IP, IPv4, IPv6, - Exception\DomainException, }; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\{ + Maybe, + Attempt, +}; $ipv4 = IP::v4('192.168.0.1'); $ipv6 = IP::v6('2001:db8:a0b:12f0::1'); @@ -31,4 +33,6 @@ IPv4::of('localhost'); // throws DomainException IPv6::of('localhost'); // throws DomainException IPv4::maybe('localhost'); // returns Maybe IPv6::maybe('localhost'); // returns Maybe +IPv4::attempt('localhost'); // returns Attempt +IPv6::attempt('localhost'); // returns Attempt ```