diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 3b78d2c..e8a0614 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -37,8 +37,27 @@ jobs: trx-file-path: '${{ runner.temp }}/*.trx' output-directory: '${{ runner.temp }}/vsplaylists' + aot-test: + name: AOT publish test + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v6 + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + global-json-file: global.json + - name: Install NativeAOT prerequisites + run: sudo apt-get install -y clang zlib1g-dev + - name: Publish AOT + run: dotnet publish IntelliTect.Multitool.AotTest/IntelliTect.Multitool.AotTest.csproj -r linux-x64 -c Release + - name: Run AOT binary + run: ./IntelliTect.Multitool.AotTest/bin/Release/net8.0/linux-x64/publish/IntelliTect.Multitool.AotTest + automerge: - needs: [build-and-test] + needs: [build-and-test, aot-test] runs-on: ubuntu-latest permissions: diff --git a/IntelliTect.Multitool.AotTest/IntelliTect.Multitool.AotTest.csproj b/IntelliTect.Multitool.AotTest/IntelliTect.Multitool.AotTest.csproj new file mode 100644 index 0000000..eb9f66a --- /dev/null +++ b/IntelliTect.Multitool.AotTest/IntelliTect.Multitool.AotTest.csproj @@ -0,0 +1,13 @@ + + + Exe + net8.0 + false + true + true + + + + + + diff --git a/IntelliTect.Multitool.AotTest/Program.cs b/IntelliTect.Multitool.AotTest/Program.cs new file mode 100644 index 0000000..0d040c2 --- /dev/null +++ b/IntelliTect.Multitool.AotTest/Program.cs @@ -0,0 +1,27 @@ +using IntelliTect.Multitool; +using IntelliTect.Multitool.Extensions; + +// StringExtensions +bool slugOk = "Hello, World!".CreateUrlSlug() == "hello-world"; +bool urlOk = "https://github.com/IntelliTect".ValidateUrlString(); + +// SystemLinqExtensions +string?[] items = ["a", null, "b", null, "c"]; +bool filterOk = items.WhereNotNull().Count() == 3; + +// ReleaseDateAttribute — returns null since no attribute on this assembly, +// but exercises the AOT-safe (statically-known type) GetCustomAttribute code path +DateTime? releaseDate = ReleaseDateAttribute.GetReleaseDate(); +bool attributeOk = releaseDate is null; + +if (!slugOk || !urlOk || !filterOk || !attributeOk) +{ + Console.Error.WriteLine("AOT test FAILED."); + return 1; +} + +// RepositoryPaths is excluded: its static initializer reads a build-time temp file +// that doesn't exist at AOT runtime. The class is AOT-compatible (file I/O + LINQ only). + +Console.WriteLine("AOT test passed."); +return 0; diff --git a/IntelliTect.Multitool.slnx b/IntelliTect.Multitool.slnx index 937a092..a83787a 100644 --- a/IntelliTect.Multitool.slnx +++ b/IntelliTect.Multitool.slnx @@ -7,6 +7,7 @@ + diff --git a/IntelliTect.Multitool/IntelliTect.Multitool.csproj b/IntelliTect.Multitool/IntelliTect.Multitool.csproj index 4a73c0b..eb76d5e 100644 --- a/IntelliTect.Multitool/IntelliTect.Multitool.csproj +++ b/IntelliTect.Multitool/IntelliTect.Multitool.csproj @@ -1,6 +1,6 @@ - netstandard2.1 + netstandard2.1;net8.0 Library true true @@ -13,6 +13,7 @@ true en 1.0.1 + true diff --git a/IntelliTect.Multitool/ReleaseDateAttribute.cs b/IntelliTect.Multitool/ReleaseDateAttribute.cs index 7356c64..1acea3c 100644 --- a/IntelliTect.Multitool/ReleaseDateAttribute.cs +++ b/IntelliTect.Multitool/ReleaseDateAttribute.cs @@ -22,8 +22,7 @@ public class ReleaseDateAttribute(string utcDateString) : Attribute /// The date time from the assembly attribute public static DateTime? GetReleaseDate(Assembly? assembly = null) { - object[]? attribute = (assembly ?? Assembly.GetEntryAssembly())?.GetCustomAttributes(typeof(ReleaseDateAttribute), false); - return attribute?.Length >= 1 ? ((ReleaseDateAttribute)attribute[0]).ReleaseDate : null; + return (assembly ?? Assembly.GetEntryAssembly())?.GetCustomAttribute()?.ReleaseDate; } } diff --git a/IntelliTect.Multitool/RepositoryPaths.cs b/IntelliTect.Multitool/RepositoryPaths.cs index bb57510..35db6a5 100644 --- a/IntelliTect.Multitool/RepositoryPaths.cs +++ b/IntelliTect.Multitool/RepositoryPaths.cs @@ -43,7 +43,7 @@ public static string GetDefaultRepoRoot() } } // Search from the project directory if we are live unit testing or if the initial search failed. - if (BuildVariables.TryGetValue("ProjectPath", out string? projectPath)) + if (BuildVariables.TryGetValue("ProjectPath", out string? projectPath) && !string.IsNullOrWhiteSpace(projectPath)) { searchStartDirectory = new FileInfo(projectPath).Directory; if (TrySearchForGitContainingDirectory(searchStartDirectory, out gitDirectory)