diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 28407fb72..ff7f9674a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,104 +1,33 @@ -trigger: -- master - -pr: - autoCancel: true - branches: - include: - - master - -stages: - -# Full multi-TFM build + unit tests. The unit test project targets .NET Framework -# (net462/net472) as well as net8/net9/net10, so it needs the complete multi-TFM -# solution build. E2E and managed-identity tests run in their own stages below. -- stage: Build - displayName: 'Build & Unit Tests' - jobs: - - job: PR_build - variables: - # Load the LabAuth client certificate from the local certificate store - # (installed into LocalMachine/My by template-install-dependencies.yaml) - # instead of the msidlabs KeyVault. Microsoft-hosted agents have no managed - # identity that can read the KeyVault, so DefaultAzureCredential would fail. - # The official OneBranch/Wilson pipeline does not set this and keeps using - # the KeyVault source. - UseLabAuthCertFromStore: true - pool: - vmImage: 'windows-2022' - demands: - - msbuild - - visualstudio - steps: - - template: build/template-install-dependencies.yaml - - template: build/template-build.yaml - - template: build/template-test-unit.yaml - -# Integration tests only depend on .NET 8, so build just that project and run them -# in parallel with the full Build stage (dependsOn: [] -> no dependency on Build). -- stage: IntegrationTests - displayName: 'Integration Tests (.NET 8)' - dependsOn: [] - jobs: - - job: IntegrationTests - variables: - UseLabAuthCertFromStore: true - pool: - vmImage: 'windows-2022' - demands: - - msbuild - - visualstudio - steps: - - template: build/template-install-dependencies.yaml - - template: build/template-build-test-project.yaml - parameters: - Project: 'tests/Microsoft.Identity.Web.Test.Integration/Microsoft.Identity.Web.Test.Integration.csproj' - TargetFramework: 'net8.0' - - template: build/template-test-integration.yaml - -# Browser/host E2E tests (excluding managed identity). The E2E projects target -# net8.0 and pull their sample apps in as project references, so build just those -# projects and run in parallel with Build (dependsOn: []). -- stage: E2ETests - displayName: 'E2E Tests (.NET 8)' - dependsOn: [] - jobs: - - job: E2ETests - variables: - UseLabAuthCertFromStore: true - pool: - vmImage: 'windows-2022' - demands: - - msbuild - - visualstudio - steps: - - template: build/template-install-dependencies.yaml - - template: build/template-build-test-project.yaml - parameters: - Project: 'tests/E2E Tests/WebAppUiTests/WebAppUiTests.csproj' - TargetFramework: 'net8.0' - - template: build/template-build-test-project.yaml - parameters: - Project: 'tests/E2E Tests/TokenAcquirerTests/TokenAcquirerTests.csproj' - TargetFramework: 'net8.0' - - template: build/template-test-e2e.yaml - parameters: - # Exclude managed-identity E2E tests: they require an MI assigned to the - # host (IMDS), which Microsoft-hosted agents do not have. They run in the - # ManagedIdentityE2E stage below on the MSALMSIV2 VM pool. - e2eTestFilterCriteria: 'Category!=MI_E2E' - -# Managed-identity E2E tests require a VM with an assigned managed identity (IMDS), -# which Microsoft-hosted agents do not have. They run on the MSALMSIV2 VM pool and -# build only the E2E project (.NET 8), independent of the Build stage. -- stage: ManagedIdentityE2E - displayName: 'Managed Identity E2E (MSALMSIV2)' - dependsOn: [] - jobs: - - job: ManagedIdentityE2E - pool: - name: 'MSALMSIV2' - steps: - - template: build/template-run-managed-identity-e2e-tests.yaml - parameters: - TargetFramework: 'net8.0' +trigger: +- master + +pr: + autoCancel: true + branches: + include: + - master + +jobs: +- job: "PR_build" + variables: + # Load the LabAuth client certificate from the local certificate store + # (installed into LocalMachine/My by template-install-dependencies.yaml) + # instead of the msidlabs KeyVault. Microsoft-hosted agents have no managed + # identity that can read the KeyVault, so DefaultAzureCredential would fail. + # The official OneBranch/Wilson pipeline does not set this and keeps using + # the KeyVault source. + UseLabAuthCertFromStore: true + pool: + vmImage: 'windows-2022' + demands: + - msbuild + - visualstudio + steps: + - template: build/template-install-dependencies.yaml + - template: build/template-build.yaml + - template: build/template-run-unit-tests.yaml + parameters: + # Exclude managed-identity E2E tests: they require an MI assigned to the + # host (IMDS), which Microsoft-hosted agents do not have. They still run in + # the official OneBranch pipeline on VM-based agents that have the MI. + e2eTestFilterCriteria: 'Category!=MI_E2E' diff --git a/build/template-build-test-project.yaml b/build/template-build-test-project.yaml deleted file mode 100644 index 477388ec4..000000000 --- a/build/template-build-test-project.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# template-build-test-project.yaml -# Restore and build a single test project (and its project references) for one -# target framework. Used by the independent stages that only need .NET 8, so they -# don't wait on the full multi-TFM solution build. - -parameters: -- name: Project - type: string -- name: BuildConfiguration - type: string - default: 'Release' -- name: TargetFramework - type: string - default: 'net8.0' - -steps: - -- task: DotNetCoreCLI@2 - displayName: 'Restore ${{ parameters.Project }}' - inputs: - command: 'restore' - projects: '${{ parameters.Project }}' - -- task: DotNetCoreCLI@2 - displayName: 'Build ${{ parameters.Project }} (${{ parameters.TargetFramework }})' - inputs: - command: 'build' - projects: '${{ parameters.Project }}' - arguments: '--configuration ${{ parameters.BuildConfiguration }} --framework ${{ parameters.TargetFramework }} --no-restore' diff --git a/build/template-run-managed-identity-e2e-tests.yaml b/build/template-run-managed-identity-e2e-tests.yaml deleted file mode 100644 index e2f20c947..000000000 --- a/build/template-run-managed-identity-e2e-tests.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# template-run-managed-identity-e2e-tests.yaml -# Build the TokenAcquirer E2E project (.NET 8 only) and run the managed-identity -# E2E tests (Category=MI_E2E). These require a VM with an assigned managed -# identity (IMDS), so they run on the MSALMSIV2 pool, not Microsoft-hosted agents. -# Mirrors the MSAL.NET template-run-mi-e2e-imds.yaml approach. - -parameters: -- name: BuildConfiguration - type: string - default: 'Release' -- name: TargetFramework - type: string - default: 'net8.0' - -steps: - -# The repo global.json pins the .NET SDK (10.0.x). Install it so 'dotnet restore' -# succeeds, plus the .NET 8 runtime the tests execute under. -- task: UseDotNet@2 - displayName: 'Use .NET SDK 8.0.x' - inputs: - packageType: 'sdk' - version: '8.0.x' - -- task: UseDotNet@2 - displayName: 'Use .NET SDK from global.json' - inputs: - useGlobalJson: true - -- template: template-build-test-project.yaml - parameters: - Project: 'tests/E2E Tests/TokenAcquirerTests/TokenAcquirerTests.csproj' - BuildConfiguration: '${{ parameters.BuildConfiguration }}' - TargetFramework: '${{ parameters.TargetFramework }}' - -- task: VSTest@2 - displayName: 'Run managed identity E2E tests' - inputs: - testSelector: 'testAssemblies' - testAssemblyVer2: 'tests\E2E Tests\TokenAcquirerTests\bin\${{ parameters.BuildConfiguration }}\${{ parameters.TargetFramework }}\TokenAcquirerTests.dll' - searchFolder: '$(System.DefaultWorkingDirectory)' - testFiltercriteria: 'Category=MI_E2E' - runTestsInIsolation: true - rerunFailedTests: true - rerunMaxAttempts: '3' - runInParallel: false - failOnMinTestsNotRun: true - minimumExpectedTests: '1' diff --git a/build/template-run-unit-tests.yaml b/build/template-run-unit-tests.yaml index c92698c4d..cc7895d7d 100644 --- a/build/template-run-unit-tests.yaml +++ b/build/template-run-unit-tests.yaml @@ -1,9 +1,5 @@ # template-run-unit-tests.yaml -# Aggregator that runs every test suite (unit + integration + E2E) in one job. -# Kept for consumers that want the full suite in a single stage (e.g. the release -# build). The PR pipeline composes the granular templates into separate stages -# instead: template-test-unit.yaml, template-test-integration.yaml and -# template-test-e2e.yaml. +# Run all unit tests across the IdWeb project parameters: # VSTest filter applied to the E2E test run. Empty by default so every consumer @@ -16,10 +12,70 @@ parameters: steps: -- template: template-test-unit.yaml +- task: VSTest@2 + displayName: 'Run unit tests' + inputs: + testSelector: 'testAssemblies' + testAssemblyVer2: 'tests\Microsoft.Identity.Web.Test\bin\**\Microsoft.Identity.Web.Test.dll' + searchFolder: '$(System.DefaultWorkingDirectory)' + runInParallel: true + codeCoverageEnabled: true + failOnMinTestsNotRun: true + minimumExpectedTests: '1' + runSettingsFile: 'build\CodeCoverage.runsettings' -- template: template-test-integration.yaml +- task: VSTest@2 + displayName: 'Run integration tests' + inputs: + testSelector: 'testAssemblies' + testAssemblyVer2: 'tests\Microsoft.Identity.Web.Test.Integration\bin\**\Microsoft.Identity.Web.Test.Integration.dll' + searchFolder: '$(System.DefaultWorkingDirectory)' + rerunFailedTests: true + rerunMaxAttempts: '3' + runInParallel: false + codeCoverageEnabled: true + failOnMinTestsNotRun: false + minimumExpectedTests: '1' + runSettingsFile: 'build\CodeCoverage.runsettings' -- template: template-test-e2e.yaml - parameters: - e2eTestFilterCriteria: '${{ parameters.e2eTestFilterCriteria }}' +- task: VSTest@2 + displayName: 'Run E2E tests' + inputs: + testSelector: 'testAssemblies' + testAssemblyVer2: | + tests\E2E Tests\WebAppUiTests\bin\**\WebAppUiTests.dll + tests\E2E Tests\TokenAcquirerTests\bin\**\TokenAcquirerTests.dll + tests\E2E Tests\NET 7 tests\IntegrationTests\bin\**\IntegrationTests.dll + searchFolder: '$(System.DefaultWorkingDirectory)' + testFiltercriteria: '${{ parameters.e2eTestFilterCriteria }}' + rerunFailedTests: true + rerunMaxAttempts: '3' + runInParallel: false + codeCoverageEnabled: true + failOnMinTestsNotRun: false + minimumExpectedTests: '1' + runSettingsFile: 'build\CodeCoverage.runsettings' + +- task: PublishBuildArtifacts@1 + displayName: 'Publish traces after test' + inputs: + PathtoPublish: '$(Build.SourcesDirectory)/tests/E2E Tests/PlaywrightTraces/' + ArtifactName: 'traces-after-tests-$(Build.BuildNumber)' + condition: failed() + +# Copy all packages out to staging +- task: CopyFiles@2 + displayName: 'Copy screenshots to staging directory' + inputs: + SourceFolder: '$(Build.SourcesDirectory)/tests/E2E Tests/' + Contents: '**/*screenshotFail.png' + TargetFolder: '$(Build.ArtifactStagingDirectory)\screenshots' + flattenFolders: true + condition: failed() + +- task: PublishBuildArtifacts@1 + displayName: 'Publish Screenshot after test' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)\screenshots' + ArtifactName: 'ScreenshotFail' + condition: failed() \ No newline at end of file diff --git a/build/template-test-e2e.yaml b/build/template-test-e2e.yaml deleted file mode 100644 index 5ebb082c5..000000000 --- a/build/template-test-e2e.yaml +++ /dev/null @@ -1,55 +0,0 @@ -# template-test-e2e.yaml -# Run the browser/host E2E tests (Playwright + multi-target). These require the -# full multi-TFM build output, so they run in the build stage. - -parameters: -# VSTest filter applied to the E2E run. Empty by default so the release build runs -# the full suite. The PR build passes 'Category!=MI_E2E' to exclude managed-identity -# tests, which run on the MSALMSIV2 pool in their own stage. -- name: e2eTestFilterCriteria - type: string - default: '' - -steps: - -- task: VSTest@2 - displayName: 'Run E2E tests' - inputs: - testSelector: 'testAssemblies' - testAssemblyVer2: | - tests\E2E Tests\WebAppUiTests\bin\**\WebAppUiTests.dll - tests\E2E Tests\TokenAcquirerTests\bin\**\TokenAcquirerTests.dll - tests\E2E Tests\NET 7 tests\IntegrationTests\bin\**\IntegrationTests.dll - searchFolder: '$(System.DefaultWorkingDirectory)' - testFiltercriteria: '${{ parameters.e2eTestFilterCriteria }}' - rerunFailedTests: true - rerunMaxAttempts: '3' - runInParallel: false - codeCoverageEnabled: true - failOnMinTestsNotRun: false - minimumExpectedTests: '1' - runSettingsFile: 'build\CodeCoverage.runsettings' - -- task: PublishBuildArtifacts@1 - displayName: 'Publish traces after test' - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/tests/E2E Tests/PlaywrightTraces/' - ArtifactName: 'traces-after-tests-$(Build.BuildNumber)' - condition: failed() - -# Copy all packages out to staging -- task: CopyFiles@2 - displayName: 'Copy screenshots to staging directory' - inputs: - SourceFolder: '$(Build.SourcesDirectory)/tests/E2E Tests/' - Contents: '**/*screenshotFail.png' - TargetFolder: '$(Build.ArtifactStagingDirectory)\screenshots' - flattenFolders: true - condition: failed() - -- task: PublishBuildArtifacts@1 - displayName: 'Publish Screenshot after test' - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)\screenshots' - ArtifactName: 'ScreenshotFail' - condition: failed() diff --git a/build/template-test-integration.yaml b/build/template-test-integration.yaml deleted file mode 100644 index 3691c5e8b..000000000 --- a/build/template-test-integration.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# template-test-integration.yaml -# Run the Microsoft.Identity.Web integration tests. Only depend on .NET 8, so a -# consuming stage can build just this project and run in parallel with the build. - -steps: - -- task: VSTest@2 - displayName: 'Run integration tests' - inputs: - testSelector: 'testAssemblies' - testAssemblyVer2: 'tests\Microsoft.Identity.Web.Test.Integration\bin\**\Microsoft.Identity.Web.Test.Integration.dll' - searchFolder: '$(System.DefaultWorkingDirectory)' - rerunFailedTests: true - rerunMaxAttempts: '3' - runInParallel: false - codeCoverageEnabled: true - failOnMinTestsNotRun: false - minimumExpectedTests: '1' - runSettingsFile: 'build\CodeCoverage.runsettings' diff --git a/build/template-test-unit.yaml b/build/template-test-unit.yaml deleted file mode 100644 index 818a09d16..000000000 --- a/build/template-test-unit.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# template-test-unit.yaml -# Run the Microsoft.Identity.Web unit tests. - -steps: - -- task: VSTest@2 - displayName: 'Run unit tests' - inputs: - testSelector: 'testAssemblies' - testAssemblyVer2: | - tests\Microsoft.Identity.Web.Test\bin\**\Microsoft.Identity.Web.Test.dll - tests\Microsoft.Identity.Web.UI.Test\bin\**\Microsoft.Identity.Web.UI.Test.dll - tests\E2E Tests\Sidecar.Tests\bin\**\Sidecar.Tests.dll - tests\E2E Tests\OidcIdPSignedAssertionProviderTests\bin\**\OidcIdpSignedAssertionProviderTests.dll - tests\E2E Tests\CustomSignedAssertionProviderTests\bin\**\CustomSignedAssertionProviderTests.dll - searchFolder: '$(System.DefaultWorkingDirectory)' - # Match the GitHub Action: Sidecar.Tests ships E2E/integration classes that - # need a live sidecar and are excluded there. Skip the same ones here. - testFiltercriteria: 'FullyQualifiedName!~SidecarEndpointsE2ETests&FullyQualifiedName!~SidecarIntegrationTests' - runInParallel: true - codeCoverageEnabled: true - failOnMinTestsNotRun: true - minimumExpectedTests: '1' - runSettingsFile: 'build\CodeCoverage.runsettings' diff --git a/tests/E2E Tests/TokenAcquirerTests/TokenAcquirer.cs b/tests/E2E Tests/TokenAcquirerTests/TokenAcquirer.cs index 7baec1ff1..3dadbc17b 100644 --- a/tests/E2E Tests/TokenAcquirerTests/TokenAcquirer.cs +++ b/tests/E2E Tests/TokenAcquirerTests/TokenAcquirer.cs @@ -561,10 +561,9 @@ public async Task AcquireTokenWithManagedIdentity_UserAssignedAsync() // Arrange const string scope = "https://vault.azure.net/.default"; const string baseUrl = "https://vault.azure.net"; - // User-assigned managed identity "msiv2uami" (RG MSIV2-Testing-MSALNET, - // sub c1686c51-b717-4fe0-9af3-24a20a41fb0c) assigned to the MSALMSIV2 - // VM pool that runs these MI E2E tests. Shared with MSAL.NET E2E tests. - const string clientId = "6325cd32-9911-41f3-819c-416cdf9104e7"; + // User-assigned managed identity "Msal_Integration_tests" (RG MSAL_MSI, sub c1686c51-b717-4fe0-9af3-24a20a41fb0c). + // Shared/consolidated lab UAMI reused across MSAL and Id.Web E2E tests. + const string clientId = "45344e7d-c562-4be6-868f-18dac789c021"; TokenAcquirerFactoryTesting.ResetTokenAcquirerFactoryInTest(); TokenAcquirerFactory tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance(); IServiceProvider serviceProvider = tokenAcquirerFactory.Build();