mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-06-28 19:46:24 +02:00
infra: Custom Update server instead of direct GitLab API calls
This reduces the amount of requests for an update from 3 if an update is needed, or 2 if not; to 1 if an update is needed, and none if an update is not. The difference comes from using this update server to check if an update is needed, and not GETing a snippet content for the release channels.
This commit is contained in:
parent
693837dca7
commit
cc5a3f12e1
4 changed files with 60 additions and 97 deletions
|
@ -1,20 +0,0 @@
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Common.Models.GitLab
|
|
||||||
{
|
|
||||||
public class GitLabReleaseAssetJsonResponse
|
|
||||||
{
|
|
||||||
[JsonPropertyName("links")]
|
|
||||||
public GitLabReleaseAssetLinkJsonResponse[] Links { get; set; }
|
|
||||||
|
|
||||||
public class GitLabReleaseAssetLinkJsonResponse
|
|
||||||
{
|
|
||||||
[JsonPropertyName("id")]
|
|
||||||
public long Id { get; set; }
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
public string AssetName { get; set; }
|
|
||||||
[JsonPropertyName("url")]
|
|
||||||
public string Url { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Common.Models.GitLab
|
|
||||||
{
|
|
||||||
public class GitLabReleasesJsonResponse
|
|
||||||
{
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("tag_name")]
|
|
||||||
public string TagName { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("assets")]
|
|
||||||
public GitLabReleaseAssetJsonResponse Assets { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonSerializable(typeof(GitLabReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
|
|
||||||
public partial class GitLabReleasesJsonSerializerContext : JsonSerializerContext;
|
|
||||||
}
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Common.Models.GitLab;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -17,7 +15,31 @@ namespace Ryujinx.Ava.Systems
|
||||||
{
|
{
|
||||||
internal static partial class Updater
|
internal static partial class Updater
|
||||||
{
|
{
|
||||||
private static GitLabReleaseChannels.ChannelType _currentGitLabReleaseChannel;
|
private static string CreateUpdateQueryUrl()
|
||||||
|
{
|
||||||
|
#pragma warning disable CS8524
|
||||||
|
var os = RunningPlatform.CurrentOS switch
|
||||||
|
#pragma warning restore CS8524
|
||||||
|
{
|
||||||
|
OperatingSystemType.MacOS => "mac",
|
||||||
|
OperatingSystemType.Linux => "linux",
|
||||||
|
OperatingSystemType.Windows => "win"
|
||||||
|
};
|
||||||
|
|
||||||
|
var arch = RunningPlatform.Architecture switch
|
||||||
|
{
|
||||||
|
Architecture.Arm64 => "arm",
|
||||||
|
Architecture.X64 => "amd64",
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (arch is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var rc = ReleaseInformation.IsCanaryBuild ? "canary" : "stable";
|
||||||
|
|
||||||
|
return $"https://update.ryujinx.app/latest/query?os={os}&arch={arch}&rc={rc}";
|
||||||
|
}
|
||||||
|
|
||||||
private static async Task<Optional<(Version Current, Version Incoming)>> CheckGitLabVersionAsync(bool showVersionUpToDate = false)
|
private static async Task<Optional<(Version Current, Version Incoming)>> CheckGitLabVersionAsync(bool showVersionUpToDate = false)
|
||||||
{
|
{
|
||||||
|
@ -35,38 +57,42 @@ namespace Ryujinx.Ava.Systems
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, "Checking for updates from https://git.ryujinx.app.");
|
if (CreateUpdateQueryUrl() is not {} updateUrl)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, "Could not determine URL for updates.");
|
||||||
|
|
||||||
|
_running = false;
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"Checking for updates from {updateUrl}.");
|
||||||
|
|
||||||
// Get latest version number from GitLab API
|
// Get latest version number from GitLab API
|
||||||
using HttpClient jsonClient = ConstructHttpClient();
|
using HttpClient jsonClient = ConstructHttpClient();
|
||||||
|
|
||||||
// GitLab instance is located in Ukraine. Connection times will vary across the world.
|
// GitLab instance is located in Ukraine. Connection times will vary across the world.
|
||||||
jsonClient.Timeout = TimeSpan.FromSeconds(10);
|
jsonClient.Timeout = TimeSpan.FromSeconds(10);
|
||||||
|
|
||||||
if (_currentGitLabReleaseChannel == null)
|
try
|
||||||
{
|
{
|
||||||
GitLabReleaseChannels releaseChannels = await GitLabReleaseChannels.GetAsync(jsonClient);
|
UpdaterResponse response =
|
||||||
|
await jsonClient.GetFromJsonAsync(updateUrl, UpdaterResponseJsonContext.Default.UpdaterResponse);
|
||||||
|
|
||||||
_currentGitLabReleaseChannel = ReleaseInformation.IsCanaryBuild
|
_buildVer = response.Tag;
|
||||||
? releaseChannels.Canary
|
_buildUrl = response.DownloadUrl;
|
||||||
: releaseChannels.Stable;
|
_changelogUrlFormat = response.ReleaseUrlFormat;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"An error occurred when parsing JSON response from API ({e.GetType().AsFullNamePrettyString()}): {e.Message}");
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"Loaded GitLab release channel for '{(ReleaseInformation.IsCanaryBuild ? "canary" : "stable")}'");
|
_running = false;
|
||||||
|
return default;
|
||||||
_changelogUrlFormat = _currentGitLabReleaseChannel.UrlFormat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string fetchedJson = await jsonClient.GetStringAsync(_currentGitLabReleaseChannel.GetLatestReleaseApiUrl());
|
|
||||||
GitLabReleasesJsonResponse fetched = JsonHelper.Deserialize(fetchedJson, _glSerializerContext.GitLabReleasesJsonResponse);
|
|
||||||
|
|
||||||
_buildVer = fetched.TagName;
|
|
||||||
_buildUrl = fetched.Assets.Links
|
|
||||||
.FirstOrDefault(link =>
|
|
||||||
link.AssetName.StartsWith("ryujinx") && link.AssetName.EndsWith(_platformExt)
|
|
||||||
)?.Url;
|
|
||||||
|
|
||||||
// If build URL not found, assume no new update is available.
|
// If build URL not found, assume no new update is available.
|
||||||
if (_buildUrl is null)
|
if (_buildUrl is null or "")
|
||||||
{
|
{
|
||||||
if (showVersionUpToDate)
|
if (showVersionUpToDate)
|
||||||
{
|
{
|
||||||
|
@ -104,35 +130,17 @@ namespace Ryujinx.Ava.Systems
|
||||||
|
|
||||||
return (currentVersion, newVersion);
|
return (currentVersion, newVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(UpdaterResponse))]
|
||||||
|
partial class UpdaterResponseJsonContext : JsonSerializerContext;
|
||||||
|
|
||||||
[JsonSerializable(typeof(GitLabReleaseChannels))]
|
public class UpdaterResponse
|
||||||
partial class GitLabReleaseChannelPairContext : JsonSerializerContext;
|
|
||||||
|
|
||||||
public class GitLabReleaseChannels
|
|
||||||
{
|
{
|
||||||
public static async Task<GitLabReleaseChannels> GetAsync(HttpClient httpClient)
|
[JsonPropertyName("tag")] public string Tag { get; set; }
|
||||||
=> await httpClient.GetFromJsonAsync(
|
[JsonPropertyName("download_url")] public string DownloadUrl { get; set; }
|
||||||
"https://git.ryujinx.app/ryubing/ryujinx/-/snippets/1/raw/main/meta.json",
|
[JsonPropertyName("web_url")] public string ReleaseUrl { get; set; }
|
||||||
GitLabReleaseChannelPairContext.Default.GitLabReleaseChannels);
|
|
||||||
|
|
||||||
[JsonPropertyName("stable")] public ChannelType Stable { get; set; }
|
[JsonIgnore] public string ReleaseUrlFormat => ReleaseUrl.Replace(Tag, "{0}");
|
||||||
[JsonPropertyName("canary")] public ChannelType Canary { get; set; }
|
|
||||||
|
|
||||||
public class ChannelType
|
|
||||||
{
|
|
||||||
[JsonPropertyName("id")] public long Id { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("group")] public string Group { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("project")] public string Project { get; set; }
|
|
||||||
|
|
||||||
public string UrlFormat => $"https://git.ryujinx.app/{ToString()}/-/releases/{{0}}";
|
|
||||||
|
|
||||||
public override string ToString() => $"{Group}/{Project}";
|
|
||||||
|
|
||||||
public string GetLatestReleaseApiUrl() =>
|
|
||||||
$"https://git.ryujinx.app/api/v4/projects/{Id}/releases/permalink/latest";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ using ICSharpCode.SharpZipLib.Tar;
|
||||||
using ICSharpCode.SharpZipLib.Zip;
|
using ICSharpCode.SharpZipLib.Zip;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Common.Models.Github;
|
using Ryujinx.Ava.Common.Models.Github;
|
||||||
using Ryujinx.Ava.Common.Models.GitLab;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
|
@ -33,19 +32,14 @@ namespace Ryujinx.Ava.Systems
|
||||||
internal static partial class Updater
|
internal static partial class Updater
|
||||||
{
|
{
|
||||||
private static readonly GithubReleasesJsonSerializerContext _ghSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly GithubReleasesJsonSerializerContext _ghSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
private static readonly GitLabReleasesJsonSerializerContext _glSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
|
||||||
|
|
||||||
|
|
||||||
|
private static readonly string _platformExt = BuildPlatformExtension();
|
||||||
private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory;
|
private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
||||||
private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish");
|
private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish");
|
||||||
private const int ConnectionCount = 4;
|
private const int ConnectionCount = 4;
|
||||||
|
|
||||||
private static string _buildVer;
|
private static string _buildVer;
|
||||||
|
|
||||||
|
|
||||||
private static readonly string _platformExt = BuildPlatformExtension();
|
|
||||||
|
|
||||||
private static string _buildUrl;
|
private static string _buildUrl;
|
||||||
private static long _buildSize;
|
private static long _buildSize;
|
||||||
private static bool _updateSuccessful;
|
private static bool _updateSuccessful;
|
||||||
|
@ -168,7 +162,7 @@ namespace Ryujinx.Ava.Systems
|
||||||
HttpClient result = new();
|
HttpClient result = new();
|
||||||
|
|
||||||
// Required by GitHub to interact with APIs.
|
// Required by GitHub to interact with APIs.
|
||||||
result.DefaultRequestHeaders.Add("User-Agent", "Ryujinx-Updater/1.0.0");
|
result.DefaultRequestHeaders.Add("User-Agent", $"Ryujinx-Updater/{ReleaseInformation.Version}");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue