Skip to content

Commit 252c64d

Browse files
committed
feature: Version Pinning
Allows the ability to specify in the appsettings.json what OS & architectures to limit to getting a specific latest version. This will be used when we remove Intel Mac support from Ryubing, to prevent people who don't update during the 1.3.4 update cycle getting an ARM-only build.
1 parent c0e5728 commit 252c64d

7 files changed

Lines changed: 142 additions & 56 deletions

File tree

src/Server/Controllers/Api/v1/VersionController.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ public async Task<ActionResult<VersionResponse>> GetLatestStable(
1818
[FromQuery] string? arch = null
1919
)
2020
{
21-
if (await vcache.GetReleaseAsync(c => c.Latest) is not {} latest)
22-
return NotFound();
23-
2421
if (!os.TryParseAsSupportedPlatform(out var supportedPlatform))
2522
return BadRequest($"Unknown platform '{os}'");
2623

2724
if (!arch.TryParseAsSupportedArchitecture(out var supportedArch))
2825
return BadRequest($"Unknown architecture '{arch}'");
2926

27+
if (await vcache.GetReleaseAsync(c => c.GetLatest(supportedPlatform, supportedArch)) is not {} latest)
28+
return NotFound();
29+
3030
return Ok(new VersionResponse
3131
{
3232
Version = latest.Tag,
@@ -45,14 +45,14 @@ public async Task<ActionResult<VersionResponse>> GetLatestCanary(
4545
[FromQuery] string? arch = null
4646
)
4747
{
48-
if (await vcache.GetReleaseAsync(c => c.Latest) is not { } latest)
49-
return NotFound();
50-
5148
if (!os.TryParseAsSupportedPlatform(out var supportedPlatform))
5249
return BadRequest($"Unknown platform '{os}'");
5350

5451
if (!arch.TryParseAsSupportedArchitecture(out var supportedArch))
5552
return BadRequest($"Unknown architecture '{arch}'");
53+
54+
if (await vcache.GetReleaseAsync(c => c.GetLatest(supportedPlatform, supportedArch)) is not { } latest)
55+
return NotFound();
5656

5757
return Ok(new VersionResponse
5858
{

src/Server/Controllers/DownloadController.cs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,53 +17,54 @@ public async Task<ActionResult> DownloadCustom(
1717
[FromQuery] string arch,
1818
[FromQuery] string rc = Constants.StableRoute,
1919
[FromQuery] string version = Constants.RouteName_Latest
20-
)
20+
)
2121
{
2222
if (os == string.Empty)
2323
return BadRequest("os was empty.");
24-
24+
2525
if (arch == string.Empty)
2626
return BadRequest("arch was empty.");
2727

2828
if (rc == string.Empty)
2929
return BadRequest("rc was empty.");
30-
30+
3131
if (!os.TryParseAsSupportedPlatform(out var supportedPlatform))
3232
return BadRequest($"Unknown platform '{os}'");
33-
33+
3434
if (!arch.TryParseAsSupportedArchitecture(out var supportedArch))
3535
return BadRequest($"Unknown architecture '{arch}'");
36-
36+
3737
if (!rc.TryParseAsReleaseChannel(out var releaseChannel))
38-
return BadRequest($"Unknown release channel '{rc}'; valid are '{Constants.StableRoute}' and '{Constants.CanaryRoute}'");
39-
38+
return BadRequest(
39+
$"Unknown release channel '{rc}'; valid are '{Constants.StableRoute}' and '{Constants.CanaryRoute}'");
40+
4041
var release = await HttpContext.RequestServices
4142
.GetCacheFor(releaseChannel)
42-
.GetReleaseAsync(c =>
43-
version is Constants.RouteName_Latest ? c.Latest : c[version]
43+
.GetReleaseAsync(c =>
44+
version is Constants.RouteName_Latest ? c.GetLatest(supportedPlatform, supportedArch) : c[version]
4445
);
45-
46+
4647
if (release is null)
4748
return NotFound();
48-
49+
4950
return Redirect(release.GetUrlFor(supportedPlatform, supportedArch));
5051
}
51-
52+
5253
[HttpGet]
5354
[HttpGet(Constants.StableRoute)]
5455
[ProducesResponseType(StatusCodes.Status302Found)]
5556
[ProducesResponseType(StatusCodes.Status404NotFound)]
5657
public async Task<ActionResult> DownloadLatestStable(
57-
[FromKeyedServices("stableCache")] VersionCache vcache,
58+
[FromKeyedServices("stableCache")] VersionCache vcache,
5859
[FromServices] ILogger<DownloadController> logger
5960
)
6061
{
61-
if (await vcache.GetReleaseAsync(c => c.Latest) is not {} latest)
62+
if (await vcache.GetReleaseAsync(c => c.Latest) is not { } latest)
6263
return NotFound();
63-
64+
6465
return RedirectOrProblem(latest, logger, HttpContext.Request.Headers.UserAgent.ToString());
6566
}
66-
67+
6768
[HttpGet(Constants.CanaryRoute)]
6869
[ProducesResponseType(StatusCodes.Status302Found)]
6970
[ProducesResponseType(StatusCodes.Status404NotFound)]
@@ -72,26 +73,29 @@ public async Task<ActionResult> DownloadLatestCanary(
7273
[FromServices] ILogger<DownloadController> logger
7374
)
7475
{
75-
if (await vcache.GetReleaseAsync(c => c.Latest) is not {} latest)
76+
if (await vcache.GetReleaseAsync(c => c.Latest) is not { } latest)
7677
return NotFound();
77-
78+
7879
return RedirectOrProblem(latest, logger, HttpContext.Request.Headers.UserAgent.ToString());
7980
}
80-
81-
private ActionResult RedirectOrProblem(VersionCacheEntry cacheEntry, ILogger<DownloadController> logger, string userAgent)
81+
82+
private ActionResult RedirectOrProblem(VersionCacheEntry cacheEntry, ILogger<DownloadController> logger,
83+
string userAgent)
8284
{
8385
var (platform, arch) = VersionCacheEntry.GetVersionTupleForUserAgent(userAgent);
84-
86+
8587
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
8688
// I was still getting occasional errors for passing null into a Redirect, so idk
8789
if (cacheEntry.GetUrlFor(platform, arch) is not { } url)
8890
{
89-
logger.LogError(new EventId(1), "Requested download URL was null: Version: {ver}; User-Agent: '{userAgent}'", cacheEntry.Tag, userAgent);
90-
91+
logger.LogError(new EventId(1),
92+
"Requested download URL was null: Version: {ver}; User-Agent: '{userAgent}'", cacheEntry.Tag,
93+
userAgent);
94+
9195
return Problem(statusCode: 500,
9296
detail: $"The requested download's url was null. Version: {cacheEntry.Tag}; User-Agent: '{userAgent}'");
9397
}
94-
98+
9599
return Redirect(url);
96100
}
97101
}

src/Server/Controllers/LatestController.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,26 @@ public async Task<ActionResult<VersionResponse>> GetLatestCustom(
2020
{
2121
if (os == string.Empty)
2222
return BadRequest("os was empty.");
23-
23+
2424
if (arch == string.Empty)
2525
return BadRequest("arch was empty.");
2626

2727
if (rc == string.Empty)
2828
return BadRequest("rc was empty.");
29-
29+
3030
if (!os.TryParseAsSupportedPlatform(out var supportedPlatform))
3131
return BadRequest($"Unknown platform '{os}'");
3232

3333
if (!arch.TryParseAsSupportedArchitecture(out var supportedArch))
3434
return BadRequest($"Unknown architecture '{arch}'");
35-
35+
3636
if (!rc.TryParseAsReleaseChannel(out var releaseChannel))
3737
return BadRequest(
3838
$"Unknown release channel '{rc}'; valid are '{Constants.StableRoute}' and '{Constants.CanaryRoute}'");
3939

4040
var vcache = HttpContext.RequestServices.GetCacheFor(releaseChannel);
41-
42-
if (await vcache.GetReleaseAsync(c => c.Latest) is not { } latest)
41+
42+
if (await vcache.GetReleaseAsync(c => c.GetLatest(supportedPlatform, supportedArch)) is not { } latest)
4343
return NotFound();
4444

4545
return Ok(new VersionResponse
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using Gommon;
2+
using Ryujinx.Systems.Update.Common;
3+
4+
namespace Ryujinx.Systems.Update.Server.Services.GitLab;
5+
6+
public class PinnedVersions : SafeDictionary<SupportedPlatform, SafeDictionary<SupportedArchitecture, string>>
7+
{
8+
public PinnedVersions(VersionCache vcache, IConfigurationSection configSection)
9+
{
10+
foreach (var subSection in configSection.GetChildren())
11+
{
12+
if (!subSection.Key.TryParseAsSupportedPlatform(out var platform))
13+
{
14+
vcache.Logger.LogWarning("Unknown platform '{key}'; skipping", subSection.Key);
15+
continue;
16+
}
17+
18+
SafeDictionary<SupportedArchitecture, string> versions = [];
19+
foreach (var archVersionPair in subSection.GetChildren())
20+
{
21+
if (!archVersionPair.Key.TryParseAsSupportedArchitecture(out SupportedArchitecture arch))
22+
{
23+
vcache.Logger.LogWarning("Unknown platform '{key}' in '{subsectionName}'; skipping", archVersionPair.Key, subSection.Key);
24+
continue;
25+
}
26+
27+
if (archVersionPair.Value == null)
28+
{
29+
vcache.Logger.LogWarning("Version pair value for '{key}' in '{subsectionName}' was null; skipping", archVersionPair.Key, subSection.Key);
30+
continue;
31+
}
32+
33+
versions[arch] = archVersionPair.Value;
34+
}
35+
36+
this[platform] = versions;
37+
}
38+
}
39+
40+
public string? Find(SupportedPlatform plat, SupportedArchitecture arch)
41+
=> this[plat]?[arch];
42+
}

0 commit comments

Comments
 (0)