diff --git a/src/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListener.php b/src/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListener.php index 46272f47..641916a8 100644 --- a/src/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListener.php +++ b/src/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListener.php @@ -20,6 +20,7 @@ use Psr\Container\ContainerInterface; use Throwable; +use function array_merge_recursive; use function array_walk; use function in_array; use function pathinfo; @@ -134,7 +135,7 @@ function (OperationInterface $operation): void { $packageReleaseAssets = $this->container->get(PackageReleaseAssets::class); try { - $url = $packageReleaseAssets->findMatchingReleaseAssetUrl( + $matchedReleaseAsset = $packageReleaseAssets->findMatchingReleaseAsset( $targetPlatform, $piePackage, new HttpDownloader($this->io, $this->composer->getConfig()), @@ -147,8 +148,13 @@ function (OperationInterface $operation): void { continue; } - $this->composerRequest->pieOutput->write('Found prebuilt archive: ' . $url); - $composerPackage->setDistUrl($url); + $this->composerRequest->pieOutput->write('Found prebuilt archive: ' . $matchedReleaseAsset->url); + $composerPackage->setDistUrl($matchedReleaseAsset->url); + + $composerPackage->setTransportOptions(array_merge_recursive( + $composerPackage->getTransportOptions(), + ['http' => ['header' => ['Accept: application/octet-stream']]], + )); // Composer's dist-sha was computed against the original // Packagist URL; once we swap to a release-asset URL the @@ -159,7 +165,7 @@ function (OperationInterface $operation): void { 'Note: dist-sha integrity check is not available for prebuilt-binary URLs; HTTPS to the release-asset origin is the only integrity guarantee.', ); - if (pathinfo($url, PATHINFO_EXTENSION) === 'tgz') { + if (pathinfo($matchedReleaseAsset->filename, PATHINFO_EXTENSION) === 'tgz') { $composerPackage->setDistType('tar'); } diff --git a/src/Downloading/GithubPackageReleaseAssets.php b/src/Downloading/GithubPackageReleaseAssets.php index ad1bd13a..3826a7ce 100644 --- a/src/Downloading/GithubPackageReleaseAssets.php +++ b/src/Downloading/GithubPackageReleaseAssets.php @@ -22,18 +22,14 @@ public function __construct( ) { } - /** - * @param non-empty-list $possibleReleaseAssetNames - * - * @return non-empty-string - */ - public function findMatchingReleaseAssetUrl( + /** @param non-empty-list $possibleReleaseAssetNames */ + public function findMatchingReleaseAsset( TargetPlatform $targetPlatform, Package $package, HttpDownloader $httpDownloader, DownloadUrlMethod $downloadUrlMethod, array $possibleReleaseAssetNames, - ): string { + ): MatchedReleaseAsset { $releaseAsset = $this->selectMatchingReleaseAsset( $targetPlatform, $package, @@ -42,16 +38,16 @@ public function findMatchingReleaseAssetUrl( $possibleReleaseAssetNames, ); - return $releaseAsset['browser_download_url']; + return new MatchedReleaseAsset($releaseAsset['url'], $releaseAsset['name']); } /** @link https://github.com/squizlabs/PHP_CodeSniffer/issues/3734 */ // phpcs:disable Squiz.Commenting.FunctionComment.MissingParamName /** - * @param list $releaseAssets + * @param list $releaseAssets * @param non-empty-list $possibleReleaseAssetNames * - * @return array{name: non-empty-string, browser_download_url: non-empty-string, ...} + * @return array{name: non-empty-string, url: non-empty-string, ...} */ // phpcs:enable private function selectMatchingReleaseAsset( @@ -70,7 +66,7 @@ private function selectMatchingReleaseAsset( throw Exception\CouldNotFindReleaseAsset::forPackage($targetPlatform, $package, $downloadUrlMethod, $possibleReleaseAssetNames); } - /** @return list */ + /** @return list */ private function getReleaseAssetsForPackage( Package $package, HttpDownloader $httpDownloader, @@ -106,8 +102,8 @@ private function getReleaseAssetsForPackage( static function (array $asset): array { Assert::keyExists($asset, 'name'); Assert::stringNotEmpty($asset['name']); - Assert::keyExists($asset, 'browser_download_url'); - Assert::stringNotEmpty($asset['browser_download_url']); + Assert::keyExists($asset, 'url'); + Assert::stringNotEmpty($asset['url']); return $asset; }, diff --git a/src/Downloading/MatchedReleaseAsset.php b/src/Downloading/MatchedReleaseAsset.php new file mode 100644 index 00000000..f10554e5 --- /dev/null +++ b/src/Downloading/MatchedReleaseAsset.php @@ -0,0 +1,23 @@ + $possibleReleaseAssetNames - * - * @return non-empty-string - */ - public function findMatchingReleaseAssetUrl( + /** @param non-empty-list $possibleReleaseAssetNames */ + public function findMatchingReleaseAsset( TargetPlatform $targetPlatform, Package $package, HttpDownloader $httpDownloader, DownloadUrlMethod $downloadUrlMethod, array $possibleReleaseAssetNames, - ): string; + ): MatchedReleaseAsset; } diff --git a/test/integration/Downloading/GithubPackageReleaseAssetsTest.php b/test/integration/Downloading/GithubPackageReleaseAssetsTest.php index 2d04ec80..a2153701 100644 --- a/test/integration/Downloading/GithubPackageReleaseAssetsTest.php +++ b/test/integration/Downloading/GithubPackageReleaseAssetsTest.php @@ -60,10 +60,10 @@ public function testDeterminingReleaseAssetUrlForWindows(): void $config = Factory::createConfig(); $io->loadConfiguration($config); - self::assertSame( - 'https://github.com/asgrim/example-pie-extension/releases/download/2.0.2/php_example_pie_extension-2.0.2-8.3-ts-vs16-x86_64.zip', + self::assertMatchesRegularExpression( + '~^https://api\.github\.com/repos/asgrim/example-pie-extension/releases/assets/\d+$~', (new GithubPackageReleaseAssets('https://api.github.com')) - ->findMatchingReleaseAssetUrl( + ->findMatchingReleaseAsset( $targetPlatform, $package, new HttpDownloader($io, $config), @@ -72,7 +72,7 @@ public function testDeterminingReleaseAssetUrlForWindows(): void $targetPlatform, $package, ), - ), + )->url, ); } } diff --git a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php index f7ce589a..2e706841 100644 --- a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php +++ b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php @@ -21,6 +21,7 @@ use Php\Pie\DependencyResolver\RequestedPackageAndVersion; use Php\Pie\Downloading\DownloadUrlMethod; use Php\Pie\Downloading\Exception\CouldNotFindReleaseAsset; +use Php\Pie\Downloading\MatchedReleaseAsset; use Php\Pie\Downloading\PackageReleaseAssets; use Php\Pie\Platform\Architecture; use Php\Pie\Platform\OperatingSystem; @@ -283,8 +284,11 @@ public function testDistUrlIsUpdatedForWindowsInstallers(): void $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); $packageReleaseAssets ->expects(self::once()) - ->method('findMatchingReleaseAssetUrl') - ->willReturn('https://example.com/windows-download-url'); + ->method('findMatchingReleaseAsset') + ->willReturn(new MatchedReleaseAsset( + 'https://api.github.com/repos/foo/bar/releases/assets/11111', + 'php_foo-1.2.3-8.3-vc14-ts-x86.zip', + )); $this->container ->method('get') @@ -315,10 +319,11 @@ public function testDistUrlIsUpdatedForWindowsInstallers(): void ))($installerEvent); self::assertSame( - 'https://example.com/windows-download-url', + 'https://api.github.com/repos/foo/bar/releases/assets/11111', $composerPackage->getDistUrl(), ); self::assertSame(DownloadUrlMethod::WindowsBinaryDownload, DownloadUrlMethod::fromComposerPackage($composerPackage)); + self::assertSame(['http' => ['header' => ['Accept: application/octet-stream']]], $composerPackage->getTransportOptions()); } public function testDistUrlIsUpdatedForPrePackagedTgzSource(): void @@ -343,8 +348,11 @@ public function testDistUrlIsUpdatedForPrePackagedTgzSource(): void $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); $packageReleaseAssets ->expects(self::once()) - ->method('findMatchingReleaseAssetUrl') - ->willReturn('https://example.com/pre-packaged-source-download-url.tgz'); + ->method('findMatchingReleaseAsset') + ->willReturn(new MatchedReleaseAsset( + 'https://api.github.com/repos/foo/bar/releases/assets/22222', + 'php_foobar-1.2.3-src.tgz', + )); $this->container ->method('get') @@ -375,7 +383,7 @@ public function testDistUrlIsUpdatedForPrePackagedTgzSource(): void ))($installerEvent); self::assertSame( - 'https://example.com/pre-packaged-source-download-url.tgz', + 'https://api.github.com/repos/foo/bar/releases/assets/22222', $composerPackage->getDistUrl(), ); self::assertSame(DownloadUrlMethod::PrePackagedSourceDownload, DownloadUrlMethod::fromComposerPackage($composerPackage)); @@ -404,8 +412,11 @@ public function testDistUrlIsUpdatedForPrePackagedTgzBinaryWhenBinaryIsFound(): $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); $packageReleaseAssets ->expects(self::once()) - ->method('findMatchingReleaseAssetUrl') - ->willReturn('https://example.com/pre-packaged-binary-download-url.tgz'); + ->method('findMatchingReleaseAsset') + ->willReturn(new MatchedReleaseAsset( + 'https://api.github.com/repos/foo/bar/releases/assets/12345', + 'php_foobar-1.2.3_php8.3-x86_64-linux-glibc-zts.tgz', + )); $this->container ->method('get') @@ -436,11 +447,12 @@ public function testDistUrlIsUpdatedForPrePackagedTgzBinaryWhenBinaryIsFound(): ))($installerEvent); self::assertSame( - 'https://example.com/pre-packaged-binary-download-url.tgz', + 'https://api.github.com/repos/foo/bar/releases/assets/12345', $composerPackage->getDistUrl(), ); self::assertSame(DownloadUrlMethod::PrePackagedBinary, DownloadUrlMethod::fromComposerPackage($composerPackage)); self::assertSame('tar', $composerPackage->getDistType()); + self::assertSame(['http' => ['header' => ['Accept: application/octet-stream']]], $composerPackage->getTransportOptions()); } public function testDistUrlIsUpdatedForPrePackagedTgzBinaryWhenBinaryIsNotFound(): void @@ -465,7 +477,7 @@ public function testDistUrlIsUpdatedForPrePackagedTgzBinaryWhenBinaryIsNotFound( $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); $packageReleaseAssets ->expects(self::once()) - ->method('findMatchingReleaseAssetUrl') + ->method('findMatchingReleaseAsset') ->willThrowException(new CouldNotFindReleaseAsset('nope not found')); $this->container @@ -583,8 +595,11 @@ public function testDistUrlIsUpdatedForWindowsInstallersOnUpdateOperations(): vo $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); $packageReleaseAssets ->expects(self::once()) - ->method('findMatchingReleaseAssetUrl') - ->willReturn('https://example.com/windows-download-url'); + ->method('findMatchingReleaseAsset') + ->willReturn(new MatchedReleaseAsset( + 'https://api.github.com/repos/foo/bar/releases/assets/33333', + 'php_foo-1.2.3-8.3-vc14-ts-x86.zip', + )); $this->container ->method('get') @@ -615,7 +630,7 @@ public function testDistUrlIsUpdatedForWindowsInstallersOnUpdateOperations(): vo ))($installerEvent); self::assertSame( - 'https://example.com/windows-download-url', + 'https://api.github.com/repos/foo/bar/releases/assets/33333', $targetPackage->getDistUrl(), ); self::assertSame(DownloadUrlMethod::WindowsBinaryDownload, DownloadUrlMethod::fromComposerPackage($targetPackage)); @@ -643,7 +658,7 @@ public function testNoSelectedDownloadUrlMethodWillThrowException(): void $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); $packageReleaseAssets ->expects(self::once()) - ->method('findMatchingReleaseAssetUrl') + ->method('findMatchingReleaseAsset') ->willThrowException(new CouldNotFindReleaseAsset('nope not found')); $this->container diff --git a/test/unit/Downloading/GithubPackageReleaseAssetsTest.php b/test/unit/Downloading/GithubPackageReleaseAssetsTest.php index e36347b5..2260075a 100644 --- a/test/unit/Downloading/GithubPackageReleaseAssetsTest.php +++ b/test/unit/Downloading/GithubPackageReleaseAssetsTest.php @@ -56,11 +56,11 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrl(): void 'assets' => [ [ 'name' => 'php_foo-1.2.3-8.3-vc14-nts-x86.zip', - 'browser_download_url' => 'wrong_download_url', + 'url' => 'wrong_download_url', ], [ 'name' => 'php_foo-1.2.3-8.3-vc14-ts-x86.zip', - 'browser_download_url' => 'actual_download_url', + 'url' => 'actual_download_url', ], ], ]); @@ -84,7 +84,7 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrl(): void self::assertSame( 'actual_download_url', - $releaseAssets->findMatchingReleaseAssetUrl( + $releaseAssets->findMatchingReleaseAsset( $targetPlatform, $package, $httpDownloader, @@ -93,7 +93,7 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrl(): void $targetPlatform, $package, ), - ), + )->url, ); } @@ -123,11 +123,11 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrlWithCompilerAndThr 'assets' => [ [ 'name' => 'php_foo-1.2.3-8.3-nts-vc14-x86.zip', - 'browser_download_url' => 'wrong_download_url', + 'url' => 'wrong_download_url', ], [ 'name' => 'php_foo-1.2.3-8.3-ts-vc14-x86.zip', - 'browser_download_url' => 'actual_download_url', + 'url' => 'actual_download_url', ], ], ]); @@ -151,7 +151,7 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrlWithCompilerAndThr self::assertSame( 'actual_download_url', - $releaseAssets->findMatchingReleaseAssetUrl( + $releaseAssets->findMatchingReleaseAsset( $targetPlatform, $package, $httpDownloader, @@ -160,7 +160,7 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrlWithCompilerAndThr $targetPlatform, $package, ), - ), + )->url, ); } @@ -198,7 +198,7 @@ public function testFindWindowsDownloadUrlForPackageThrowsExceptionWhenAssetNotF $releaseAssets = new GithubPackageReleaseAssets('https://test-github-api-base-url.thephp.foundation'); $this->expectException(CouldNotFindReleaseAsset::class); - $releaseAssets->findMatchingReleaseAssetUrl( + $releaseAssets->findMatchingReleaseAsset( $targetPlatform, $package, $httpDownloader,