Skip to content

Commit d27b5e4

Browse files
simonhampclaude
andauthored
Fix plugin listing page showing stale version (#359)
* Update SyncPluginReleases to keep plugin listing version in sync The SyncPluginReleases job creates PluginVersion records but never updated the plugins.latest_version field, causing the public listing page to show a stale version while admin/Satis showed the correct one. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Mock SatisService in tests to fix CI TypeError SatisService constructor requires non-nullable string properties from config, which are null in CI. Mock it instead since Satis is not exercised in these tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b69fd86 commit d27b5e4

3 files changed

Lines changed: 105 additions & 2 deletions

File tree

app/Jobs/SyncPluginReleases.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,17 @@ public function handle(SatisService $satisService): void
7878
}
7979
}
8080

81-
$this->plugin->update(['last_synced_at' => now()]);
81+
$updateData = ['last_synced_at' => now()];
82+
83+
if ($this->hasNewReleases) {
84+
$latestVersion = $this->plugin->versions()->latest('published_at')->first();
85+
86+
if ($latestVersion) {
87+
$updateData['latest_version'] = $latestVersion->version;
88+
}
89+
}
90+
91+
$this->plugin->update($updateData);
8292

8393
Log::info('[SyncPluginReleases] Processing complete', [
8494
'plugin_id' => $this->plugin->id,

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
namespace Tests\Feature\Jobs;
4+
5+
use App\Jobs\SyncPluginReleases;
6+
use App\Models\Plugin;
7+
use App\Models\PluginVersion;
8+
use App\Services\SatisService;
9+
use Illuminate\Foundation\Testing\RefreshDatabase;
10+
use Illuminate\Support\Facades\Http;
11+
use Tests\TestCase;
12+
13+
class SyncPluginReleasesTest extends TestCase
14+
{
15+
use RefreshDatabase;
16+
17+
public function test_it_updates_latest_version_on_plugin_when_new_releases_are_synced(): void
18+
{
19+
Http::fake([
20+
'api.github.com/repos/acme/test-plugin/releases*' => Http::response([
21+
[
22+
'id' => 1,
23+
'tag_name' => 'v1.0.0',
24+
'body' => 'Initial release',
25+
'target_commitish' => 'abc123',
26+
'published_at' => '2026-01-01T00:00:00Z',
27+
],
28+
[
29+
'id' => 2,
30+
'tag_name' => 'v1.1.0',
31+
'body' => 'New features',
32+
'target_commitish' => 'def456',
33+
'published_at' => '2026-02-01T00:00:00Z',
34+
],
35+
]),
36+
]);
37+
38+
$plugin = Plugin::factory()->create([
39+
'name' => 'acme/test-plugin',
40+
'repository_url' => 'https://github.com/acme/test-plugin',
41+
'latest_version' => '0.9.0',
42+
]);
43+
44+
$satisService = $this->mock(SatisService::class);
45+
46+
$job = new SyncPluginReleases($plugin, triggerSatisBuild: false);
47+
$job->handle($satisService);
48+
49+
$plugin->refresh();
50+
51+
$this->assertEquals('1.1.0', $plugin->latest_version);
52+
$this->assertCount(2, $plugin->versions);
53+
}
54+
55+
public function test_it_does_not_update_latest_version_when_no_new_releases(): void
56+
{
57+
Http::fake([
58+
'api.github.com/repos/acme/test-plugin/releases*' => Http::response([
59+
[
60+
'id' => 1,
61+
'tag_name' => 'v1.0.0',
62+
'body' => 'Initial release',
63+
'target_commitish' => 'abc123',
64+
'published_at' => '2026-01-01T00:00:00Z',
65+
],
66+
]),
67+
]);
68+
69+
$plugin = Plugin::factory()->create([
70+
'name' => 'acme/test-plugin',
71+
'repository_url' => 'https://github.com/acme/test-plugin',
72+
'latest_version' => '1.0.0',
73+
]);
74+
75+
// Pre-create the version so nothing is "new"
76+
PluginVersion::create([
77+
'plugin_id' => $plugin->id,
78+
'version' => '1.0.0',
79+
'tag_name' => 'v1.0.0',
80+
'github_release_id' => '1',
81+
'published_at' => '2026-01-01T00:00:00Z',
82+
]);
83+
84+
$satisService = $this->mock(SatisService::class);
85+
86+
$job = new SyncPluginReleases($plugin, triggerSatisBuild: false);
87+
$job->handle($satisService);
88+
89+
$plugin->refresh();
90+
91+
$this->assertEquals('1.0.0', $plugin->latest_version);
92+
}
93+
}

0 commit comments

Comments
 (0)