GenerateToolingFeed/Helper.cs (170 lines of code) (raw):

using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Net.Http; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NuGet.Versioning; namespace GenerateToolingFeed { public class Helper { public static System.Net.Http.HttpClient HttpClient => _lazyClient.Value; public static string newReleaseVersion = string.Empty; public static bool ShouldBeMinified(V4FormatCliEntry cliEntry) { return !string.IsNullOrEmpty(cliEntry.size) && string.Equals(cliEntry.size, "minified", StringComparison.OrdinalIgnoreCase); } public static string GetNewReleaseVersion(JToken jToken, int majorReleaseVersion) { if (!string.IsNullOrEmpty(newReleaseVersion)) { return newReleaseVersion; } List<String> versions = new List<string>(); foreach (JProperty item in jToken) { string name = item.Name.Split("-").First(); if (name.StartsWith($"{majorReleaseVersion}.")) { versions.Add(item.Name); } } if (!versions.Any()) { return null; } var nuGetVersions = versions.Select(p => { Version.TryParse(p, out Version version); return version; }).Where(v => v != null); var maxVersion = nuGetVersions.OrderByDescending(p => p).FirstOrDefault(); Version releaseVersion = new Version(maxVersion.Major, maxVersion.Minor + 1, 0); newReleaseVersion = releaseVersion.ToString(); return newReleaseVersion; } public static string GetShaFileContent(string os, string architecture, string cliVersion, string filePath, bool isMinified = false, string linkSuffix = "") { string rid = GetRuntimeIdentifier(isMinified, os, architecture); string fileName = $"Azure.Functions.Cli.{rid}{linkSuffix}.{cliVersion}.zip.sha2"; string path = Path.Combine(filePath, fileName); return File.ReadAllText(path); } public static string GetLatestPackageVersion(string packageId, int cliMajor) { string url = $"https://api.nuget.org/v3-flatcontainer/{packageId.ToLower()}/index.json"; var response = HttpClient.GetStringAsync(url).Result; var versionsObject = JObject.Parse(response); var versions = JsonConvert.DeserializeObject<IEnumerable<string>>(versionsObject["versions"].ToString()); var nuGetVersions = versions.Select(p => { if (NuGetVersion.TryParse(p, out NuGetVersion nuGetVersion) && nuGetVersion.Major == cliMajor) { return nuGetVersion; } return null; }).Where(v => v != null); return nuGetVersions.OrderByDescending(p => p.Version).FirstOrDefault()?.ToString(); } public static string GetTemplateUrl(string packageId, int cliMajor) { string version = GetLatestPackageVersion(packageId, cliMajor); return $"https://www.nuget.org/api/v2/package/{packageId}/{version}"; } public static string GetRuntimeIdentifier(bool isMinified, string os, string architecture) { string rid = string.Empty; if (isMinified) { rid = "min."; } os = os.ToLower(); if (Constants.OperatingSystem.TryGetValue(os, out string osValue)) { rid = rid + osValue; } else { throw new Exception($"Could not find matching value for {os} to generate rid"); } if (Constants.Architecture.TryGetValue(architecture, out string architectureValue)) { rid = rid + "-" + architectureValue; } else { throw new Exception($"Could not find matching value for {architecture} to generate rid"); } return rid; } public static void MergeObjectToJToken(JObject source, object toMerge) { // Clone source for iterating. That way we can modify acutal source in place JObject cloneSource = source.DeepClone() as JObject; foreach (var jsonItem in cloneSource) { string tokenName = jsonItem.Key; JToken tokenValue = jsonItem.Value; foreach (var prop in toMerge.GetType().GetProperties()) { if (string.Equals(tokenName, prop.Name, StringComparison.OrdinalIgnoreCase)) { source[tokenName] = JToken.FromObject(prop.GetValue(toMerge)); break; } } } } public static bool IsValidDownloadLink(string url) { var result = HttpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).Result; return !(result.StatusCode == HttpStatusCode.NotFound || !result.IsSuccessStatusCode); } private static Lazy<System.Net.Http.HttpClient> _lazyClient = new Lazy<System.Net.Http.HttpClient>(() => { return new System.Net.Http.HttpClient(new HttpClientHandler { MaxConnectionsPerServer = 50 }); }); public static string GetReleaseVersionFromTag(JObject json, string tag) { var releaseVersion = json?["tags"]?[tag]?["release"].ToString(); return releaseVersion; } public static List<string> GetTagsFromMajorVersion(int majorVersion) => majorVersion switch { 2 => ["v2"], 3 => ["v3"], 4 => ["v4", "v0"], _ => throw new ArgumentNullException($"{majorVersion} is not a supported version.", nameof(majorVersion)) }; public static string GetCliVersion(string path) { string cliVersion = string.Empty; Console.WriteLine($"Searching for core tools builds in {path}..."); foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories)) { if (file.EndsWith(".zip")) { var zip = ZipFile.OpenRead(file); foreach (var entry in zip.Entries) { if (entry.Name == "func.dll") { ZipFileExtensions.ExtractToFile(entry, "func.dll", true); cliVersion = FileVersionInfo.GetVersionInfo(".\\func.dll").FileVersion; break; } } } } return cliVersion; } } }