diff --git a/composer.json b/composer.json index d4f7fe44..9a768dc2 100644 --- a/composer.json +++ b/composer.json @@ -22,12 +22,12 @@ }, "require-dev": { "doctrine/coding-standard": "^11.0.0", - "php-standard-library/psalm-plugin": "^2.1.0", - "phpunit/phpunit": "^9.5.26", - "psalm/plugin-phpunit": "^0.18.0", - "roave/infection-static-analysis-plugin": "^1.25.0", + "php-standard-library/psalm-plugin": "^2.2.1", + "phpunit/phpunit": "^9.5.27", + "psalm/plugin-phpunit": "^0.18.4", + "roave/infection-static-analysis-plugin": "^1.26.0", "squizlabs/php_codesniffer": "^3.7.1", - "vimeo/psalm": "^5.0.0" + "vimeo/psalm": "^5.3.0" }, "config": { "sort-packages": true, diff --git a/composer.lock b/composer.lock index 1a2fec90..05d943a1 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": "e6a9ec7de84d817c03d443b7f960f0ee", + "content-hash": "5f85d0acf1128f0a50f7fe8e38c3a4a4", "packages": [ { "name": "azjezz/psl", @@ -3902,16 +3902,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "0.4.0", + "version": "0.4.1", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "666cb04a02f2801f3b19955fc23c824f9018bf64" + "reference": "79261cc280aded96d098e1b0e0ba0c4881b432c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/666cb04a02f2801f3b19955fc23c824f9018bf64", - "reference": "666cb04a02f2801f3b19955fc23c824f9018bf64", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/79261cc280aded96d098e1b0e0ba0c4881b432c2", + "reference": "79261cc280aded96d098e1b0e0ba0c4881b432c2", "shasum": "" }, "require": { @@ -3951,7 +3951,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/0.4.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/0.4.1" }, "funding": [ { @@ -3959,7 +3959,7 @@ "type": "github" } ], - "time": "2022-12-10T21:26:31+00:00" + "time": "2022-12-16T22:01:02+00:00" }, { "name": "infection/abstract-testframework-adapter", @@ -4578,59 +4578,6 @@ }, "time": "2021-04-14T09:16:52+00:00" }, - { - "name": "openlss/lib-array2xml", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/nullivex/lib-array2xml.git", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "LSS": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Bryan Tong", - "email": "bryan@nullivex.com", - "homepage": "https://www.nullivex.com" - }, - { - "name": "Tony Butler", - "email": "spudz76@gmail.com", - "homepage": "https://www.nullivex.com" - } - ], - "description": "Array2XML conversion library credit to lalit.org", - "homepage": "https://www.nullivex.com", - "keywords": [ - "array", - "array conversion", - "xml", - "xml conversion" - ], - "support": { - "issues": "https://github.com/nullivex/lib-array2xml/issues", - "source": "https://github.com/nullivex/lib-array2xml/tree/master" - }, - "time": "2019-03-29T20:06:56+00:00" - }, { "name": "phar-io/manifest", "version": "2.0.3", @@ -4963,16 +4910,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.15.0", + "version": "1.15.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "6ff970a7101acfe99b3048e4bbfbc094e55c5b04" + "reference": "5941477f100993652218928039d530b75a13a9ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6ff970a7101acfe99b3048e4bbfbc094e55c5b04", - "reference": "6ff970a7101acfe99b3048e4bbfbc094e55c5b04", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/5941477f100993652218928039d530b75a13a9ca", + "reference": "5941477f100993652218928039d530b75a13a9ca", "shasum": "" }, "require": { @@ -5002,22 +4949,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.15.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.15.2" }, - "time": "2022-12-07T16:12:39+00:00" + "time": "2022-12-16T06:42:48+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.19", + "version": "9.2.22", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559" + "reference": "e4bf60d2220b4baaa0572986b5d69870226b06df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c77b56b63e3d2031bd8997fcec43c1925ae46559", - "reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e4bf60d2220b4baaa0572986b5d69870226b06df", + "reference": "e4bf60d2220b4baaa0572986b5d69870226b06df", "shasum": "" }, "require": { @@ -5073,7 +5020,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.19" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.22" }, "funding": [ { @@ -5081,7 +5028,7 @@ "type": "github" } ], - "time": "2022-11-18T07:47:47+00:00" + "time": "2022-12-18T16:40:55+00:00" }, { "name": "phpunit/php-file-iterator", @@ -6626,16 +6573,16 @@ }, { "name": "slevomat/coding-standard", - "version": "8.7.0", + "version": "8.7.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "326d195209d196be02f8c2a0034529262fc7ffcc" + "reference": "c51edb898bebd36aac70a190c6a41a7c056bb5b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/326d195209d196be02f8c2a0034529262fc7ffcc", - "reference": "326d195209d196be02f8c2a0034529262fc7ffcc", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/c51edb898bebd36aac70a190c6a41a7c056bb5b9", + "reference": "c51edb898bebd36aac70a190c6a41a7c056bb5b9", "shasum": "" }, "require": { @@ -6675,7 +6622,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.7.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.7.1" }, "funding": [ { @@ -6687,7 +6634,71 @@ "type": "tidelift" } ], - "time": "2022-12-13T15:02:08+00:00" + "time": "2022-12-14T08:49:18+00:00" + }, + { + "name": "spatie/array-to-xml", + "version": "2.17.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/array-to-xml.git", + "reference": "df0f116f26f6d3f84041e94d46811ee6b64fe7d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/df0f116f26f6d3f84041e94d46811ee6b64fe7d5", + "reference": "df0f116f26f6d3f84041e94d46811ee6b64fe7d5", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "^7.4|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "pestphp/pest": "^1.21", + "phpunit/phpunit": "^9.0", + "spatie/pest-plugin-snapshots": "^1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\ArrayToXml\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://freek.dev", + "role": "Developer" + } + ], + "description": "Convert an array to xml", + "homepage": "https://github.com/spatie/array-to-xml", + "keywords": [ + "array", + "convert", + "xml" + ], + "support": { + "source": "https://github.com/spatie/array-to-xml/tree/2.17.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2022-12-13T09:08:39+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -7124,16 +7135,16 @@ }, { "name": "vimeo/psalm", - "version": "5.2.0", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "fb685a16df3050d4c18d8a4100fe83abe6458cba" + "reference": "b6faa3e96b8eb50ec71384c53799b8a107236bb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/fb685a16df3050d4c18d8a4100fe83abe6458cba", - "reference": "fb685a16df3050d4c18d8a4100fe83abe6458cba", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/b6faa3e96b8eb50ec71384c53799b8a107236bb6", + "reference": "b6faa3e96b8eb50ec71384c53799b8a107236bb6", "shasum": "" }, "require": { @@ -7155,9 +7166,9 @@ "fidry/cpu-core-counter": "^0.4.0", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", "nikic/php-parser": "^4.13", - "openlss/lib-array2xml": "^1.0", "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0", "sebastian/diff": "^4.0", + "spatie/array-to-xml": "^2.17.0", "symfony/console": "^4.1.6 || ^5.0 || ^6.0", "symfony/filesystem": "^5.4 || ^6.0", "symfony/polyfill-php80": "^1.25" @@ -7223,9 +7234,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.2.0" + "source": "https://github.com/vimeo/psalm/tree/5.3.0" }, - "time": "2022-12-12T08:18:56+00:00" + "time": "2022-12-18T18:15:37+00:00" }, { "name": "webmozart/assert", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index eceb7e20..50aa9cc1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,20 +1,24 @@ - - + + ./test/unit - + - src + src diff --git a/src/Git/Value/MergeTargetCandidateBranches.php b/src/Git/Value/MergeTargetCandidateBranches.php index cec01cd0..bc976a29 100644 --- a/src/Git/Value/MergeTargetCandidateBranches.php +++ b/src/Git/Value/MergeTargetCandidateBranches.php @@ -9,6 +9,9 @@ use Psl\Vec; use function array_search; +use function Psl\Iter\first; +use function Psl\Vec\filter; +use function Psl\Vec\reverse; final class MergeTargetCandidateBranches { @@ -22,7 +25,7 @@ private function __construct(private readonly array $sortedBranches) public static function fromAllBranches(BranchName ...$branches): self { - $mergeTargetBranches = Vec\filter($branches, static function (BranchName $branch): bool { + $mergeTargetBranches = filter($branches, static function (BranchName $branch): bool { return $branch->isReleaseBranch(); }); @@ -70,23 +73,24 @@ public function branchToMergeUp(SemVerVersion $version): BranchName|null public function newestReleaseBranch(): BranchName|null { - return Iter\first(Vec\reverse($this->sortedBranches)); + return first(reverse($this->sortedBranches)); } public function newestFutureReleaseBranchAfter(SemVerVersion $version): BranchName { $nextMinor = $version->nextMinor(); - $futureReleaseBranch = Vec\filter( - Vec\reverse($this->sortedBranches), + /** @var ?BranchName $futureReleaseBranch */ + $futureReleaseBranch = first(filter( + reverse($this->sortedBranches), static function (BranchName $branch) use ($nextMinor): bool { $targetVersion = $branch->targetMinorReleaseVersion(); return ! $targetVersion->isNewMajorRelease() && $nextMinor->lessThanEqual($targetVersion); }, - ); + )); - return Iter\first($futureReleaseBranch) ?? $nextMinor->targetReleaseBranchName(); + return $futureReleaseBranch ?? $nextMinor->targetReleaseBranchName(); } public function contains(BranchName $needle): bool diff --git a/src/Github/Api/V3/CreateReleaseThroughApiCall.php b/src/Github/Api/V3/CreateReleaseThroughApiCall.php index a1e2421e..a15eec28 100644 --- a/src/Github/Api/V3/CreateReleaseThroughApiCall.php +++ b/src/Github/Api/V3/CreateReleaseThroughApiCall.php @@ -7,16 +7,20 @@ use Laminas\AutomaticReleases\Git\Value\SemVerVersion; use Laminas\AutomaticReleases\Github\Value\RepositoryName; use Laminas\Diactoros\Uri; -use Psl; -use Psl\Json; -use Psl\Type; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\UriInterface; +use function Psl\invariant_violation; +use function Psl\Json\encode; +use function Psl\Json\typed; +use function Psl\Type\non_empty_string; +use function Psl\Type\shape; +use function sprintf; + final class CreateReleaseThroughApiCall implements CreateRelease { - private const API_ROOT = 'https://api.github.com/'; + private const API_URI = 'https://api.github.com/repos/%s/%s/releases'; /** @psalm-param non-empty-string $apiToken */ public function __construct( @@ -34,32 +38,40 @@ public function __invoke( $request = $this->messageFactory ->createRequest( 'POST', - self::API_ROOT . 'repos/' . $repository->owner() . '/' . $repository->name() . '/releases', + sprintf(self::API_URI, $repository->owner(), $repository->name()), ) ->withAddedHeader('Content-Type', 'application/json') ->withAddedHeader('User-Agent', 'Ocramius\'s minimal API V3 client') ->withAddedHeader('Authorization', 'token ' . $this->apiToken); - $request - ->getBody() - ->write(Json\encode([ - 'tag_name' => $version->fullReleaseName(), - 'name' => $version->fullReleaseName(), - 'body' => $releaseNotes, - ])); + $request->getBody()->write(encode([ + 'tag_name' => $version->fullReleaseName(), + 'name' => $version->fullReleaseName(), + 'body' => $releaseNotes, + ])); $response = $this->client->sendRequest($request); - Psl\invariant($response->getStatusCode() >= 200 && $response->getStatusCode() <= 299, 'Failed to create release through GitHub API.'); + $statusCode = $response->getStatusCode(); + $responseBody = (string) $response->getBody(); + $validResponseCode = $statusCode >= 200 && $statusCode <= 299; + + if ($validResponseCode) { + $responseData = typed($responseBody, shape([ + 'html_url' => non_empty_string(), + ])); - $responseBody = $response - ->getBody() - ->__toString(); + return new Uri($responseData['html_url']); + } - $responseData = Json\typed($responseBody, Type\shape([ - 'html_url' => Type\non_empty_string(), + $errorResponseData = typed($responseBody, shape([ + 'message' => non_empty_string(), ])); - return new Uri($responseData['html_url']); + invariant_violation( + "Failed to create release through GitHub API;\nStatus code: %s\nMessage: %s\n", + $statusCode, + $errorResponseData['message'], + ); } } diff --git a/src/Github/Value/RepositoryName.php b/src/Github/Value/RepositoryName.php index 4d2bc9c1..68570397 100644 --- a/src/Github/Value/RepositoryName.php +++ b/src/Github/Value/RepositoryName.php @@ -11,6 +11,8 @@ use Psl\Type; use Psr\Http\Message\UriInterface; +use function explode; + /** @psalm-immutable */ final class RepositoryName { @@ -39,7 +41,7 @@ public static function fromFullName(string $fullName): self { Psl\invariant(Regex\matches($fullName, '~^[a-zA-Z0-9_\\.-]+/[a-zA-Z0-9_\\.-]+$~'), 'Invalid repository name.'); - [$owner, $name] = Str\split($fullName, '/'); + [$owner, $name] = explode('/', $fullName); return new self( Type\non_empty_string()->assert($owner), diff --git a/test/unit/Changelog/ChangelogReleaseNotesTest.php b/test/unit/Changelog/ChangelogReleaseNotesTest.php index 319bc053..d9498fa5 100644 --- a/test/unit/Changelog/ChangelogReleaseNotesTest.php +++ b/test/unit/Changelog/ChangelogReleaseNotesTest.php @@ -156,11 +156,9 @@ public function testMergedInstanceContainsChangelogEntryFromTheInstanceThatHadOn ): void { $merged = $original->merge($secondary); - $r = new ReflectionProperty($merged, 'changelogEntry'); - $r->setAccessible(true); - + $reflectionProperty = new ReflectionProperty($merged, 'changelogEntry'); // Equals, but not same, as the class stores a clone of the original. - $this->assertEquals($expectedEntry, $r->getValue($merged)); + $this->assertEquals($expectedEntry, $reflectionProperty->getValue($merged)); } private const CHANGELOG_ENTRY = <<< 'ENTRY' diff --git a/test/unit/Environment/EnvironmentVariablesTest.php b/test/unit/Environment/EnvironmentVariablesTest.php index 04b6acaf..0245ed17 100644 --- a/test/unit/Environment/EnvironmentVariablesTest.php +++ b/test/unit/Environment/EnvironmentVariablesTest.php @@ -13,6 +13,8 @@ use Psl\Exception\InvariantViolationException; use Psl\SecureRandom; +use function Psl\Env\set_var; + final class EnvironmentVariablesTest extends TestCase { private const RESET_ENVIRONMENT_VARIABLES = [ @@ -51,7 +53,7 @@ protected function tearDown(): void return; } - Env\set_var($key, $value); + set_var($key, $value); }); parent::tearDown(); @@ -68,13 +70,13 @@ public function testReadsEnvironmentVariables(): void $githubEventPath = 'githubEventPath' . SecureRandom\string(8); $githubWorkspace = 'githubWorkspace' . SecureRandom\string(8); - Env\set_var('GITHUB_TOKEN', $githubToken); - Env\set_var('SIGNING_SECRET_KEY', $signingSecretKey); - Env\set_var('GITHUB_ORGANISATION', $githubOrganisation); - Env\set_var('GIT_AUTHOR_NAME', $gitAuthorName); - Env\set_var('GIT_AUTHOR_EMAIL', $gitAuthorEmail); - Env\set_var('GITHUB_EVENT_PATH', $githubEventPath); - Env\set_var('GITHUB_WORKSPACE', $githubWorkspace); + set_var('GITHUB_TOKEN', $githubToken); + set_var('SIGNING_SECRET_KEY', $signingSecretKey); + set_var('GITHUB_ORGANISATION', $githubOrganisation); + set_var('GIT_AUTHOR_NAME', $gitAuthorName); + set_var('GIT_AUTHOR_EMAIL', $gitAuthorEmail); + set_var('GITHUB_EVENT_PATH', $githubEventPath); + set_var('GITHUB_WORKSPACE', $githubWorkspace); $importKey = $this->createMock(ImportGpgKeyFromString::class); @@ -94,13 +96,13 @@ public function testReadsEnvironmentVariables(): void public function testFailsOnMissingEnvironmentVariables(): void { - Env\set_var('GITHUB_TOKEN', ''); - Env\set_var('SIGNING_SECRET_KEY', 'aaa'); - Env\set_var('GITHUB_ORGANISATION', 'bbb'); - Env\set_var('GIT_AUTHOR_NAME', 'ccc'); - Env\set_var('GIT_AUTHOR_EMAIL', 'ddd@eee.ff'); - Env\set_var('GITHUB_EVENT_PATH', '/tmp/event'); - Env\set_var('GITHUB_WORKSPACE', '/tmp'); + set_var('GITHUB_TOKEN', ''); + set_var('SIGNING_SECRET_KEY', 'aaa'); + set_var('GITHUB_ORGANISATION', 'bbb'); + set_var('GIT_AUTHOR_NAME', 'ccc'); + set_var('GIT_AUTHOR_EMAIL', 'ddd@eee.ff'); + set_var('GITHUB_EVENT_PATH', '/tmp/event'); + set_var('GITHUB_WORKSPACE', '/tmp'); $importKey = $this->createMock(ImportGpgKeyFromString::class); @@ -118,13 +120,13 @@ public function testDebugModeOffEnvironmentVariables(): void // missing env variable. Env\remove_var('ACTIONS_RUNNER_DEBUG'); - Env\set_var('GITHUB_TOKEN', 'token'); - Env\set_var('SIGNING_SECRET_KEY', 'aaa'); - Env\set_var('GITHUB_ORGANISATION', 'bbb'); - Env\set_var('GIT_AUTHOR_NAME', 'ccc'); - Env\set_var('GIT_AUTHOR_EMAIL', 'ddd@eee.ff'); - Env\set_var('GITHUB_EVENT_PATH', '/tmp/event'); - Env\set_var('GITHUB_WORKSPACE', '/tmp'); + set_var('GITHUB_TOKEN', 'token'); + set_var('SIGNING_SECRET_KEY', 'aaa'); + set_var('GITHUB_ORGANISATION', 'bbb'); + set_var('GIT_AUTHOR_NAME', 'ccc'); + set_var('GIT_AUTHOR_EMAIL', 'ddd@eee.ff'); + set_var('GITHUB_EVENT_PATH', '/tmp/event'); + set_var('GITHUB_WORKSPACE', '/tmp'); $importKey = $this->createMock(ImportGpgKeyFromString::class); $importKey->method('__invoke')->willReturn(SecretKeyId::fromBase16String('aabbccdd')); @@ -134,14 +136,14 @@ public function testDebugModeOffEnvironmentVariables(): void public function testDebugModeOnEnvironmentVariables(): void { - Env\set_var('ACTIONS_RUNNER_DEBUG', 'TRUE'); - Env\set_var('GITHUB_TOKEN', 'token'); - Env\set_var('SIGNING_SECRET_KEY', 'aaa'); - Env\set_var('GITHUB_ORGANISATION', 'bbb'); - Env\set_var('GIT_AUTHOR_NAME', 'ccc'); - Env\set_var('GIT_AUTHOR_EMAIL', 'ddd@eee.ff'); - Env\set_var('GITHUB_EVENT_PATH', '/tmp/event'); - Env\set_var('GITHUB_WORKSPACE', '/tmp'); + set_var('ACTIONS_RUNNER_DEBUG', 'TRUE'); + set_var('GITHUB_TOKEN', 'token'); + set_var('SIGNING_SECRET_KEY', 'aaa'); + set_var('GITHUB_ORGANISATION', 'bbb'); + set_var('GIT_AUTHOR_NAME', 'ccc'); + set_var('GIT_AUTHOR_EMAIL', 'ddd@eee.ff'); + set_var('GITHUB_EVENT_PATH', '/tmp/event'); + set_var('GITHUB_WORKSPACE', '/tmp'); $importKey = $this->createMock(ImportGpgKeyFromString::class); $importKey->method('__invoke')->willReturn(SecretKeyId::fromBase16String('aabbccdd')); @@ -149,4 +151,34 @@ public function testDebugModeOnEnvironmentVariables(): void self::assertSame('DEBUG', $variables->logLevel()); } + + public function testInvalidLogLevelEnvironmentVariables(): void + { + $this->setupRequiredEnvironmentVariables(); + + set_var('LOG_LEVEL', 'TEMP'); + + $this->expectException(InvariantViolationException::class); + $this->expectExceptionMessage( + 'LOG_LEVEL env MUST be a valid monolog/monolog log level constant name or value;' + . ' see https://github.com/Seldaek/monolog/blob/master/doc/01-usage.md#log-levels', + ); + + $importKey = $this->createMock(ImportGpgKeyFromString::class); + $importKey->method('__invoke') + ->willReturn(SecretKeyId::fromBase16String('aabbccdd')); + + EnvironmentVariables::fromEnvironment($importKey); + } + + private function setupRequiredEnvironmentVariables(): void + { + set_var('GITHUB_TOKEN', 'token'); + set_var('SIGNING_SECRET_KEY', 'aaa'); + set_var('GITHUB_ORGANISATION', 'bbb'); + set_var('GIT_AUTHOR_NAME', 'ccc'); + set_var('GIT_AUTHOR_EMAIL', 'ddd@eee.ff'); + set_var('GITHUB_EVENT_PATH', '/tmp/event'); + set_var('GITHUB_WORKSPACE', '/tmp'); + } } diff --git a/test/unit/Github/Api/GraphQL/Query/GetMilestoneChangelog/Response/LabelTest.php b/test/unit/Github/Api/GraphQL/Query/GetMilestoneChangelog/Response/LabelTest.php index 0a368e77..4845a5c8 100644 --- a/test/unit/Github/Api/GraphQL/Query/GetMilestoneChangelog/Response/LabelTest.php +++ b/test/unit/Github/Api/GraphQL/Query/GetMilestoneChangelog/Response/LabelTest.php @@ -48,7 +48,7 @@ public function testInvalidPayload(array $payload): void Label::fromPayload($payload); } - /** @return iterable>> */ + /** @return iterable}> */ public function provideInvalidPayload(): iterable { yield [ diff --git a/test/unit/Github/Api/V3/CreateReleaseThroughApiCallTest.php b/test/unit/Github/Api/V3/CreateReleaseThroughApiCallTest.php index c20a0f75..824ef84e 100644 --- a/test/unit/Github/Api/V3/CreateReleaseThroughApiCallTest.php +++ b/test/unit/Github/Api/V3/CreateReleaseThroughApiCallTest.php @@ -18,6 +18,10 @@ use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\RequestInterface; +use function sprintf; + +use const PHP_EOL; + /** @covers \Laminas\AutomaticReleases\Github\Api\V3\CreateReleaseThroughApiCall */ final class CreateReleaseThroughApiCallTest extends TestCase { @@ -102,13 +106,13 @@ public function testSuccessfulRequest(int $responseCode): void ); } - /** @psalm-return non-empty-list */ + /** @psalm-return array> */ public function exampleValidResponseCodes(): array { return [ - [200], - [201], - [204], + 200 => [200], + 201 => [201], + 204 => [204], ]; } @@ -127,8 +131,11 @@ public function testRequestFailedToCreateReleaseDueToInvalidResponseCode(int $re $invalidResponse = (new Response()) ->withStatus($responseCode); - $invalidResponse->getBody() - ->write('{"html_url": "http://the-domain.com/release"}'); + // `message` field describing the error + // https://docs.github.com/en/rest/overview/resources-in-the-rest-api#client-errors + $invalidResponse->getBody()->write( + sprintf('{"message": "%s"}', 'Error code ' . $responseCode), + ); $this->httpClient ->expects(self::once()) @@ -136,23 +143,27 @@ public function testRequestFailedToCreateReleaseDueToInvalidResponseCode(int $re ->willReturn($invalidResponse); $this->expectException(InvariantViolationException::class); - $this->expectExceptionMessage('Failed to create release through GitHub API.'); + $this->expectExceptionMessage( + 'Failed to create release through GitHub API;' . PHP_EOL + . 'Status code: ' . $responseCode . PHP_EOL + . 'Message: Error code ' . $responseCode . PHP_EOL, + ); - $this->createRelease->__invoke( + ($this->createRelease)( RepositoryName::fromFullName('foo/bar'), SemVerVersion::fromMilestoneName('1.2.3'), 'A description for my awesome release', ); } - /** @psalm-return non-empty-list */ + /** @psalm-return array> */ public function exampleFailureResponseCodes(): array { return [ - [199], - [400], - [401], - [500], + 199 => [199], + 400 => [400], + 401 => [401], + 500 => [500], ]; }