diff --git a/.github/workflows/create-release-candidate.yml b/.github/workflows/create-release-candidate.yml index 91b25c0..6f7228e 100644 --- a/.github/workflows/create-release-candidate.yml +++ b/.github/workflows/create-release-candidate.yml @@ -17,13 +17,18 @@ jobs: outputs: spdx-version: ${{ steps.get-latest.outputs.version }} + spdx-tag: ${{ steps.get-latest.outputs.tag }} steps: - name: Get latest release id: get-latest run: | $latestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/spdx/license-list-data/releases/latest" + $tagName = $latestRelease.tag_name + Write-Host "Using tag: $tagName" + "tag=$tagName" | Out-File -FilePath $env:GITHUB_OUTPUT -Append + $tagVersion = $tagName -Replace "^v" Write-Host "Using version: $tagVersion" "version=$tagVersion" | Out-File -FilePath $env:GITHUB_OUTPUT -Append @@ -48,7 +53,7 @@ jobs: dotnet-version: 8.0.x - name: Run Generator - run: dotnet run --project Generator/Generator.csproj + run: dotnet run --project Generator/Generator.csproj -- ${{ needs.get-spdx-version.outputs.spdx-tag }} - name: Build LicenseIdentifiers run: dotnet build LicenseIdentifiers/LicenseIdentifiers.csproj diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index e10a9e1..fa56889 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -28,7 +28,7 @@ jobs: run: dotnet build LicenseIdentifiers/LicenseIdentifiers.csproj -c Release - name: Pack LicenseIdentifiers - run: dotnet pack LicenseIdentifiers/LicenseIdentifiers.csproj -c Release -p:NuspecFile="LicenseIdentifiers.nuspec" + run: dotnet pack LicenseIdentifiers/LicenseIdentifiers.csproj -c Release -p:NuspecFile="LicenseIdentifiers.generated.nuspec" - name: Publish Artifact uses: actions/upload-artifact@v4 diff --git a/Generator/CsprojGenerator.cs b/Generator/CsprojGenerator.cs deleted file mode 100644 index 247f8b2..0000000 --- a/Generator/CsprojGenerator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Generator -{ - public class CsprojGenerator - { - public static string GenerateContent(string version) - { - return @$" - - - net8.0 - {version} - -"; - } - } -} diff --git a/Generator/DTO/Release.cs b/Generator/DTO/Release.cs deleted file mode 100644 index 440b99a..0000000 --- a/Generator/DTO/Release.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -namespace Generator.DTO -{ - public class Release - { - [JsonPropertyName("tag_name")] - public string TagName { get; set; } - - [JsonPropertyName("body")] - public string ReleaseDescription { get; set; } - } -} diff --git a/Generator/LicenseIdentifierFileComponents.cs b/Generator/LicenseIdentifierFileComponents.cs index 7a99251..7c0466c 100644 --- a/Generator/LicenseIdentifierFileComponents.cs +++ b/Generator/LicenseIdentifierFileComponents.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Generator +namespace Generator { public static class LicenseIdentifierFileComponents { diff --git a/Generator/NuspecGenerator.cs b/Generator/NuspecGenerator.cs index d8f4009..4eb34c2 100644 --- a/Generator/NuspecGenerator.cs +++ b/Generator/NuspecGenerator.cs @@ -1,32 +1,88 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Xml.Schema; +using System.Xml.Serialization; namespace Generator { public class NuspecGenerator { - public static string GenerateContent(string version, string releaseDescription) + public static void GenerateFile(string path, string version, string tag) { - return @$" - - - LicenseIdentifiers - {version} - TobyAndToby - true - ISC - http://github.com/TobyAndToby/License-Identifiers - SPDX-compliant license enum class. Validate and parse all verified SPDX license identifiers from SPDX version {version}. - {releaseDescription} - license,licence,SPDX,OSS,parse - - - - -"; + var package = new Package + { + Metadata = new Metadata + { + Id = "LicenseIdentifiers", + Authors = "TobyAndToby", + Version = version, + Tags = "license licence SPDX OSS parse", + License = new LicenseXml + { + Type = "expression", + Text = "ISC" + }, + Repository = new Repository + { + Url = "https://github.com/TobyAndToby/License-Identifiers", + }, + ReleaseNotes = $"https://github.com/spdx/license-list-data/releases/tag/{tag}", + Description = $"SPDX-compliant license enum class. Validate and parse all verified SPDX license identifiers from SPDX version {version}." + } + }; + + var xmlSerializer = new XmlSerializer(typeof(Package)); + var streamWriter = new StreamWriter(path); + + xmlSerializer.Serialize(streamWriter, package); + streamWriter.Close(); } } + + [XmlRoot("package")] + public class Package + { + [XmlElement("metadata")] + public Metadata Metadata { get; init; } + } + + public class Metadata + { + [XmlElement("id")] + public string Id { get; init; } + + [XmlElement("version")] + public string Version { get; init; } + + [XmlElement("authors")] + public string Authors { get; init; } + + [XmlElement("license")] + public LicenseXml License { get; init; } + + [XmlElement("repository")] + public Repository Repository { get; init; } + + [XmlElement("tags")] + public string Tags { get; init; } + + [XmlElement("description")] + public string Description { get; init; } + + [XmlElement("releaseNotes")] + public string ReleaseNotes { get; init; } + } + + public class LicenseXml + { + [XmlAttribute("type")] + public string Type { get; init; } + + [XmlText] + public string Text { get; init; } + } + + public class Repository + { + [XmlAttribute("url")] + public string Url { get; init; } + } } diff --git a/Generator/Program.cs b/Generator/Program.cs index ff68209..c9c91e4 100644 --- a/Generator/Program.cs +++ b/Generator/Program.cs @@ -1,38 +1,41 @@ -using Generator.DTO; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; +using System.Diagnostics.CodeAnalysis; using System.Net.Http.Headers; +using System.Net.Http.Json; using System.Reflection; -using System.Threading.Tasks; namespace Generator { class Program { - private const string SPDX_RELEASES_URI = "https://api.github.com/repos/spdx/license-list-data/releases"; private static readonly string LICENSES_OUTPUT_LOCATION = GetProjectFolderPath() + LicenseIdentifierFileComponents.NAME; - private static readonly string NUSPEC_OUTPUT_LOCATION = GetProjectFolderPath() + "LicenseIdentifiers.nuspec"; + private static readonly string NUSPEC_OUTPUT_LOCATION = GetProjectFolderPath() + "LicenseIdentifiers.generated.nuspec"; - private static readonly HttpClient client = new HttpClient(); + private static readonly HttpClient client = new(); static async Task Main(string[] args) { + if (!TryParseTagName(args, out var tag)) + { + throw new ArgumentException("Please provide a valid tag name."); + } + + var spdxJsonUrl = $"https://raw.githubusercontent.com/spdx/license-list-data/{tag}/json/licenses.json"; + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Add("User-Agent", "License-Identifiers"); - var spdxReleaseMetadata = await GetLatestSpdxReleaseMetadata(); - var spdxRelease = await GetSpdxRelease(spdxReleaseMetadata.TagName); - GenerateLicensesClass(spdxRelease.Licenses, LICENSES_OUTPUT_LOCATION); + var licensesMetadata = await client.GetFromJsonAsync(spdxJsonUrl); + + if (licensesMetadata == null) + { + throw new InvalidOperationException("Failed to retrieve licenses."); + } - var versionOverride = args.Length > 0 ? args[0] : null; - var version = GetVersion(spdxReleaseMetadata, versionOverride); + GenerateLicensesClass(licensesMetadata.Licenses, LICENSES_OUTPUT_LOCATION); - await UpdateNuspecFile(spdxReleaseMetadata.ReleaseDescription, version); + var version = GetVersion(tag); - Console.WriteLine("Done!"); + NuspecGenerator.GenerateFile(NUSPEC_OUTPUT_LOCATION, version, tag); } private static void GenerateLicensesClass(List licenses, string destination) @@ -62,55 +65,32 @@ private static void GenerateLicensesClass(List licenses, string destina outputFile.Write(LicenseIdentifierFileComponents.FOOTER); } - private static async Task GetLatestSpdxReleaseMetadata() + private static string GetVersion(string tag) { - var spdxReleases = await client.GetStringAsync(SPDX_RELEASES_URI); - var releases = Utils.ParseJson>(spdxReleases); - - if (releases == null || !releases.Any()) + if (!tag.StartsWith('v')) { - throw new Exception("No SPDX releases found."); + return tag; } - return releases.FirstOrDefault(); + return tag[1..]; } - private static async Task GetSpdxRelease(string releaseTagName) - { - var licensesUri = $"https://github.com/spdx/license-list-data/archive/{releaseTagName}.zip"; - var spdxLicenses = await client.GetAsync(licensesUri); - - var zipName = spdxLicenses.Content.Headers.ContentDisposition.FileName; - var folderName = Path.GetFileNameWithoutExtension(zipName); - - var spdxLicensesContent = Utils.GetFileContentsFromZip( - await spdxLicenses.Content.ReadAsStreamAsync(), - $"{folderName}/json/licenses.json"); - - return Utils.ParseJson(spdxLicensesContent); - } - - private static async Task UpdateNuspecFile(string releaseDescription, string version) + public static string GetProjectFolderPath() { - var nuspecContents = NuspecGenerator.GenerateContent(version, releaseDescription); - await File.WriteAllTextAsync(NUSPEC_OUTPUT_LOCATION, nuspecContents); + var location = new Uri(Assembly.GetEntryAssembly().GetName().CodeBase); + return new FileInfo(location.AbsolutePath).Directory.FullName + "/../../../../LicenseIdentifiers/"; } - private static string GetVersion(Release releaseMetadata, string versionOverride) + private static bool TryParseTagName(string[] args, [NotNullWhen(true)] out string? tag) { - var version = string.IsNullOrEmpty(versionOverride) ? releaseMetadata.TagName : versionOverride; - if (version.StartsWith('v')) + if (args.Length < 1) { - version = version[1..]; + tag = null; + return false; } - return version; - } - - public static string GetProjectFolderPath() - { - var location = new Uri(Assembly.GetEntryAssembly().GetName().CodeBase); - return new FileInfo(location.AbsolutePath).Directory.FullName + "/../../../../LicenseIdentifiers/"; + tag = args[0]; + return !string.IsNullOrWhiteSpace(tag); } } } diff --git a/Generator/Utils.cs b/Generator/Utils.cs index 3e92f47..4b0b59a 100644 --- a/Generator/Utils.cs +++ b/Generator/Utils.cs @@ -14,28 +14,6 @@ public static class Utils private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; private static readonly Regex IllegalCharacters = new Regex("[^a-zA-Z0-9_]"); - /// - /// Given a JSON file location, read and parse into specified generic type. Logs exceptions. - /// - /// - /// - /// - public static T ParseJson(string raw) where T : new() - { - var data = new T(); - - try - { - data = JsonSerializer.Deserialize(raw, JsonOptions); - } - catch (Exception e) - { - Console.WriteLine(e.ToString()); - } - - return data; - } - /// /// Takes a license ID and formats it to be a valid C# variable name. /// gpl-1.0+ -> GPL_1_0_PLUS @@ -66,26 +44,5 @@ public static string SpreadArrayValues(IEnumerable source) { return string.Join(',', source.Select(value => $"\"{value}\"")); } - - public static string GetFileContentsFromZip(Stream data, string targetFilePath) - { - using var zipArchive = new ZipArchive(data, ZipArchiveMode.Read); - - foreach (var entry in zipArchive.Entries) - { - if (entry.FullName != targetFilePath) - { - continue; - } - - using var stream = entry.Open(); - using var memoryStream = new MemoryStream(); - stream.CopyTo(memoryStream); - - return Encoding.UTF8.GetString(memoryStream.ToArray()); - } - - return null; - } } } diff --git a/LicenseIdentifiers/LicenseIdentifiers.csproj b/LicenseIdentifiers/LicenseIdentifiers.csproj index a85b670..5704b21 100644 --- a/LicenseIdentifiers/LicenseIdentifiers.csproj +++ b/LicenseIdentifiers/LicenseIdentifiers.csproj @@ -1,8 +1,6 @@ - netstandard2.0 12 - 1.0.0 diff --git a/LicenseIdentifiers/LicenseIdentifiers.generated.nuspec b/LicenseIdentifiers/LicenseIdentifiers.generated.nuspec new file mode 100644 index 0000000..913aebd --- /dev/null +++ b/LicenseIdentifiers/LicenseIdentifiers.generated.nuspec @@ -0,0 +1,13 @@ + + + + LicenseIdentifiers + 3.23 + TobyAndToby + ISC + + license licence SPDX OSS parse + SPDX-compliant license enum class. Validate and parse all verified SPDX license identifiers from SPDX version 3.23. + https://github.com/spdx/license-list-data/releases/tag/v3.23 + + \ No newline at end of file diff --git a/LicenseIdentifiers/LicenseIdentifiers.nuspec b/LicenseIdentifiers/LicenseIdentifiers.nuspec deleted file mode 100644 index 9ca6f4d..0000000 --- a/LicenseIdentifiers/LicenseIdentifiers.nuspec +++ /dev/null @@ -1,19 +0,0 @@ - - - - LicenseIdentifiers - 3.23 - TobyAndToby - true - ISC - http://github.com/TobyAndToby/License-Identifiers - SPDX-compliant license enum class. Validate and parse all verified SPDX license identifiers from SPDX version 3.23. - SPDX Data for the Version 3.23 of the license list - -See https://github.com/spdx/license-list-XML/releases/tag/v3.23 for summary of changes - license,licence,SPDX,OSS,parse - - - - - \ No newline at end of file