From ae27d72602b2fbe8a0301ae0d46da49844fce95e Mon Sep 17 00:00:00 2001 From: Karl Waldman Date: Sun, 13 Sep 2026 15:39:32 -0400 Subject: [PATCH] chore(release): 3.0.1 Demo-mode path match on a segment boundary (#23); PHPStan level 9 in CI (#24). VersioningTest read the TOPMOST changelog entry for 3.0.0's breaking-change notes, so any later release failed 12 tests unless it re-listed 3.0.0's breaks. It now reads the 3.0.0 entry by version. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015ao5paex73xXvuM424Libo --- CHANGELOG.md | 14 ++++++++++++++ src/Client.php | 2 +- tests/PublicClaimsTest.php | 2 +- tests/VersioningTest.php | 23 ++++++++++++++++++++--- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5e970a..bdf7c14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 3.0.1 - 2026-09-13 + +### Fixed + +- Keyless demo mode now matches the demo endpoint on a path-segment boundary + (#23). It used a raw prefix match, `str_starts_with($path, '/v1/demo')`, so + any path whose characters merely began that way was treated as a demo call + and sent without the `Authorization` header. + +### Internal + +- PHPStan level 9 now runs in CI against `src/`, with the 14 errors it reported + fixed and no baseline (#24). + ## 3.0.0 - 2026-09-13 ### Breaking changes diff --git a/src/Client.php b/src/Client.php index 3fbf2c9..fe5f747 100644 --- a/src/Client.php +++ b/src/Client.php @@ -28,7 +28,7 @@ */ final class Client { - public const VERSION = '3.0.0'; + public const VERSION = '3.0.1'; public const DEFAULT_BASE_URL = 'https://api.oilpriceapi.com'; public const DEFAULT_TIMEOUT = 10.0; public const DEFAULT_MAX_RETRIES = 3; diff --git a/tests/PublicClaimsTest.php b/tests/PublicClaimsTest.php index fe943b7..46f0a22 100644 --- a/tests/PublicClaimsTest.php +++ b/tests/PublicClaimsTest.php @@ -312,7 +312,7 @@ public function testCanonicalDeveloperContractIsDiscoverable(): void ); self::assertSame('oilpriceapi/oilpriceapi', $composer['name']); self::assertSame('>=8.1', $composer['require']['php']); - self::assertSame('3.0.0', Client::VERSION); + self::assertSame('3.0.1', Client::VERSION); self::assertSame('https://api.oilpriceapi.com', Client::DEFAULT_BASE_URL); $readme = (string) file_get_contents($root . '/README.md'); diff --git a/tests/VersioningTest.php b/tests/VersioningTest.php index 463dc18..8b398ec 100644 --- a/tests/VersioningTest.php +++ b/tests/VersioningTest.php @@ -79,7 +79,7 @@ public function testTopmostChangelogEntryMatchesTheShippedVersion(): void */ public function testChangelogDocumentsTheBreakingChange(): void { - $entry = self::firstChangelogEntry(); + $entry = self::breakingMajorEntry(); $this->assertMatchesRegularExpression( '/###\s+Breaking changes/i', @@ -189,9 +189,9 @@ public function testUserAgentCarriesTheSameVersion(): void */ private static function breakingChangesSection(): string { - $entry = self::firstChangelogEntry(); + $entry = self::breakingMajorEntry(); $start = strpos($entry, '### Breaking changes'); - self::assertIsInt($start, 'The topmost entry has no "### Breaking changes" section.'); + self::assertIsInt($start, 'The breaking major entry has no "### Breaking changes" section.'); $rest = substr($entry, $start + strlen('### Breaking changes')); $next = strpos($rest, '###'); @@ -212,6 +212,23 @@ private static function firstChangelogHeading(): string return trim($matches[1]); } + /** + * The entry for the major that introduced the break (3.0.0), wherever it + * sits. Reading the topmost entry instead made every later patch or minor + * release fail these tests unless it re-listed 3.0.0's breaking changes, + * which would tell a reader upgrading from 3.0.0 that something new broke. + */ + private static function breakingMajorEntry(): string + { + $version = (self::LAST_BC_COMPATIBLE_MAJOR + 1) . '.0.0'; + foreach (preg_split('/^## /m', self::changelog()) ?: [] as $entry) { + if (str_starts_with($entry, $version . ' ') || str_starts_with($entry, '[' . $version . ']')) { + return $entry; + } + } + self::fail(sprintf('CHANGELOG.md has no "## %s" entry.', $version)); + } + private static function firstChangelogEntry(): string { $parts = preg_split('/^## /m', self::changelog());