diff --git a/.github/workflow-gen/Program.cs b/.github/workflow-gen/Program.cs index c48381f6..f5996849 100644 --- a/.github/workflow-gen/Program.cs +++ b/.github/workflow-gen/Program.cs @@ -33,9 +33,12 @@ GenerateReleaseWorkflow(component); } +GenerateUploadTestResultsWorkflow(); + + void GenerateCiWorkflow(Component component) { - var workflow = new Workflow($"{component.Name}/ci"); + var workflow = new Workflow(component.CiWorkflowName); var paths = new[] { $".github/workflows/{component.Name}-**", @@ -57,6 +60,7 @@ void GenerateCiWorkflow(Component component) var job = workflow .Job("build") .Name("Build") + .RunEitherOnBranchOrAsPR() .RunsOn(GitHubHostedRunners.UbuntuLatest) .Defaults().Run("bash", component.Name) .Job; @@ -76,9 +80,11 @@ void GenerateCiWorkflow(Component component) foreach (var testProject in component.Tests) { - job.StepTestAndReport(component.Name, testProject); + job.StepTest(component.Name, testProject); } + job.StepUploadTestResultsAsArtifact(component.Tests); + job.StepToolRestore(); foreach (var project in component.Projects) @@ -102,7 +108,7 @@ void GenerateCiWorkflow(Component component) void GenerateReleaseWorkflow(Component component) { - var workflow = new Workflow($"{component.Name}/release"); + var workflow = new Workflow(component.ReleaseWorkflowName); workflow.On .WorkflowDispatch() @@ -169,6 +175,37 @@ git tag -a {component.TagPrefix}-{contexts.Event.Input.Version} -m ""Release v{c WriteWorkflow(workflow, fileName); } +void GenerateUploadTestResultsWorkflow() +{ + var workflow = new Workflow("generate-test-reports"); + workflow.On + .WorkflowRun() + .Workflows(components.Select(x => x.CiWorkflowName).ToArray()) + .Types("completed"); + + var job = workflow + .Job("report") + .Name("report") + .RunsOn(GitHubHostedRunners.UbuntuLatest); + + job.Permissions( + actions: Permission.Read, + contents: Permission.Read, + checks: Permission.Write, + packages: Permission.Write); + + foreach (var component in components) + { + foreach (var testProject in component.Tests) + { + job.StepGenerateReportFromTestArtifact(component, testProject); + } + } + + var fileName = $"generate-test-reports"; + WriteWorkflow(workflow, fileName); +} + void WriteWorkflow(Workflow workflow, string fileName) { var filePath = $"../workflows/{fileName}.yml"; @@ -176,10 +213,36 @@ void WriteWorkflow(Workflow workflow, string fileName) Console.WriteLine($"Wrote workflow to {filePath}"); } -record Component(string Name, string[] Projects, string[] Tests, string TagPrefix); +record Component(string Name, string[] Projects, string[] Tests, string TagPrefix) +{ + public string CiWorkflowName => $"{Name}/ci"; + public string ReleaseWorkflowName => $"{Name}/release"; + public string TestResultWorkflowName => $"{Name}/test-results"; +} public static class StepExtensions { + + /// + /// The build triggers both on branch AND on pull_request. + /// + /// Only (trusted) contributors can open branches in the main repo, so these builds can run with a higher trust level. + /// So, they are running with trigger 'push'. These builds have access to the secrets and thus they can do things like + /// sign, push the packages, etc.. + /// + /// External contributors can only create branches on external repo's. These builds run with a lower trust level. + /// So, they are running with trigger 'pull_request'. These builds do not have access to the secrets and thus they can't + /// sign, push the packages, etc.. + /// + /// Now, if a trusted contributor creates a branch in the main repo, then creates a PR, we don't want to run the build twice. + /// This prevents that. The build will only run once, on the branch with the higher trust level. + /// + /// + public static Job RunEitherOnBranchOrAsPR(this Job job) + => job.If( + "(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || (github.event_name == 'push')"); + + public static void EnvDefaults(this Workflow workflow) => workflow.Env( ("DOTNET_NOLOGO", "true"), @@ -193,7 +256,7 @@ public static void StepSetupDotNet(this Job job) public static Step IfRefMain(this Step step) => step.If("github.ref == 'refs/heads/main'"); - public static void StepTestAndReport(this Job job, string componentName, string testProject) + public static void StepTest(this Job job, string componentName, string testProject) { var path = $"test/{testProject}"; var logFileName = "Tests.trx"; @@ -204,13 +267,34 @@ public static void StepTestAndReport(this Job job, string componentName, string .Name($"Test - {testProject}") .Run($"dotnet test -c Release {path} {flags}"); + } + + private static readonly string LogFileName = "Tests.trx"; + + public static void StepUploadTestResultsAsArtifact(this Job job, string[] testProjects) + { + job.Step() + .Name("Upload test artifact") + .If("success() || failure()") + .Uses("actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882") // 4.4.3 + .With( + ("name", "test-results"), + ("path", string.Join(Environment.NewLine, testProjects + .Select(testProject => $"test/{testProject}/TestResults/{LogFileName}"))), + ("retention-days", "5")); + } + + internal static void StepGenerateReportFromTestArtifact(this Job job, Component component, string testProject) + { + var path = $"test/{testProject}"; job.Step() - .Name($"Test report - {testProject}") + .Name($"Test report - {component.Name} - {testProject}") .Uses("dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5") // v1.9.1 - .If("github.event == 'push' && (success() || failure())") + .If($"github.event.workflow_run.workflow == '{component.CiWorkflowName}'") .With( + ("artifact", "test-results"), ("name", $"Test Report - {testProject}"), - ("path", $"{componentName}/{path}/TestResults/{logFileName}"), + ("path", $"{component.Name}/{path}/TestResults/{LogFileName}"), ("reporter", "dotnet-trx"), ("fail-on-error", "true"), ("fail-on-empty", "true")); diff --git a/.github/workflows/access-token-management-ci.yml b/.github/workflows/access-token-management-ci.yml index e83a0db4..1fcb100b 100644 --- a/.github/workflows/access-token-management-ci.yml +++ b/.github/workflows/access-token-management-ci.yml @@ -19,6 +19,7 @@ env: jobs: build: name: Build + if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || (github.event_name == 'push') runs-on: ubuntu-latest permissions: actions: read @@ -44,15 +45,13 @@ jobs: 9.0.x - name: Test - AccessTokenManagement.Tests run: dotnet test -c Release test/AccessTokenManagement.Tests --logger "console;verbosity=normal" --logger "trx;LogFileName=Tests.trx" --collect:"XPlat Code Coverage" - - name: Test report - AccessTokenManagement.Tests - if: github.event == 'push' && (success() || failure()) - uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 + - name: Upload test artifact + if: success() || failure() + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 with: - name: Test Report - AccessTokenManagement.Tests - path: access-token-management/test/AccessTokenManagement.Tests/TestResults/Tests.trx - reporter: dotnet-trx - fail-on-error: true - fail-on-empty: true + name: test-results + path: test/AccessTokenManagement.Tests/TestResults/Tests.trx + retention-days: 5 - name: Tool restore run: dotnet tool restore - name: Pack AccessTokenManagement diff --git a/.github/workflows/generate-test-reports.yml b/.github/workflows/generate-test-reports.yml new file mode 100644 index 00000000..c6e42ad2 --- /dev/null +++ b/.github/workflows/generate-test-reports.yml @@ -0,0 +1,62 @@ +# This was generated by tool. Edits will be overwritten. + +name: generate-test-reports +on: + workflow_run: + workflows: + - 'ignore-this/ci' + - 'access-token-management/ci' + - 'identity-model/ci' + - 'identity-model-oidc-client/ci' + types: + - completed +jobs: + report: + name: report + runs-on: ubuntu-latest + permissions: + actions: read + checks: write + contents: read + packages: write + steps: + - name: Test report - ignore-this - IgnoreThis.Tests + if: github.event.workflow_run.workflow == 'ignore-this/ci' + uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 + with: + artifact: test-results + name: Test Report - IgnoreThis.Tests + path: ignore-this/test/IgnoreThis.Tests/TestResults/Tests.trx + reporter: dotnet-trx + fail-on-error: true + fail-on-empty: true + - name: Test report - access-token-management - AccessTokenManagement.Tests + if: github.event.workflow_run.workflow == 'access-token-management/ci' + uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 + with: + artifact: test-results + name: Test Report - AccessTokenManagement.Tests + path: access-token-management/test/AccessTokenManagement.Tests/TestResults/Tests.trx + reporter: dotnet-trx + fail-on-error: true + fail-on-empty: true + - name: Test report - identity-model - IdentityModel.Tests + if: github.event.workflow_run.workflow == 'identity-model/ci' + uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 + with: + artifact: test-results + name: Test Report - IdentityModel.Tests + path: identity-model/test/IdentityModel.Tests/TestResults/Tests.trx + reporter: dotnet-trx + fail-on-error: true + fail-on-empty: true + - name: Test report - identity-model-oidc-client - IdentityModel.OidcClient.Tests + if: github.event.workflow_run.workflow == 'identity-model-oidc-client/ci' + uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 + with: + artifact: test-results + name: Test Report - IdentityModel.OidcClient.Tests + path: identity-model-oidc-client/test/IdentityModel.OidcClient.Tests/TestResults/Tests.trx + reporter: dotnet-trx + fail-on-error: true + fail-on-empty: true diff --git a/.github/workflows/identity-model-ci.yml b/.github/workflows/identity-model-ci.yml index 7051208c..01ca8619 100644 --- a/.github/workflows/identity-model-ci.yml +++ b/.github/workflows/identity-model-ci.yml @@ -19,6 +19,7 @@ env: jobs: build: name: Build + if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || (github.event_name == 'push') runs-on: ubuntu-latest permissions: actions: read @@ -44,15 +45,13 @@ jobs: 9.0.x - name: Test - IdentityModel.Tests run: dotnet test -c Release test/IdentityModel.Tests --logger "console;verbosity=normal" --logger "trx;LogFileName=Tests.trx" --collect:"XPlat Code Coverage" - - name: Test report - IdentityModel.Tests - if: github.event == 'push' && (success() || failure()) - uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 + - name: Upload test artifact + if: success() || failure() + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 with: - name: Test Report - IdentityModel.Tests - path: identity-model/test/IdentityModel.Tests/TestResults/Tests.trx - reporter: dotnet-trx - fail-on-error: true - fail-on-empty: true + name: test-results + path: test/IdentityModel.Tests/TestResults/Tests.trx + retention-days: 5 - name: Tool restore run: dotnet tool restore - name: Pack IdentityModel diff --git a/.github/workflows/identity-model-oidc-client-ci.yml b/.github/workflows/identity-model-oidc-client-ci.yml index 37df9b9e..1c5dc519 100644 --- a/.github/workflows/identity-model-oidc-client-ci.yml +++ b/.github/workflows/identity-model-oidc-client-ci.yml @@ -19,6 +19,7 @@ env: jobs: build: name: Build + if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || (github.event_name == 'push') runs-on: ubuntu-latest permissions: actions: read @@ -44,15 +45,13 @@ jobs: 9.0.x - name: Test - IdentityModel.OidcClient.Tests run: dotnet test -c Release test/IdentityModel.OidcClient.Tests --logger "console;verbosity=normal" --logger "trx;LogFileName=Tests.trx" --collect:"XPlat Code Coverage" - - name: Test report - IdentityModel.OidcClient.Tests - if: github.event == 'push' && (success() || failure()) - uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 + - name: Upload test artifact + if: success() || failure() + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 with: - name: Test Report - IdentityModel.OidcClient.Tests - path: identity-model-oidc-client/test/IdentityModel.OidcClient.Tests/TestResults/Tests.trx - reporter: dotnet-trx - fail-on-error: true - fail-on-empty: true + name: test-results + path: test/IdentityModel.OidcClient.Tests/TestResults/Tests.trx + retention-days: 5 - name: Tool restore run: dotnet tool restore - name: Pack IdentityModel.OidcClient diff --git a/.github/workflows/ignore-this-ci.yml b/.github/workflows/ignore-this-ci.yml index 34b5f0b0..246e26ab 100644 --- a/.github/workflows/ignore-this-ci.yml +++ b/.github/workflows/ignore-this-ci.yml @@ -19,6 +19,7 @@ env: jobs: build: name: Build + if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || (github.event_name == 'push') runs-on: ubuntu-latest permissions: actions: read @@ -44,15 +45,13 @@ jobs: 9.0.x - name: Test - IgnoreThis.Tests run: dotnet test -c Release test/IgnoreThis.Tests --logger "console;verbosity=normal" --logger "trx;LogFileName=Tests.trx" --collect:"XPlat Code Coverage" - - name: Test report - IgnoreThis.Tests - if: github.event == 'push' && (success() || failure()) - uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 + - name: Upload test artifact + if: success() || failure() + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 with: - name: Test Report - IgnoreThis.Tests - path: ignore-this/test/IgnoreThis.Tests/TestResults/Tests.trx - reporter: dotnet-trx - fail-on-error: true - fail-on-empty: true + name: test-results + path: test/IgnoreThis.Tests/TestResults/Tests.trx + retention-days: 5 - name: Tool restore run: dotnet tool restore - name: Pack IgnoreThis diff --git a/access-token-management/test/AccessTokenManagement.Tests/AccessTokenManagement.Tests.net8.0.v3.ncrunchproject b/access-token-management/test/AccessTokenManagement.Tests/AccessTokenManagement.Tests.net8.0.v3.ncrunchproject new file mode 100644 index 00000000..95a483b4 --- /dev/null +++ b/access-token-management/test/AccessTokenManagement.Tests/AccessTokenManagement.Tests.net8.0.v3.ncrunchproject @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/access-token-management/test/AccessTokenManagement.Tests/AccessTokenManagement.Tests.net9.0.v3.ncrunchproject b/access-token-management/test/AccessTokenManagement.Tests/AccessTokenManagement.Tests.net9.0.v3.ncrunchproject new file mode 100644 index 00000000..95a483b4 --- /dev/null +++ b/access-token-management/test/AccessTokenManagement.Tests/AccessTokenManagement.Tests.net9.0.v3.ncrunchproject @@ -0,0 +1,3 @@ + + + \ No newline at end of file