chore: squash repository history into a single commit
Some checks failed
CI / build (push) Has been cancelled
Some checks failed
CI / build (push) Has been cancelled
This commit is contained in:
commit
32c088f1e7
52 changed files with 1888 additions and 0 deletions
20
.editorconfig
Normal file
20
.editorconfig
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
max_line_length = 120
|
||||
indent_style = tab
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
file_header_template = Copyright (c) The Geekeey Authors\nSPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
[*.md]
|
||||
indent_style = space
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
trim_trailing_whitespace = false
|
||||
79
.forgejo/workflows/ci.yml
Normal file
79
.forgejo/workflows/ci.yml
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ['*']
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
enable-openid-connect: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: build
|
||||
runs-on: debian-latest
|
||||
container: mcr.microsoft.com/dotnet/sdk:10.0@sha256:0d99ebf1ccad15037b5c98c9fe8979d6b8dbac23812feae2277a0b277b5c5ffa
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: https://code.geekeey.de/actions/checkout@54953ce9d6c7d0a9cbd89d185c5b2c7515358c5f # 1
|
||||
|
||||
- name: dotnet pack
|
||||
shell: bash
|
||||
env:
|
||||
TAG: ${{ forgejo.ref }}
|
||||
TAG_NAME: ${{ forgejo.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "$TAG" == refs/tags/* ]]; then
|
||||
version="${TAG_NAME#v}"
|
||||
if ! printf '%s' "$version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
||||
echo "::error::Tag '$TAG_NAME' is not a valid release version (expected MAJOR.MINOR.PATCH)"
|
||||
exit 1
|
||||
fi
|
||||
export version
|
||||
fi
|
||||
|
||||
dotnet pack arcade.slnx
|
||||
|
||||
- name: upload packages
|
||||
uses: https://code.geekeey.de/actions/artifacts/push@ae8d20e174a8706675e6d54ebd3719a2802ea9dd # 1
|
||||
with:
|
||||
name: nuget-packages
|
||||
path: artifacts/package/release
|
||||
pattern: |
|
||||
*.nupkg
|
||||
*.snupkg
|
||||
|
||||
- name: dotnet test
|
||||
run: dotnet test src/sdk.tests/Geekeey.Arcade.NET.Tests.csproj
|
||||
|
||||
- name: publish to nuget
|
||||
if: startsWith(forgejo.ref, 'refs/tags/')
|
||||
shell: bash
|
||||
env:
|
||||
AUDIENCE: "u:1:00000000-0000-0000-0000-000000000000"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" || -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ]]; then
|
||||
echo "::error::OpenID Connect is not enabled. Set enable-openid-connect: true on the workflow or job."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
response=$(curl --fail --silent --show-error \
|
||||
--header "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${AUDIENCE}")
|
||||
token=$(printf '%s' "${response}" | grep --only-matching '"value":"[^"]*"' | cut --delimiter '"' --fields 4)
|
||||
|
||||
if [[ -z "${token}" ]]; then
|
||||
echo "::error::Failed to obtain an OpenID Connect token from Forgejo."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "::add-mask::${token}"
|
||||
|
||||
feed="${{ forgejo.server_url }}/api/packages/${{ forgejo.repository_owner }}/nuget/index.json"
|
||||
|
||||
dotnet nuget add source --name forgejo --username forgejo-publish --password "$token" --store-password-in-clear-text "$feed"
|
||||
dotnet nuget push "artifacts/package/release/*.nupkg" "artifacts/package/release/*.snupkg" --source forgejo --skip-duplicate
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
artifacts/
|
||||
TestResults/
|
||||
node_modules/
|
||||
*.DotSettings.user
|
||||
7
Directory.Build.props
Normal file
7
Directory.Build.props
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<Project>
|
||||
<Import Project="$(MSBuildThisFileDirectory)src/sdk/common/Common.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
3
Directory.Build.targets
Normal file
3
Directory.Build.targets
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<Project>
|
||||
<Import Project="$(MSBuildThisFileDirectory)src/sdk/common/Common.targets" />
|
||||
</Project>
|
||||
8
Directory.Packages.props
Normal file
8
Directory.Packages.props
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="TUnit" Version="1.75.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
1
README.md
Normal file
1
README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# arcade
|
||||
7
arcade.slnx
Normal file
7
arcade.slnx
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<Solution>
|
||||
<Project Path="src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Geekeey.Arcade.NET.Sdk.csproj" />
|
||||
<Project Path="src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Razor/Geekeey.Arcade.NET.Sdk.Razor.csproj" />
|
||||
<Project Path="src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Geekeey.Arcade.NET.Sdk.Test.csproj" />
|
||||
<Project Path="src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Geekeey.Arcade.NET.Sdk.Web.csproj" />
|
||||
<Project Path="src/sdk.tests/Geekeey.Arcade.NET.Tests.csproj" />
|
||||
</Solution>
|
||||
11
global.json
Normal file
11
global.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"$schema": "https://www.schemastore.org/global.json",
|
||||
"sdk": {
|
||||
"version": "10.0.0",
|
||||
"rollForward": "latestMinor"
|
||||
},
|
||||
"msbuild-sdks": {},
|
||||
"test": {
|
||||
"runner": "Microsoft.Testing.Platform"
|
||||
}
|
||||
}
|
||||
23
src/sdk.tests/DirectoryExtensions.cs
Normal file
23
src/sdk.tests/DirectoryExtensions.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) The Geekeey Authors
|
||||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
namespace Geekeey.Arcade.NET.Tests;
|
||||
|
||||
public static class DirectoryExtensions
|
||||
{
|
||||
extension(Directory)
|
||||
{
|
||||
public static void Copy(string sourceDirectory, string destinationDirectory)
|
||||
{
|
||||
foreach (var directory in Directory.EnumerateDirectories(sourceDirectory, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
Directory.CreateDirectory(Path.Combine(destinationDirectory, Path.GetRelativePath(sourceDirectory, directory)));
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(sourceDirectory, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
File.Copy(file, Path.Combine(destinationDirectory, Path.GetRelativePath(sourceDirectory, file)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/sdk.tests/Geekeey.Arcade.NET.Tests.csproj
Normal file
15
src/sdk.tests/Geekeey.Arcade.NET.Tests.csproj
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TUnit" />
|
||||
<Compile Remove="fixtures/**/*.cs" />
|
||||
<None Remove="fixtures/**/*" />
|
||||
<Content Include="fixtures/**/*" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
163
src/sdk.tests/SdkPackageIntegrationTests.cs
Normal file
163
src/sdk.tests/SdkPackageIntegrationTests.cs
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
// Copyright (c) The Geekeey Authors
|
||||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Geekeey.Arcade.NET.Tests;
|
||||
|
||||
public sealed class SdkPackageIntegrationTests
|
||||
{
|
||||
|
||||
private static string RepositoryPath
|
||||
{
|
||||
get
|
||||
{
|
||||
for (var directory = new DirectoryInfo(AppContext.BaseDirectory); directory is not null; directory = directory.Parent)
|
||||
{
|
||||
if (File.Exists(Path.Combine(directory.FullName, "global.json")))
|
||||
{
|
||||
return directory.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Could not locate the repository root containing global.json.");
|
||||
}
|
||||
}
|
||||
|
||||
private static string NuGetFeedPath { get; } = Path.Combine(RepositoryPath, "artifacts", "package", "release");
|
||||
|
||||
[Test]
|
||||
[Arguments("Geekeey.Arcade.NET.Sdk", "base")]
|
||||
[Arguments("Geekeey.Arcade.NET.Sdk.Razor", "razor")]
|
||||
[Arguments("Geekeey.Arcade.NET.Sdk.Web", "web")]
|
||||
public async Task SdkPackageCanBeConsumedFromAFeed(string packageId, string name)
|
||||
{
|
||||
// Arrange
|
||||
var version = FindPackageVersion(packageId);
|
||||
using var sut = await SdkTestProject.CreateAsync(name, version);
|
||||
|
||||
// Act
|
||||
await sut.RunDotnetAsync($"restore --configfile \"{sut.NuGetConfigPath}\" --packages \"{sut.PackagesPath}\" --nologo");
|
||||
await sut.RunDotnetAsync("build --no-restore --nologo");
|
||||
await sut.RunDotnetAsync($"pack --no-restore --configuration Debug --output \"{sut.PackedPath}\" --nologo");
|
||||
|
||||
// Assert
|
||||
await Assert.That(File.Exists(Path.Combine(sut.ProjectPath, "bin", "Debug", "net10.0", $"{sut.ProjectName}.dll"))).IsTrue();
|
||||
await Assert.That(Directory.Exists(sut.PackedPath)).IsTrue();
|
||||
await Assert.That(Directory.EnumerateFiles(sut.PackedPath, $"{sut.ProjectName}.*.nupkg").Any()).IsTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSdkPackageStoresTestOutputInArtifacts()
|
||||
{
|
||||
// Arrange
|
||||
var version = FindPackageVersion("Geekeey.Arcade.NET.Sdk.Test");
|
||||
using var sut = await SdkTestProject.CreateAsync("test", version);
|
||||
await sut.RunDotnetAsync($"restore --configfile \"{sut.NuGetConfigPath}\" --packages \"{sut.PackagesPath}\" --nologo");
|
||||
await sut.RunDotnetAsync("build --no-restore --nologo");
|
||||
|
||||
var outputDirectory = Path.Combine(sut.ProjectPath, "artifacts", "bin", sut.ProjectName, "debug");
|
||||
await Assert.That(File.Exists(Path.Combine(outputDirectory, $"{sut.ProjectName}.dll"))).IsTrue();
|
||||
|
||||
// Act
|
||||
var stdout = await sut.RunDotnetAsync("run --no-build --no-restore");
|
||||
|
||||
// Assert
|
||||
await Assert.That(stdout.Contains("succeeded: 1", StringComparison.Ordinal)).IsTrue();
|
||||
}
|
||||
|
||||
private static string FindPackageVersion(string packageId)
|
||||
{
|
||||
var pattern = $"""^{Regex.Escape(packageId)}\.(?<version>\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)\.nupkg$""";
|
||||
foreach (var package in Directory.EnumerateFiles(NuGetFeedPath, "*.nupkg"))
|
||||
{
|
||||
var match = Regex.Match(Path.GetFileName(package), pattern, RegexOptions.CultureInvariant);
|
||||
if (match.Success)
|
||||
{
|
||||
return match.Groups["version"].Value;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"No current package found for {packageId}. Run dotnet pack first.");
|
||||
}
|
||||
|
||||
private sealed class SdkTestProject : IDisposable
|
||||
{
|
||||
private SdkTestProject(string root)
|
||||
{
|
||||
RootPath = root;
|
||||
ProjectPath = Path.Combine(RootPath, "Project");
|
||||
PackagesPath = Path.Combine(RootPath, "packages");
|
||||
PackedPath = Path.Combine(RootPath, "packed");
|
||||
NuGetConfigPath = Path.Combine(RootPath, "NuGet.config");
|
||||
}
|
||||
|
||||
public static async Task<SdkTestProject> CreateAsync(string name, string version)
|
||||
{
|
||||
var sut = new SdkTestProject(Path.Combine(Path.GetTempPath(), $"arcade-sdk-test-{Guid.NewGuid():N}"));
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(sut.ProjectPath);
|
||||
Directory.Copy(Path.Combine(AppContext.BaseDirectory, "fixtures", name), sut.ProjectPath);
|
||||
sut.ProjectFilePath = Directory.EnumerateFiles(sut.ProjectPath, "*.csproj").Single();
|
||||
sut.ProjectName = Path.GetFileNameWithoutExtension(sut.ProjectFilePath);
|
||||
var project = await File.ReadAllTextAsync(sut.ProjectFilePath);
|
||||
await File.WriteAllTextAsync(sut.ProjectFilePath, project.Replace("{0}", version, StringComparison.Ordinal));
|
||||
var contents = $"""
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="local" value="{Path.Combine(RepositoryPath, "artifacts", "package", "release")}" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
""";
|
||||
await File.WriteAllTextAsync(sut.NuGetConfigPath, contents);
|
||||
return sut;
|
||||
}
|
||||
catch
|
||||
{
|
||||
sut.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public string RootPath { get; }
|
||||
|
||||
public string ProjectPath { get; }
|
||||
|
||||
public string ProjectFilePath { get; private set; } = "";
|
||||
|
||||
public string ProjectName { get; private set; } = "";
|
||||
|
||||
public string PackagesPath { get; }
|
||||
|
||||
public string PackedPath { get; }
|
||||
|
||||
public string NuGetConfigPath { get; }
|
||||
|
||||
public async Task<string> RunDotnetAsync(string arguments)
|
||||
{
|
||||
var startInfo = new ProcessStartInfo("dotnet", arguments)
|
||||
{
|
||||
WorkingDirectory = ProjectPath,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
Environment = { ["NUGET_PACKAGES"] = PackagesPath, ["DOTNET_CLI_DO_NOT_USE_MSBUILD_SERVER"] = "1" }
|
||||
};
|
||||
var process = Process.Start(startInfo) ?? throw new InvalidOperationException("Could not start dotnet.");
|
||||
var output = await process.StandardOutput.ReadToEndAsync();
|
||||
var error = await process.StandardError.ReadToEndAsync();
|
||||
await process.WaitForExitAsync();
|
||||
return process.ExitCode is 0 ? output : throw new InvalidOperationException($"dotnet {arguments} failed with exit code {process.ExitCode}.\n{output}\n{error}");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Directory.Delete(RootPath, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/sdk.tests/fixtures/base/BaseConsumer.csproj
Normal file
9
src/sdk.tests/fixtures/base/BaseConsumer.csproj
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<Project Sdk="Geekeey.Arcade.NET.Sdk/{0}">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<IsPackable>true</IsPackable>
|
||||
<NoBuild>false</NoBuild>
|
||||
<PackageId>BaseConsumer</PackageId>
|
||||
<NoWarn>IDE0055</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
4
src/sdk.tests/fixtures/base/Program.cs
Normal file
4
src/sdk.tests/fixtures/base/Program.cs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
public static class EntryPoint
|
||||
{
|
||||
public static string Value { get; } = "ok";
|
||||
}
|
||||
4
src/sdk.tests/fixtures/razor/Program.cs
Normal file
4
src/sdk.tests/fixtures/razor/Program.cs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
public sealed class ComponentModel
|
||||
{
|
||||
public static string Value { get; } = "ok";
|
||||
}
|
||||
8
src/sdk.tests/fixtures/razor/RazorConsumer.csproj
Normal file
8
src/sdk.tests/fixtures/razor/RazorConsumer.csproj
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<Project Sdk="Geekeey.Arcade.NET.Sdk.Razor/{0}">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<PackageId>RazorConsumer</PackageId>
|
||||
<StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
|
||||
<NoWarn>IDE0055</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
5
src/sdk.tests/fixtures/test/Directory.Build.props
Normal file
5
src/sdk.tests/fixtures/test/Directory.Build.props
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<ArtifactsPath>$(MSBuildProjectDirectory)/artifacts/</ArtifactsPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
7
src/sdk.tests/fixtures/test/Program.cs
Normal file
7
src/sdk.tests/fixtures/test/Program.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
using TUnit.Core;
|
||||
|
||||
public class ConsumerTests
|
||||
{
|
||||
[Test]
|
||||
public void TestPasses() { }
|
||||
}
|
||||
14
src/sdk.tests/fixtures/test/TestConsumer.csproj
Normal file
14
src/sdk.tests/fixtures/test/TestConsumer.csproj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Geekeey.Arcade.NET.Sdk.Test/{0}">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<IsPackable>true</IsPackable>
|
||||
<NoBuild>false</NoBuild>
|
||||
<PackageId>TestConsumer</PackageId>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<OutputType>Exe</OutputType>
|
||||
<NoWarn>IDE0055</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TUnit" Version="1.75.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
3
src/sdk.tests/fixtures/web/Program.cs
Normal file
3
src/sdk.tests/fixtures/web/Program.cs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
var builder = WebApplication.CreateBuilder(args);
|
||||
var app = builder.Build();
|
||||
app.MapGet("/", () => "ok");
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue