diff --git a/.editorconfig b/.editorconfig index f64f1d7..b107a1d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -87,7 +87,7 @@ dotnet_style_prefer_simplified_boolean_expressions = true:suggestion ### Visual Studio ### # IDE0005: Using directive is unnecessary. -dotnet_diagnostic.IDE0005.severity = warning +dotnet_diagnostic.IDE0005.severity = none # IDE0130: Namespace does not match folder structure dotnet_diagnostic.IDE0130.severity = none @@ -108,4 +108,8 @@ indent_size = unset indent_style = unset insert_final_newline = false tab_width = unset -trim_trailing_whitespace = false \ No newline at end of file +trim_trailing_whitespace = false + +[*.{received,verified}.{html}] +indent_size = 2 +indent_style = space \ No newline at end of file diff --git a/.github/workflows/github-actions-ci.yaml b/.github/workflows/github-actions-ci.yaml index d2bff7f..9b4e8f2 100644 --- a/.github/workflows/github-actions-ci.yaml +++ b/.github/workflows/github-actions-ci.yaml @@ -10,10 +10,10 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: dotnet-version: 9.x @@ -25,10 +25,14 @@ jobs: - name: Run tests run: | - dotnet test PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.slnx \ + dotnet test \ + --solution PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.slnx \ --configuration Release \ --no-build \ - --logger "trx;LogFileName=test_results.trx" \ + --coverage \ + --coverage-output-format cobertura \ + --coverage-settings CodeCoverage.runsettings \ + --report-trx \ --results-directory ./TestResults - name: Publish Test Results diff --git a/.github/workflows/github-actions-release.yml b/.github/workflows/github-actions-release.yml index 5dc9868..cf20f5f 100644 --- a/.github/workflows/github-actions-release.yml +++ b/.github/workflows/github-actions-release.yml @@ -7,7 +7,7 @@ on: type: string description: The version of the application required: true - default: 1.1.0 + default: 1.2.0 VersionSuffix: type: string description: The version suffix of the application (for example rc.1) @@ -18,12 +18,12 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - name: Setup .NET 9.x - uses: actions/setup-dotnet@v4 + - name: Setup .NET 10.x + uses: actions/setup-dotnet@v5 with: - dotnet-version: '9.x' + dotnet-version: '10.x' - name: Build AppRegistrationSecretWatcher Azure Functions run: dotnet publish @@ -34,13 +34,13 @@ jobs: "src/Functions/Functions.csproj" - name: Package the AppRegistrationSecretWatcher Azure Functions - run: cd ./publish && zip -r ../PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.Functions.net9.0.zip . + run: cd ./publish && zip -r ../PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.Functions.net10.0.zip . - name: Upload to release uses: softprops/action-gh-release@v2 with: tag_name: v${{ github.event.inputs.VersionPrefix }}${{ github.event.inputs.VersionSuffix && format('-{0}', github.event.inputs.VersionSuffix) || '' }} - files: ./PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.Functions.net9.0.zip + files: ./PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.Functions.net10.0.zip overwrite_files: true draft: ${{ github.event.inputs.VersionSuffix == '' }} prerelease: ${{ github.event.inputs.VersionSuffix != '' }} diff --git a/CodeCoverage.runsettings b/CodeCoverage.runsettings new file mode 100644 index 0000000..c9bffdc --- /dev/null +++ b/CodeCoverage.runsettings @@ -0,0 +1,51 @@ + + + + + + + + + + + + + .*\.dll$ + + + .*xunit.* + .*webjobs.* + moq.* + .*durabletask.* + microsoft.* + bouncycastle.* + .*tests\.dll$ + + + + + + + ^System\.CodeDom\.Compiler\.GeneratedCodeAttribute$ + ^System\.Diagnostics\.CodeAnalysis\.ExcludeFromCodeCoverageAttribute$ + + + + + + .*PosInformatique.* + + + + + True + True + True + False + + + + + + + \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index 7dc0a65..1b4d7be 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -2,30 +2,29 @@ true - 1.0.0 + 1.1.0 - - - - - - + + + + + - - - + + + + - - + + - - - + + \ No newline at end of file diff --git a/PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.slnx b/PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.slnx index d65c357..cf480fc 100644 --- a/PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.slnx +++ b/PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.slnx @@ -3,6 +3,7 @@ + diff --git a/README.md b/README.md index 842b16a..3da795d 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ To send the e-mail using Graph API: ### Configuration +- `APPLICATIONINSIGHTS_CONNECTION_STRING`: + Application Insights connection string to enable telemetry. - `APP_SECRET_WATCHER_CLIENT_ID`: Client ID of the App Registration used to query secrets across tenants. If omitted, the Function managed identity is used (single-tenant only). - `APP_SECRET_WATCHER_CLIENT_SECRET`: @@ -115,5 +117,5 @@ to send mail via Graph withb the `Mail.Send` application permission. - Ensure recipients are a monitored distribution list or shared mailbox to avoid missed alerts. ## Compatibility -- .NET: 9.0 +- .NET: 10.0 - Azure Functions: Isolated v4 diff --git a/global.json b/global.json index 9d34b15..9d50058 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,9 @@ { "sdk": { - "version": "9.0.305", + "version": "10.0.301", "rollForward": "latestFeature" + }, + "test": { + "runner": "Microsoft.Testing.Platform" } } diff --git a/src/Core/EntraId/GraphServiceClientFactory.cs b/src/Core/EntraId/GraphServiceClientFactory.cs index 44e075d..4e05250 100644 --- a/src/Core/EntraId/GraphServiceClientFactory.cs +++ b/src/Core/EntraId/GraphServiceClientFactory.cs @@ -26,7 +26,7 @@ public GraphServiceClient Create(string tenantId) if (this.options.ClientId is null) { - credential = new ManagedIdentityCredential(); + credential = new ManagedIdentityCredential(new ManagedIdentityCredentialOptions()); } else { diff --git a/src/Directory.Build.props b/src/Directory.Build.props index a67878d..1681166 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,7 +4,7 @@ - net9.0 + net10.0 enable diff --git a/src/Functions/AppRegistrationSecretWatcherApplication.cs b/src/Functions/AppRegistrationSecretWatcherApplication.cs index ea3406b..ffaa1f0 100644 --- a/src/Functions/AppRegistrationSecretWatcherApplication.cs +++ b/src/Functions/AppRegistrationSecretWatcherApplication.cs @@ -8,8 +8,10 @@ namespace PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.Functions { using System.Globalization; using global::Azure.Identity; + using global::Azure.Monitor.OpenTelemetry.Exporter; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Builder; + using Microsoft.Azure.Functions.Worker.OpenTelemetry; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.Emailing; @@ -105,8 +107,9 @@ public static async Task Main(string[] args) // Add Application Insights builder.Services - .AddApplicationInsightsTelemetryWorkerService() - .ConfigureFunctionsApplicationInsights(); + .AddOpenTelemetry() + .UseFunctionsWorkerDefaults() + .UseAzureMonitorExporter(); // Emailing builder.Services.AddEmailing(opt => diff --git a/src/Functions/Functions.csproj b/src/Functions/Functions.csproj index 8e0cf1a..7c6c457 100644 --- a/src/Functions/Functions.csproj +++ b/src/Functions/Functions.csproj @@ -7,11 +7,11 @@ - + - + diff --git a/tests/Core.Tests/Emailing/RazorTemplateTools.cs b/tests/Core.Tests/Emailing/RazorTemplateTools.cs index 580d264..23ba24d 100644 --- a/tests/Core.Tests/Emailing/RazorTemplateTools.cs +++ b/tests/Core.Tests/Emailing/RazorTemplateTools.cs @@ -15,7 +15,7 @@ namespace PosInformatique public static class RazorTemplateTools { - /*public static void DisplayHtmlPage(string content, string testName) + public static void DisplayHtmlPage(string content, string testName) { if (!Debugger.IsAttached) { @@ -37,7 +37,7 @@ public static class RazorTemplateTools FileName = temporaryFile, UseShellExecute = true, }); - }*/ + } public static async Task RenderAsync(object model, IServiceCollection services) where TComponent : ComponentBase @@ -67,4 +67,4 @@ public static async Task RenderAsync(object model, IServiceC return output.ToString(); } } -} +} \ No newline at end of file diff --git a/tests/Core.Tests/UnitTestsFolders.cs b/tests/Core.Tests/UnitTestsFolders.cs new file mode 100644 index 0000000..46bb798 --- /dev/null +++ b/tests/Core.Tests/UnitTestsFolders.cs @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) P.O.S Informatique. All rights reserved. +// +//----------------------------------------------------------------------- + +namespace PosInformatique +{ + internal static class UnitTestsFolders + { + static UnitTestsFolders() + { + SolutionRoot = GetSolutionRootPath(); + TemporaryRoot = Path.Combine(SolutionRoot, "tmp"); + } + + public static string TemporaryRoot { get; } + + private static string SolutionRoot { get; } + + private static string GetSolutionRootPath() + { + var directory = new DirectoryInfo("./"); + + while (directory is not null && !directory.EnumerateFiles("PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.slnx").Any()) + { + directory = directory.Parent; + } + + if (directory is null) + { + throw new DirectoryNotFoundException("Unable to find the PosInformatique.Azure.Identity.AppRegistrationSecretWatcher solution root path."); + } + + return directory.FullName; + } + } +} \ No newline at end of file diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index 0b956a7..b1a1a87 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -5,27 +5,25 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + - net9.0 - + net10.0 + + + Exe + true + false + $(NoWarn);SA0001