Skip to content

Commit

Permalink
Merge pull request #10 from Kocal/feat/config-latest-stable-or-nightly
Browse files Browse the repository at this point in the history
  • Loading branch information
Kocal authored Aug 6, 2024
2 parents fdc033e + f5e669e commit 2d3fa3d
Show file tree
Hide file tree
Showing 4 changed files with 8,654 additions and 15 deletions.
38 changes: 35 additions & 3 deletions src/BiomeJsBinary.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@ final class BiomeJsBinary implements BiomeJsBinaryInterface
private HttpClientInterface $httpClient;
private ?string $cachedVersion = null;

public const LATEST_STABLE_VERSION = 'latest_stable';
public const LATEST_NIGHTLY_VERSION = 'latest_nightly';

/**
* @param string|self::LATEST_STABLE_VERSION|self::LATEST_NIGHTLY_VERSION|null $binaryVersion
*/
public function __construct(
private readonly string $cwd,
private readonly string $binaryDownloadDir,
private readonly ?string $binaryVersion,
?HttpClientInterface $httpClient = null,
) {
if (null === $this->binaryVersion) {
trigger_deprecation('kocal/biome-js-bundle', '1.1', 'Not explicitly specifying a Biome.js CLI version is deprecated, use "latest_stable", "latest_nightly", or an explicit version (e.g.: "v1.8.3") instead.');
}

$this->httpClient = $httpClient ?? HttpClient::create();
}

Expand Down Expand Up @@ -95,17 +105,39 @@ private function downloadExecutable(): void

private function getVersion(): string
{
return $this->cachedVersion ??= $this->binaryVersion ?? $this->getLatestVersion();
if (null !== $this->cachedVersion) {
return $this->cachedVersion;
}

if (null === $this->binaryVersion || self::LATEST_STABLE_VERSION === $this->binaryVersion || self::LATEST_NIGHTLY_VERSION === $this->binaryVersion) {
return $this->cachedVersion = $this->getLatestVersion();
}

return $this->cachedVersion = $this->binaryVersion;
}

