private static async Task <UpdateResult> CrawlReleases(ILogger log, CancellationToken ct) { var config = new ConfigurationBuilder() .AddJsonFile("host.json", optional: true, reloadOnChange: true) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); var status = "starting"; using (var hc = new HealthchecksApi(config, log, "crawler")) using (var videoLan = new VideoLanApi()) using (var azure = new AzureDevOpsApi(config["azure-auth"])) { try { status = "reporting start to healthchecks"; await hc.Start(ct); status = "searching latest available version"; var(version, url) = await videoLan.GetLatestVersion(ct); status = "loading azure config"; var variables = await azure.GetBuildVariables(ct); if (variables.TryUpdate("latest.version", version)) { variables.TryUpdate("latest.url", url); status = "updating azure config"; await azure.UpdateBuildVariables(variables, ct); status = "queuing new build"; await azure.QueueBuild(ct); status = "reporting success to healthchecks"; await hc.Report(ct); return(UpdateResult.Succeeded()); } else { status = "reporting success (not changed) to healthchecks"; await hc.Report(ct); return(UpdateResult.NotChanged()); } } catch (Exception e) { await hc.Failed(ct); // cannot fail return(UpdateResult.Failed(status, e)); } } }
private static async Task <UpdateResult[]> CrawlReleases(string[] channels, ILogger log, CancellationToken ct) { var config = new ConfigurationBuilder() .AddJsonFile("host.json", optional: true, reloadOnChange: true) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); using (var hc = new HealthchecksApi(config, log)) using (var gitHub = new GitHubApi()) using (var azure = new AzureDevOpsApi(config["azureDevOpsAuth"])) { var releases = await gitHub.GetDuplicatiReleases(ct); var variables = await azure.GetBuildVariables(ct); var @default = variables["default"]; return(await Task.WhenAll(channels.Select(TryUpdateChannel))); async Task <UpdateResult> TryUpdateChannel(string channel) { var status = "parsing inputs"; try { status = "searching release"; if (!releases.TryGetValue(channel, out var release)) { throw new Exception($"Cannot find release for {channel}"); } status = "reporting start to healthchecks"; await hc.Start(channel, ct); // we report to HC only if we found a release. This prevent issue with the still awaited "stable" version :) status = "searching variable group"; if (!variables.TryGetValue(channel, out var group)) { throw new Exception($"Cannot find build variables for {channel}"); } status = "analyzing build config vs. found release"; var install = release.data.Assets.FirstOrDefault(a => a.Url.EndsWith(release.version + ".zip", StringComparison.OrdinalIgnoreCase))?.Url; var version = release.version; if (install.IsNullOrWhiteSpace() || version.IsNullOrWhiteSpace()) { throw new Exception($"The found release is invalid for {channel} (Failed to get required values 'install' and 'version')"); } var hasChanged = false; hasChanged |= group.TryUpdate("install", install); hasChanged |= group.TryUpdate("version", version); hasChanged |= group.TryUpdate("url", release.data.Url); hasChanged |= group.TryUpdate("notes", release.data.Notes); if (hasChanged) { status = "updating build variables"; await azure.UpdateBuildVariables(group, ct); if (@default["channel"] == channel) { status = "updating **default** build variables"; @default.TryUpdate("install", install); @default.TryUpdate("version", version); @default.TryUpdate("url", release.data.Url); @default.TryUpdate("notes", release.data.Notes); await azure.UpdateBuildVariables(@default, ct); status = "queuing new **default** build"; await azure.QueueBuild("default", ct); // So the image is tagged as 'latest' } else { status = "queuing new build"; await azure.QueueBuild(channel, ct); } status = "reporting success to healthchecks"; await hc.Report(channel, ct); return(UpdateResult.Succeeded(channel)); } else { status = "reporting success (not changed) to healthchecks"; await hc.Report(channel, ct); return(UpdateResult.NotChanged(channel)); } } catch (Exception e) { await hc.Failed(channel, ct); // cannot fail return(UpdateResult.Failed(channel, status, e)); } } } }