Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/create-release-candidate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 0 additions & 22 deletions Generator/CsprojGenerator.cs

This file was deleted.

18 changes: 0 additions & 18 deletions Generator/DTO/Release.cs

This file was deleted.

6 changes: 1 addition & 5 deletions Generator/LicenseIdentifierFileComponents.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Generator
namespace Generator
{
public static class LicenseIdentifierFileComponents
{
Expand Down
102 changes: 79 additions & 23 deletions Generator/NuspecGenerator.cs
Original file line number Diff line number Diff line change
@@ -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 @$"<?xml version=""1.0"" encoding=""utf-8""?>
<package>
<metadata>
<id>LicenseIdentifiers</id>
<version>{version}</version>
<authors>TobyAndToby</authors>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<license type=""expression"">ISC</license>
<projectUrl>http://github.com/TobyAndToby/License-Identifiers</projectUrl>
<description>SPDX-compliant license enum class. Validate and parse all verified SPDX license identifiers from SPDX version {version}.</description>
<releaseNotes>{releaseDescription}</releaseNotes>
<tags>license,licence,SPDX,OSS,parse</tags>
</metadata>
<files>
<file src=""bin/Release/netstandard2.0/LicenseIdentifiers.dll"" target=""lib"" />
</files>
</package>";
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; }
}
}
86 changes: 33 additions & 53 deletions Generator/Program.cs
Original file line number Diff line number Diff line change
@@ -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<LicensesList>(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<License> licenses, string destination)
Expand Down Expand Up @@ -62,55 +65,32 @@ private static void GenerateLicensesClass(List<License> licenses, string destina
outputFile.Write(LicenseIdentifierFileComponents.FOOTER);
}

private static async Task<Release> GetLatestSpdxReleaseMetadata()
private static string GetVersion(string tag)
{
var spdxReleases = await client.GetStringAsync(SPDX_RELEASES_URI);
var releases = Utils.ParseJson<List<Release>>(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<LicensesList> 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<LicensesList>(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);
}
}
}
43 changes: 0 additions & 43 deletions Generator/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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_]");

/// <summary>
/// Given a JSON file location, read and parse into specified generic type. Logs exceptions.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileLocation"></param>
/// <returns></returns>
public static T ParseJson<T>(string raw) where T : new()
{
var data = new T();

try
{
data = JsonSerializer.Deserialize<T>(raw, JsonOptions);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}

return data;
}

/// <summary>
/// Takes a license ID and formats it to be a valid C# variable name.
/// <code>gpl-1.0+ -> GPL_1_0_PLUS</code>
Expand Down Expand Up @@ -66,26 +44,5 @@ public static string SpreadArrayValues(IEnumerable<string> 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;
}
}
}
2 changes: 0 additions & 2 deletions LicenseIdentifiers/LicenseIdentifiers.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>12</LangVersion>
<Version>1.0.0</Version>
</PropertyGroup>
</Project>
Loading