Skip to content

Commit 8e52aaf

Browse files
authored
Merge pull request #24 from jmsche/cache-latest-version
2 parents 5b285b2 + e471357 commit 8e52aaf

File tree

4 files changed

+66
-3
lines changed

4 files changed

+66
-3
lines changed

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
],
2323
"require": {
2424
"php": ">=8.1",
25+
"symfony/cache": "^6.4|^7.0",
2526
"symfony/console": "^6.4|^7.0",
2627
"symfony/http-client": "^6.4|^7.0",
2728
"symfony/process": "^6.4|^7.0"

config/services.php

+6
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,17 @@
1212

1313
return static function (ContainerConfigurator $container): void {
1414
$container->services()
15+
->set('.biomejs.cache')
16+
->parent('cache.system')
17+
->private()
18+
->tag('cache.pool')
19+
1520
->set('biomejs.binary', BiomeJsBinary::class)
1621
->args([
1722
param('kernel.project_dir'),
1823
param('kernel.project_dir').'/var/biomejs',
1924
abstract_arg('Biome.js binary version'),
25+
service('.biomejs.cache'),
2026
])
2127
->alias(BiomeJsBinaryInterface::class, 'biomejs.binary')
2228

src/BiomeJsBinary.php

+23-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Kocal\BiomeJsBundle;
66

7+
use Psr\Cache\CacheItemPoolInterface;
78
use Symfony\Component\Console\Style\SymfonyStyle;
89
use Symfony\Component\HttpClient\HttpClient;
910
use Symfony\Component\HttpClient\RetryableHttpClient;
@@ -29,6 +30,7 @@ public function __construct(
2930
private readonly string $cwd,
3031
private readonly string $binaryDownloadDir,
3132
private readonly ?string $binaryVersion,
33+
private readonly CacheItemPoolInterface $cache,
3234
?HttpClientInterface $httpClient = null,
3335
) {
3436
if (null === $this->binaryVersion) {
@@ -121,6 +123,20 @@ private function getLatestVersion(): string
121123
{
122124
$useStable = null === $this->binaryVersion || 'latest_stable' === $this->binaryVersion;
123125
$useNightly = 'latest_nightly' === $this->binaryVersion;
126+
$cacheKey = sprintf(
127+
'binary.latest_version.%s.%s',
128+
match (true) {
129+
$useStable => 'stable',
130+
$useNightly => 'nightly',
131+
default => throw new \LogicException('Invalid configuration'),
132+
},
133+
self::getBinaryName(),
134+
);
135+
$cacheItem = $this->cache->getItem($cacheKey);
136+
137+
if (($cachedLatestVersion = $cacheItem->get()) && is_string($cachedLatestVersion)) {
138+
return $cachedLatestVersion;
139+
}
124140

125141
try {
126142
$response = $this->httpClient->request('GET', 'https://api.github.com/repos/biomejs/biome/releases');
@@ -138,7 +154,13 @@ private function getLatestVersion(): string
138154
continue;
139155
}
140156

141-
return str_replace('cli/', '', $release['tag_name']);
157+
$latestVersion = str_replace('cli/', '', $release['tag_name']);
158+
159+
$cacheItem->set($latestVersion);
160+
$cacheItem->expiresAfter(new \DateInterval('P1W'));
161+
$this->cache->save($cacheItem);
162+
163+
return $latestVersion;
142164
}
143165

144166
throw new \Exception('Unable to find the latest Biome.js CLI release.');

tests/BiomeJsBinaryTest.php

+36-2
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77
use Kocal\BiomeJsBundle\BiomeJsBinary;
88
use PHPUnit\Framework\Attributes\DataProvider;
99
use PHPUnit\Framework\TestCase;
10+
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1011
use Symfony\Component\Filesystem\Filesystem;
1112
use Symfony\Component\HttpClient\MockHttpClient;
1213
use Symfony\Component\HttpClient\Response\JsonMockResponse;
1314
use Symfony\Component\HttpClient\Response\MockResponse;
14-
use Symfony\Contracts\HttpClient\HttpClientInterface;
1515

1616
final class BiomeJsBinaryTest extends TestCase
1717
{
1818
private const BINARY_DOWNLOAD_DIR = __DIR__ . '/fixtures/var/download';
1919

20-
private HttpClientInterface $httpClient;
20+
private MockHttpClient $httpClient;
21+
22+
private ArrayAdapter $cache;
2123

2224
protected function setUp(): void
2325
{
@@ -51,6 +53,8 @@ protected function setUp(): void
5153

5254
return new MockResponse('Not Found', ['http_code' => 404]);
5355
});
56+
57+
$this->cache = new ArrayAdapter();
5458
}
5559

5660
/**
@@ -71,6 +75,7 @@ public function testBinaryIsDownloadedIfNotExists(?string $passedVersion, string
7175
__DIR__,
7276
self::BINARY_DOWNLOAD_DIR,
7377
$passedVersion,
78+
$this->cache,
7479
$this->httpClient,
7580
);
7681
$process = $binary->createProcess(['check', '--apply', '*.{js,ts}']);
@@ -83,5 +88,34 @@ public function testBinaryIsDownloadedIfNotExists(?string $passedVersion, string
8388
sprintf($expectedTemplate, self::BINARY_DOWNLOAD_DIR . '/' . $expectedVersion . '/' . BiomeJsBinary::getBinaryName()),
8489
$process->getCommandLine()
8590
);
91+
92+
$cacheValues = $this->cache->getValues();
93+
if (null !== $passedVersion && str_starts_with($passedVersion, 'v')) {
94+
// A specific version was passed, so no HTTP call expected and no cache call
95+
self::assertCount(0, $cacheValues);
96+
} else {
97+
// No specific version was passed, so an HTTP call expected and cache should be set
98+
self::assertCount(1, $cacheValues);
99+
self::assertSame($expectedVersion, unserialize($cacheValues[array_key_first($cacheValues)]));
100+
101+
// Check that the binary is not downloaded again, but the cache is used
102+
$binary = $this->cloneAndResetBinary($binary);
103+
$this->httpClient->setResponseFactory(fn () => throw new \LogicException('No HTTP request should be made'));
104+
$binary->createProcess(['check', '--apply', '*.{js,ts}']);
105+
106+
$cacheValues = $this->cache->getValues();
107+
self::assertCount(1, $cacheValues);
108+
self::assertSame($expectedVersion, unserialize($cacheValues[array_key_first($cacheValues)]));
109+
}
110+
}
111+
112+
private function cloneAndResetBinary(BiomeJsBinary $binary): BiomeJsBinary
113+
{
114+
$binary = clone $binary;
115+
116+
$reflProperty = new \ReflectionProperty($binary, 'cachedVersion');
117+
$reflProperty->setValue($binary, null);
118+
119+
return clone $binary;
86120
}
87121
}

0 commit comments

Comments
 (0)