Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 95 additions & 24 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,98 @@ pr:
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'
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'
29 changes: 29 additions & 0 deletions build/template-build-test-project.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 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'
48 changes: 48 additions & 0 deletions build/template-run-managed-identity-e2e-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# 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'
76 changes: 10 additions & 66 deletions build/template-run-unit-tests.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# template-run-unit-tests.yaml
# Run all unit tests across the IdWeb project
# 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.

parameters:
# VSTest filter applied to the E2E test run. Empty by default so every consumer
Expand All @@ -12,70 +16,10 @@ parameters:

steps:

- 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-unit.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-integration.yaml

- 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()
- template: template-test-e2e.yaml
parameters:
e2eTestFilterCriteria: '${{ parameters.e2eTestFilterCriteria }}'
55 changes: 55 additions & 0 deletions build/template-test-e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# 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()
19 changes: 19 additions & 0 deletions build/template-test-integration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 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'
16 changes: 16 additions & 0 deletions build/template-test-unit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 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'
searchFolder: '$(System.DefaultWorkingDirectory)'
runInParallel: true
codeCoverageEnabled: true
failOnMinTestsNotRun: true
minimumExpectedTests: '1'
runSettingsFile: 'build\CodeCoverage.runsettings'
7 changes: 4 additions & 3 deletions tests/E2E Tests/TokenAcquirerTests/TokenAcquirer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -561,9 +561,10 @@ 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 "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";
// 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";
TokenAcquirerFactoryTesting.ResetTokenAcquirerFactoryInTest();
TokenAcquirerFactory tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
IServiceProvider serviceProvider = tokenAcquirerFactory.Build();
Expand Down
Loading