private function getLatestVersion(): string
{
$useStable = null === $this->binaryVersion || 'latest_stable' === $this->binaryVersion;
$useNightly = 'latest_nightly' === $this->binaryVersion;

try {
$response = $this->httpClient->request('GET', 'https://api.github.com/repos/biomejs/biome/releases');

foreach ($response->toArray() as $release) {
if (str_starts_with($release['tag_name'], 'cli/')) {
return str_replace('cli/', '', $release['tag_name']);
if (!str_starts_with($release['tag_name'], 'cli/')) {
continue;
}

if ($useStable && true === $release['prerelease']) {
continue;
}

if ($useNightly && false === $release['prerelease']) {
continue;
}

return str_replace('cli/', '', $release['tag_name']);
}

throw new \Exception('Unable to find the latest Biome.js CLI release.');
Expand Down
10 changes: 7 additions & 3 deletions src/DependencyInjection/BiomeJsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,13 @@ public function getConfigTreeBuilder(): TreeBuilder
$rootNode
->children()
->scalarNode('binary_version')
->info('Biome.js CLI version to download - null means the latest version')
->example('v1.7.3')
->defaultNull()
->info('Biome.js CLI version to download, can be either a specific version, "latest_stable" or "latest_nightly".')
->example([
'v1.7.3',
'latest_stable',
'latest_nightly',
])
->defaultValue('latest_stable')
->end()
->end();

Expand Down
61 changes: 52 additions & 9 deletions tests/BiomeJsBinaryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,61 @@
namespace Kocal\BiomeJsBundle\Tests;

use Kocal\BiomeJsBundle\BiomeJsBinary;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\JsonMockResponse;
use Symfony\Component\HttpClient\Response\MockResponse;
use Symfony\Contracts\HttpClient\HttpClientInterface;

final class BiomeJsBinaryTest extends TestCase
{
public function testBinaryIsDownloadedIfNotExists(): void
private HttpClientInterface $httpClient;

protected function setUp(): void
{
$this->httpClient = new MockHttpClient(function (string $method, string $url, array $options) {
// Mock GitHub API, the releases must contain multiples stable versions and nightly versions,
// and also not-CLI releases (e.g.: js-api).
if ('GET' === $method && 'https://api.github.com/repos/biomejs/biome/releases' === $url) {
return new JsonMockResponse(
json_decode(
file_get_contents(__DIR__ . '/github-biomejs-releases.json') ?: throw new \RuntimeException('Cannot read file "github-biomejs-releases.json".'),
associative: true,
flags: JSON_THROW_ON_ERROR
)
);
}

if ('GET' === $method && str_starts_with($url, 'https://github.com/biomejs/biome/releases/download/cli')) {
$binaryName = BiomeJsBinary::getBinaryName();

return match ($url) {
'https://github.com/biomejs/biome/releases/download/cli/v1.8.1/' . $binaryName => new MockResponse('fake-binary-content v1.8.1'),
'https://github.com/biomejs/biome/releases/download/cli/v1.8.3/' . $binaryName => new MockResponse('fake-binary-content v1.8.3'),
'https://github.com/biomejs/biome/releases/download/cli/v1.8.4-nightly.bd1d0c6/' . $binaryName => new MockResponse('fake-binary-content v1.8.4-nightly.bd1d0c6'),
default => new MockResponse('Not Found', ['http_code' => 404]),
};
}

return new MockResponse('Not Found', ['http_code' => 404]);
});
}

/**
* @return iterable<array{passedVersion: ?string, expectedVersion: string}>
*/
public static function provideBinaryIsDownloadedIfNotExists(): iterable
{
yield 'specific version' => ['passedVersion' => 'v1.8.1', 'expectedVersion' => 'v1.8.1'];
yield 'latest stable version' => ['passedVersion' => null, 'expectedVersion' => 'v1.8.3'];
yield 'latest stable version (explicit)' => ['passedVersion' => 'latest_stable', 'expectedVersion' => 'v1.8.3'];
yield 'latest nightly version' => ['passedVersion' => 'latest_nightly', 'expectedVersion' => 'v1.8.4-nightly.bd1d0c6'];
}

#[DataProvider('provideBinaryIsDownloadedIfNotExists')]
public function testBinaryIsDownloadedIfNotExists(?string $passedVersion, string $expectedVersion): void
{
$binaryDownloadDir = __DIR__ . '/fixtures/var/download';
$fs = new Filesystem();
Expand All @@ -21,24 +68,20 @@ public function testBinaryIsDownloadedIfNotExists(): void
}
$fs->mkdir($binaryDownloadDir);

$client = new MockHttpClient([
new MockResponse('fake binary contents'),
]);

$binary = new BiomeJsBinary(
__DIR__,
$binaryDownloadDir,
'fake-version',
$client
$passedVersion,
$this->httpClient,
);
$process = $binary->createProcess(['check', '--apply', '*.{js,ts}']);
self::assertFileExists($binaryDownloadDir . '/fake-version/' . BiomeJsBinary::getBinaryName());
self::assertFileExists($binaryDownloadDir . '/' . $expectedVersion . '/' . BiomeJsBinary::getBinaryName());

// Windows doesn't wrap arguments in quotes
$expectedTemplate = '\\' === \DIRECTORY_SEPARATOR ? '"%s" check --apply *.{js,ts}' : "'%s' 'check' '--apply' '*.{js,ts}'";

self::assertSame(
sprintf($expectedTemplate, $binaryDownloadDir . '/fake-version/' . BiomeJsBinary::getBinaryName()),
sprintf($expectedTemplate, $binaryDownloadDir . '/' . $expectedVersion . '/' . BiomeJsBinary::getBinaryName()),
$process->getCommandLine()
);
}
Expand Down
Loading

0 comments on commit 2d3fa3d

Please sign in to comment.