From 1c697842bd62af13f65a3702999b77873c4be64a Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Mon, 30 Mar 2026 15:51:07 -0700 Subject: [PATCH 01/10] [0.74] Changes to PR, CI, and Release pipelines --- .ado/build-template.yml | 704 ++++++++++++++++++ .ado/ci-pipeline.yml | 29 + .ado/compliance.yml | 105 --- .ado/continuous.yml | 28 - .ado/integrate-rn.yaml | 12 +- .ado/jobs/cli-init-windows.yml | 149 ++-- .ado/jobs/desktop-single.yml | 221 ++++++ .ado/jobs/desktop.yml | 359 --------- .ado/jobs/e2e-test.yml | 264 ++++--- .ado/jobs/linting.yml | 3 - .ado/jobs/node-tests.yml | 1 - .ado/jobs/nuget-desktop.yml | 44 -- .ado/jobs/playground.yml | 61 +- .ado/jobs/setup.yml | 64 -- .ado/jobs/universal-single.yml | 138 ++++ .ado/jobs/universal.yml | 338 --------- .ado/pr-pipeline.yml | 28 + .ado/prepare-release-bot.yml | 7 +- .ado/publish.yml | 516 +------------ .ado/release.yml | 71 +- .ado/stages.yml | 102 --- .ado/templates/cleanup-certificate.yml | 2 +- .../compute-beachball-branch-name.yml | 16 +- .../detect-nuget-lockfile-changes.yml | 22 + .../discover-google-test-adapter.yml | 2 +- .ado/templates/enable-experimental-winui3.yml | 26 + .ado/templates/msbuild-sln.yml | 21 +- .ado/templates/prep-and-pack-nuget.yml | 8 +- .ado/templates/prep-and-pack-single.yml | 6 +- .ado/templates/prepare-build-env.yml | 10 +- .ado/templates/prepare-js-env.yml | 2 +- .ado/templates/publish-build-artifacts.yml | 13 - .ado/templates/publish-nuget-to-ado-feed.yml | 2 +- .ado/templates/react-native-init-windows.yml | 53 +- .ado/templates/run-compliance-postbuild.yml | 14 - .ado/templates/run-compliance-prebuild.yml | 76 -- .ado/templates/run-wack.yml | 2 +- .../run-windows-with-certificates.yml | 1 - .ado/templates/set-appx-platforms.yml | 2 +- .ado/templates/set-experimental-feature.yml | 2 +- .ado/templates/set-version-vars.yml | 1 - .ado/templates/stop-packagers.yml | 1 + .ado/templates/upload-build-logs.yml | 20 +- .ado/templates/verdaccio-start.yml | 16 +- .ado/templates/verdaccio-stop.yml | 10 +- .ado/templates/write-certificate.yml | 2 +- .ado/variables/shared.yml | 6 - .ado/windows-vs-pr-secure.yml | 31 - .ado/windows-vs-pr.yml | 27 +- docs/build-pipelines.md | 105 +++ .../prepare-release/src/beachballBump.ts | 2 +- .../prepare-release/src/prepareRelease.ts | 26 +- 52 files changed, 1667 insertions(+), 2104 deletions(-) create mode 100644 .ado/build-template.yml create mode 100644 .ado/ci-pipeline.yml delete mode 100644 .ado/compliance.yml delete mode 100644 .ado/continuous.yml create mode 100644 .ado/jobs/desktop-single.yml delete mode 100644 .ado/jobs/desktop.yml delete mode 100644 .ado/jobs/nuget-desktop.yml delete mode 100644 .ado/jobs/setup.yml create mode 100644 .ado/jobs/universal-single.yml delete mode 100644 .ado/jobs/universal.yml create mode 100644 .ado/pr-pipeline.yml delete mode 100644 .ado/stages.yml create mode 100644 .ado/templates/detect-nuget-lockfile-changes.yml create mode 100644 .ado/templates/enable-experimental-winui3.yml delete mode 100644 .ado/templates/run-compliance-postbuild.yml delete mode 100644 .ado/templates/run-compliance-prebuild.yml delete mode 100644 .ado/windows-vs-pr-secure.yml create mode 100644 docs/build-pipelines.md diff --git a/.ado/build-template.yml b/.ado/build-template.yml new file mode 100644 index 00000000000..80e14c92903 --- /dev/null +++ b/.ado/build-template.yml @@ -0,0 +1,704 @@ +# +# Shared build and pack template used by CI and PR pipelines. +# CI sets buildEnvironment: Continuous for signed Official builds. +# PR sets buildEnvironment: PullRequest for Unofficial validation builds. +# + +parameters: +- name: buildEnvironment + type: string + default: PullRequest + values: [PullRequest, Continuous] + +- name: isReleaseBuild + type: string + default: auto + values: [auto, 'true', 'false'] + +- name: AgentPool + type: object + default: + Medium: + name: rnw-pool-4-microsoft + demands: ImageOverride -equals rnw-img-vs2022-node22 + Large: + name: rnw-pool-8-microsoft + demands: ImageOverride -equals rnw-img-vs2022-node22 + +- name: desktopBuildMatrix + type: object + default: + # Non-Fabric (Paper) builds + - Name: X64Debug + BuildConfiguration: Debug + BuildPlatform: x64 + UseFabric: false + - Name: X64Release + BuildConfiguration: Release + BuildPlatform: x64 + UseFabric: false + - Name: X86Debug + BuildConfiguration: Debug + BuildPlatform: x86 + UseFabric: false + - Name: X86Release + BuildConfiguration: Release + BuildPlatform: x86 + UseFabric: false + - Name: ARM64ECDebug + BuildConfiguration: Debug + BuildPlatform: ARM64EC + UseFabric: false + - Name: ARM64ECRelease + BuildConfiguration: Release + BuildPlatform: ARM64EC + UseFabric: false + # Fabric (New Architecture) builds + - Name: X64DebugFabric + BuildConfiguration: Debug + BuildPlatform: x64 + UseFabric: true + - Name: X64ReleaseFabric + BuildConfiguration: Release + BuildPlatform: x64 + UseFabric: true + - Name: X86DebugFabric + BuildConfiguration: Debug + BuildPlatform: x86 + UseFabric: true + - Name: X86ReleaseFabric + BuildConfiguration: Release + BuildPlatform: x86 + UseFabric: true + - Name: ARM64ECDebugFabric + BuildConfiguration: Debug + BuildPlatform: ARM64EC + UseFabric: true + - Name: ARM64ECReleaseFabric + BuildConfiguration: Release + BuildPlatform: ARM64EC + UseFabric: true + +- name: universalBuildMatrix + type: object + default: + # Non-Fabric (Paper) builds + - Name: X64Debug + BuildConfiguration: Debug + BuildPlatform: x64 + UseFabric: false + - Name: X64Release + BuildConfiguration: Release + BuildPlatform: x64 + UseFabric: false + - Name: X86Debug + BuildConfiguration: Debug + BuildPlatform: x86 + UseFabric: false + - Name: X86Release + BuildConfiguration: Release + BuildPlatform: x86 + UseFabric: false + - Name: Arm64Debug + BuildConfiguration: Debug + BuildPlatform: ARM64 + UseFabric: false + - Name: Arm64Release + BuildConfiguration: Release + BuildPlatform: ARM64 + UseFabric: false + # Fabric (New Architecture) builds + - Name: X64DebugFabric + BuildConfiguration: Debug + BuildPlatform: x64 + UseFabric: true + - Name: X64ReleaseFabric + BuildConfiguration: Release + BuildPlatform: x64 + UseFabric: true + - Name: X86DebugFabric + BuildConfiguration: Debug + BuildPlatform: x86 + UseFabric: true + - Name: X86ReleaseFabric + BuildConfiguration: Release + BuildPlatform: x86 + UseFabric: true + - Name: Arm64DebugFabric + BuildConfiguration: Debug + BuildPlatform: ARM64 + UseFabric: true + - Name: Arm64ReleaseFabric + BuildConfiguration: Release + BuildPlatform: ARM64 + UseFabric: true + +resources: + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + ${{ if eq(parameters.buildEnvironment, 'Continuous') }}: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + ${{ else }}: + template: v1/1ES.Unofficial.PipelineTemplate.yml@1ESPipelineTemplates + parameters: + pool: ${{ parameters.AgentPool.Medium }} + ${{ if ne(parameters.buildEnvironment, 'Continuous') }}: + settings: + skipBuildTagsForGitHubPullRequests: true + featureFlags: + autoEnablePREfastWithNewRuleset: false # PREfast produces 0 actionable findings; auto-enable injects /analyze into every C++ TU, generating ~2656 SARIF files that Guardian uploads for ~19 min per native build + sdl: + credscan: + suppressionsFile: $(Build.SourcesDirectory)\.ado\config\CredScanSuppressions.json + spotBugs: + enabled: false # We don't have any java, but random packages in node_modules do + prefast: + enabled: false + stages: + #================================================================= + # Stage: Setup + # Detects build scenario, bumps versions (developer builds), + # and publishes version variables for downstream stages. + #================================================================= + - stage: Setup + jobs: + - job: Setup + displayName: Setup + variables: [template: .ado/variables/shared.yml@self] + pool: ${{ parameters.AgentPool.Medium }} + timeoutInMinutes: 60 # CodeQL requires 3x usual build timeout + steps: + # 1. Detect whether this is a release build or a developer build + - pwsh: | + $param = '${{ parameters.isReleaseBuild }}' + $buildReason = $env:BUILD_REASON + $sourceMessage = $env:SOURCE_MESSAGE + $prSourceBranch = $env:PR_SOURCE_BRANCH + + if ($param -eq 'true') { + $isRelease = $true + Write-Host "Release build forced by parameter" + } + elseif ($param -eq 'false') { + $isRelease = $false + Write-Host "Developer build forced by parameter" + } + else { + # Auto-detect + if ($buildReason -eq 'PullRequest') { + # PR: check source branch + $isRelease = $prSourceBranch.StartsWith('prepare-release/') + Write-Host "PR source branch: $prSourceBranch -> isRelease=$isRelease" + } + else { + # CI/Manual: check commit message + $firstLine = ($sourceMessage -split "`n")[0].Trim() + $isRelease = $firstLine.StartsWith("RELEASE:") + Write-Host "Commit message first line: $firstLine -> isRelease=$isRelease" + } + } + + Write-Host "RESULT: isReleaseBuild=$isRelease" + Write-Host "##vso[task.setvariable variable=isReleaseBuild;isOutput=true]$isRelease" + Write-Host "##vso[task.setvariable variable=isReleaseBuild]$isRelease" + name: detectScenario + displayName: Detect build scenario + env: + BUILD_REASON: $(Build.Reason) + SOURCE_MESSAGE: $(Build.SourceVersionMessage) + PR_SOURCE_BRANCH: $(System.PullRequest.SourceBranch) + + # 2. Full checkout (needed for beachball bump on developer builds; + # harmless ~1 min overhead on release builds where bump is skipped) + - template: .ado/templates/checkout-full.yml@self + parameters: + persistCredentials: true + + # 3. Node.js (always needed — setVersionEnvVars.js requires it) + - task: UseNode@1 + inputs: + version: '24.x' + displayName: Use Node.js 24.x + + - template: .ado/templates/compute-beachball-branch-name.yml@self + + # 4. Beachball tooling (developer builds only) + # Inlined from strict-yarn-install.yml because template references + # do not support the condition: keyword. + - pwsh: | + $packageJson = Get-Content ./package.json | ConvertFrom-Json + $packageJson.scripts = $packageJson.scripts | Select-Object * -ExcludeProperty postinstall + $packageJson | ConvertTo-Json | Out-File ./package.json + displayName: Remove postinstall + condition: and(succeeded(), eq(variables['detectScenario.isReleaseBuild'], 'False')) + + - script: npx --yes midgard-yarn-strict@1.2.4 @rnw-scripts/beachball-config + displayName: Strict yarn install @rnw-scripts/beachball-config + condition: and(succeeded(), eq(variables['detectScenario.isReleaseBuild'], 'False')) + + - script: npx lage build --scope @rnw-scripts/prepare-release --scope @rnw-scripts/beachball-config + displayName: Build prepare-release and beachball-config + condition: and(succeeded(), eq(variables['detectScenario.isReleaseBuild'], 'False')) + + # 5. Beachball check (Developer PR only) + - pwsh: npx beachball check --branch "origin/$env:BEACHBALL_BRANCH" --verbose --changehint "##vso[task.logissue type=error]Run 'yarn change' from root of repo to generate a change file." + displayName: Check for change files + condition: and(succeeded(), eq(variables['detectScenario.isReleaseBuild'], 'False'), eq(variables['Build.Reason'], 'PullRequest')) + env: + BEACHBALL_BRANCH: $(BeachBallBranchName) + + # 6. Bump versions via prepare-release (Developer builds only) + - pwsh: npx prepare-release --bump-only --branch "$env:BEACHBALL_BRANCH" --no-color + displayName: Bump versions (prepare-release --bump-only) + condition: and(succeeded(), eq(variables['detectScenario.isReleaseBuild'], 'False')) + env: + BEACHBALL_BRANCH: $(BeachBallBranchName) + + # 7. Read version and set pipeline variables (always) + - template: .ado/templates/set-version-vars.yml@self + parameters: + buildEnvironment: Continuous + + # 8. Include npmPack.js for Release pipeline (CI only) + - script: copy ".ado\scripts\npmPack.js" "$(Build.StagingDirectory)\versionEnvVars\npmPack.js" + displayName: Include npmPack.js in VersionEnvVars artifact + condition: and(succeeded(), eq('${{ parameters.buildEnvironment }}', 'Continuous')) + + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish version variables' + targetPath: $(Build.StagingDirectory)/versionEnvVars + artifactName: VersionEnvVars + + #================================================================= + # Stage: Build + # Shipping builds (Desktop + Universal), ESRP signing, NPM pack, + # linting, and NuGet packing. + #================================================================= + - stage: Build + dependsOn: Setup + jobs: + # Create NPM packages + - job: RnwNpmPack + displayName: Create NPM packages + pool: ${{ parameters.AgentPool.Medium }} + timeoutInMinutes: 120 # CodeQL requires 3x usual build timeout + cancelTimeoutInMinutes: 5 + steps: + - template: .ado/templates/checkout-shallow.yml@self + + - template: .ado/templates/prepare-js-env.yml@self + parameters: + agentImage: HostedImage + + - script: node .ado/scripts/npmPack.js --clean --no-color "$(Pipeline.Workspace)\published-packages" + displayName: Pack npm packages + + - script: dir /s "$(Pipeline.Workspace)\published-packages" + displayName: Show created npm packages + + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish npm pack artifacts' + condition: succeededOrFailed() + targetPath: $(Pipeline.Workspace)/published-packages + artifactName: NpmPackedTarballs + + # Run linting + - template: .ado/jobs/linting.yml@self + parameters: + buildEnvironment: ${{ parameters.buildEnvironment }} + AgentPool: ${{ parameters.AgentPool }} + + # Build, test, and sign Desktop DLLs + - ${{ each matrix in parameters.desktopBuildMatrix }}: + - job: Desktop${{ matrix.Name }} + displayName: Desktop ${{ matrix.Name }} + pool: ${{ parameters.AgentPool.Large }} + timeoutInMinutes: 360 # CodeQL requires 3x usual build timeout + variables: + - template: .ado/variables/windows.yml@self + # Enable if any issues RNTesterIntegrationTests::* become unstable. + - name: Desktop.IntegrationTests.SkipRNTester + value: false + #5059 - Disable failing or intermittent tests (IntegrationTestHarness,WebSocket,Logging). + #10732 - WebSocketIntegrationTest::SendReceiveSsl fails on Windows Server 2022. + #12714 - Disable for first deployment of test website. + #14217 - Reneable RNTesterIntegrationTests + - name: Desktop.IntegrationTests.Filter + value: > + (FullyQualifiedName!=RNTesterIntegrationTests::IntegrationTestHarness)& + (FullyQualifiedName!=RNTesterIntegrationTests::WebSocket)& + (FullyQualifiedName!=RNTesterIntegrationTests::WebSocketBlob)& + (FullyQualifiedName!=RNTesterIntegrationTests::WebSocketMultipleSend)& + (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::ConnectClose)& + (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::ConnectNoClose)& + (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::SendReceiveClose)& + (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::SendConsecutive)& + (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::SendReceiveLargeMessage)& + (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::SendReceiveSsl)& + (FullyQualifiedName!=Microsoft::React::Test::HttpOriginPolicyIntegrationTest)& + (FullyQualifiedName!=RNTesterIntegrationTests::Dummy)& + (FullyQualifiedName!=RNTesterIntegrationTests::Fetch)& + (FullyQualifiedName!=RNTesterIntegrationTests::XHRSample)& + (FullyQualifiedName!=RNTesterIntegrationTests::Blob)& + (FullyQualifiedName!=RNTesterIntegrationTests::Logging) + #6799 - HostFunctionTest, HostObjectProtoTest crash under JSI/V8; + # PreparedJavaScriptSourceTest asserts/fails under JSI/ChakraCore + - name: Desktop.UnitTests.Filter + value: > + (FullyQualifiedName!~HostFunctionTest)& + (FullyQualifiedName!~HostObjectProtoTest)& + (FullyQualifiedName!~PreparedJavaScriptSourceTest) + steps: + # Build and test + - template: .ado/jobs/desktop-single.yml@self + parameters: + buildPlatform: ${{ matrix.BuildPlatform }} + buildConfiguration: ${{ matrix.BuildConfiguration }} + buildEnvironment: ${{ parameters.buildEnvironment }} + useFabric: ${{ matrix.UseFabric }} + + # Stage shipping artifacts (copies to staging dir, does not publish) + # Fabric builds + - ${{ if eq(matrix.UseFabric, true) }}: + - template: .ado/templates/publish-build-artifacts.yml@self + parameters: + artifactName: DesktopFabric + buildPlatform: ${{ matrix.BuildPlatform }} + buildConfiguration: ${{ matrix.BuildConfiguration }} + contents: | + React.Windows.Desktop\** + React.Windows.Desktop.DLL\** + React.Windows.Desktop.Test.DLL\** + + # Non-Fabric builds + - ${{ else }}: + - template: .ado/templates/publish-build-artifacts.yml@self + parameters: + artifactName: Desktop + buildPlatform: ${{ matrix.BuildPlatform }} + buildConfiguration: ${{ matrix.BuildConfiguration }} + contents: | + React.Windows.Desktop\** + React.Windows.Desktop.DLL\** + React.Windows.Desktop.Test.DLL\** + + # ESRP sign (CI only — service connection unavailable in PR/Unofficial mode) + - ${{ if eq(parameters.buildEnvironment, 'Continuous') }}: + - template: .ado/templates/esrp-codesign-binaries.yml@self + parameters: + displayName: 'CodeSign Desktop Binaries' + ${{ if eq(matrix.UseFabric, true) }}: + folderPath: $(Build.StagingDirectory)/NuGet/DesktopFabric/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} + ${{ else }}: + folderPath: $(Build.StagingDirectory)/NuGet/Desktop/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} + pattern: | + **/react-native-win32.dll + + templateContext: + sdl: + prefast: + enabled: false + binskim: + analyzeTargetGlob: '$(Build.SourcesDirectory)\vnext\target\${{ matrix.BuildPlatform }}\${{ matrix.BuildConfiguration }}\React.Windows.Desktop.DLL\react-native-win32.dll' + outputs: + - output: pipelineArtifact + displayName: 'Upload build logs' + condition: succeededOrFailed() + targetPath: $(BuildLogDirectory) + artifactName: Build logs - $(Agent.JobName)-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Upload crash dumps' + condition: and(succeededOrFailed(), eq(variables.HasCrashDumps, 'True')) + targetPath: '$(CrashDumpRootPath)' + artifactName: Crash dumps - $(Agent.JobName)-$(System.JobAttempt) + - ${{ if eq(matrix.UseFabric, true) }}: + - output: pipelineArtifact + displayName: 'Publish Artifact: DesktopFabric.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }}' + artifactName: DesktopFabric.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }} + targetPath: $(Build.StagingDirectory)/NuGet/DesktopFabric/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} + - ${{ else }}: + - output: pipelineArtifact + displayName: 'Publish Artifact: Desktop.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }}' + artifactName: Desktop.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }} + targetPath: $(Build.StagingDirectory)/NuGet/Desktop/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} + + # Build, test, and sign Universal DLLs + - ${{ each matrix in parameters.universalBuildMatrix }}: + - job: Universal${{ matrix.Name }} + displayName: Universal ${{ matrix.Name }} + pool: ${{ parameters.AgentPool.Large }} + timeoutInMinutes: 360 # CodeQL requires 3x usual build timeout + variables: + - template: .ado/variables/windows.yml@self + # Some tasks run on a different user (VssAdministrator) instead of the default user (AzDevOps). + # Keep NuGet cache independent from the user directory. + - name: NUGET_PACKAGES + value: $(Agent.TempDirectory)/NuGetPackages + steps: + # Build and test + - template: .ado/jobs/universal-single.yml@self + parameters: + buildPlatform: ${{ matrix.BuildPlatform }} + buildConfiguration: ${{ matrix.BuildConfiguration }} + buildEnvironment: ${{ parameters.buildEnvironment }} + useFabric: ${{ matrix.UseFabric }} + + # Stage shipping artifacts (copies to staging dir, does not publish) + # Fabric builds — artifact name: ReactWindowsFabric + - ${{ if eq(matrix.UseFabric, true) }}: + - template: .ado/templates/publish-build-artifacts.yml@self + parameters: + artifactName: ReactWindowsFabric + buildPlatform: ${{ matrix.BuildPlatform }} + buildConfiguration: ${{ matrix.BuildConfiguration }} + contents: | + Microsoft.ReactNative\Microsoft.ReactNative.* + Microsoft.ReactNative.CsWinRT\Microsoft.ReactNative.Projection.* + + # Non-Fabric builds — artifact name: ReactWindows (include managed code for NuGet) + - ${{ else }}: + - template: .ado/templates/publish-build-artifacts.yml@self + parameters: + artifactName: ReactWindows + buildPlatform: ${{ matrix.BuildPlatform }} + buildConfiguration: ${{ matrix.BuildConfiguration }} + contents: | + Microsoft.ReactNative\Microsoft.ReactNative.* + Microsoft.ReactNative.CsWinRT\Microsoft.ReactNative.Projection.* + Microsoft.ReactNative.Managed\** + Microsoft.ReactNative.Managed.CodeGen\** + + # ESRP sign (CI only — service connection unavailable in PR/Unofficial mode) + - ${{ if eq(parameters.buildEnvironment, 'Continuous') }}: + - template: .ado/templates/esrp-codesign-binaries.yml@self + parameters: + displayName: 'CodeSign Microsoft.ReactNative Binaries' + ${{ if eq(matrix.UseFabric, true) }}: + folderPath: $(Build.StagingDirectory)/NuGet/ReactWindowsFabric/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} + ${{ else }}: + folderPath: $(Build.StagingDirectory)/NuGet/ReactWindows/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} + pattern: | + **/Microsoft.ReactNative.dll + **/Microsoft.ReactNative.winmd + **/Microsoft.ReactNative.Projection.dll + + templateContext: + sdl: + prefast: + enabled: false + binskim: + analyzeTargetGlob: '$(Build.SourcesDirectory)\vnext\target\${{ matrix.BuildPlatform }}\${{ matrix.BuildConfiguration }}\Microsoft.ReactNative\Microsoft.ReactNative.dll' + outputs: + - output: pipelineArtifact + displayName: 'Upload build logs' + condition: succeededOrFailed() + targetPath: $(BuildLogDirectory) + artifactName: Build logs - $(Agent.JobName)-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Upload crash dumps' + condition: and(succeededOrFailed(), eq(variables.HasCrashDumps, 'True')) + targetPath: '$(CrashDumpRootPath)' + artifactName: Crash dumps - $(Agent.JobName)-$(System.JobAttempt) + - ${{ if eq(matrix.UseFabric, true) }}: + - output: pipelineArtifact + displayName: 'Publish Artifact: ReactWindowsFabric.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }}' + artifactName: ReactWindowsFabric.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }} + targetPath: $(Build.StagingDirectory)/NuGet/ReactWindowsFabric/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} + - ${{ else }}: + - output: pipelineArtifact + displayName: 'Publish Artifact: ReactWindows.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }}' + artifactName: ReactWindows.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }} + targetPath: $(Build.StagingDirectory)/NuGet/ReactWindows/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} + + # Create NuGet packages + - job: RNWNuget + displayName: Pack NuGet + dependsOn: + - RnwNpmPack + - Linting + - ${{ each matrix in parameters.desktopBuildMatrix }}: + - Desktop${{ matrix.Name }} + - ${{ each matrix in parameters.universalBuildMatrix }}: + - Universal${{ matrix.Name }} + pool: ${{ parameters.AgentPool.Medium }} + timeoutInMinutes: 60 # Protect against the long CodeSign task + + steps: + - template: .ado/templates/checkout-shallow.yml@self + + - template: .ado/templates/prepare-js-env.yml@self + + - template: .ado/templates/apply-published-version-vars.yml@self + + # The commit tag in the nuspec requires that we use at least nuget 5.8 (because things break with nuget versions before and VS 16.8 or later) + - task: NuGetToolInstaller@1 + inputs: + versionSpec: ">=5.8.0" + + # Pack 1: ReactWindows (non-Fabric) + - template: .ado/templates/prep-and-pack-nuget.yml@self + parameters: + artifactName: ReactWindows + publishCommitId: $(publishCommitId) + npmVersion: $(npmVersion) + packMicrosoftReactNative: true + packMicrosoftReactNativeCxx: true + packMicrosoftReactNativeManaged: true + packMicrosoftReactNativeManagedCodeGen: true + slices: + - platform: x64 + configuration: Release + - platform: x86 + configuration: Release + - platform: ARM64 + configuration: Release + - platform: x64 + configuration: Debug + - platform: x86 + configuration: Debug + - platform: ARM64 + configuration: Debug + + # Pack 2: ReactWindowsFabric + - template: .ado/templates/prep-and-pack-nuget.yml@self + parameters: + artifactName: ReactWindowsFabric + publishCommitId: $(publishCommitId) + npmVersion: $(npmVersion)-Fabric + packMicrosoftReactNative: true + packMicrosoftReactNativeCxx: true + slices: + - platform: x64 + configuration: Release + - platform: x86 + configuration: Release + - platform: ARM64 + configuration: Release + - platform: x64 + configuration: Debug + - platform: x86 + configuration: Debug + - platform: ARM64 + configuration: Debug + + # Pack 3: Desktop (non-Fabric) + - template: .ado/templates/prep-and-pack-nuget.yml@self + parameters: + artifactName: Desktop + publishCommitId: $(publishCommitId) + npmVersion: $(npmVersion) + packDesktop: true + slices: + - platform: x64 + configuration: Release + - platform: x86 + configuration: Release + - platform: ARM64EC + configuration: Release + - platform: x64 + configuration: Debug + - platform: x86 + configuration: Debug + - platform: ARM64EC + configuration: Debug + + # Pack 4: DesktopFabric + - template: .ado/templates/prep-and-pack-nuget.yml@self + parameters: + artifactName: DesktopFabric + publishCommitId: $(publishCommitId) + npmVersion: $(npmVersion)-Fabric + packDesktop: true + slices: + - platform: x64 + configuration: Release + - platform: x86 + configuration: Release + - platform: ARM64EC + configuration: Release + - platform: x64 + configuration: Debug + - platform: x86 + configuration: Debug + - platform: ARM64EC + configuration: Debug + + # ESRP sign (CI only — service connection unavailable in PR/Unofficial mode) + - ${{ if eq(parameters.buildEnvironment, 'Continuous') }}: + - template: .ado/templates/esrp-codesign-nuget.yml@self + parameters: + displayName: 'CodeSign all NuGet packages' + folderPath: $(System.DefaultWorkingDirectory)/NugetRootFinal + pattern: '**/*.nupkg' + + # Tag the source commit when a RELEASE build succeeds (CI only) + - ${{ if eq(parameters.buildEnvironment, 'Continuous') }}: + - pwsh: | + $tag = "react-native-windows_v$(npmVersion)" + Write-Host "Creating tag $tag on $(Build.SourceVersion)" + $authHeader = "AUTHORIZATION: bearer $env:SYSTEM_ACCESSTOKEN" + Write-Host "##vso[task.setsecret]$authHeader" + git -c http.extraheader="$authHeader" tag $tag "$(Build.SourceVersion)" + git -c http.extraheader="$authHeader" push origin $tag + displayName: Tag release sources + condition: and(succeeded(), startsWith(variables['Build.SourceVersionMessage'], 'RELEASE:')) + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + + templateContext: + sdl: + binskim: + analyzeTargetGlob: '$(System.DefaultWorkingDirectory)\NugetRoot\**\Microsoft.ReactNative\Microsoft.ReactNative.dll;$(System.DefaultWorkingDirectory)\NugetRoot\**\React.Windows.Desktop.DLL\react-native-win32.dll' + outputs: + - output: pipelineArtifact + displayName: 'Publish final nuget artifacts' + targetPath: $(System.DefaultWorkingDirectory)\NugetRootFinal + artifactName: "ReactWindows-final-nuget" + + #================================================================= + # Stage: Tests + # Independent test jobs that don't require native build artifacts. + # Runs in parallel with Build stage (both depend only on Setup). + #================================================================= + - stage: Tests + displayName: Tests + dependsOn: Setup + jobs: + - template: .ado/jobs/node-tests.yml@self + parameters: + buildEnvironment: ${{ parameters.buildEnvironment }} + AgentPool: ${{ parameters.AgentPool }} + + - template: .ado/jobs/playground.yml@self + parameters: + buildEnvironment: ${{ parameters.buildEnvironment }} + AgentPool: ${{ parameters.AgentPool }} + + - template: .ado/jobs/e2e-test.yml@self + parameters: + buildEnvironment: ${{ parameters.buildEnvironment }} + AgentPool: ${{ parameters.AgentPool }} + + #================================================================= + # Stage: CLI + # CLI init verification — tests the final NuGet + npm packages. + # Runs after Build stage completes (needs RNWNuget artifacts). + #================================================================= + - stage: CLI + displayName: CLI + dependsOn: Build + jobs: + - template: .ado/jobs/cli-init-windows.yml@self + parameters: + buildEnvironment: ${{ parameters.buildEnvironment }} + AgentPool: ${{ parameters.AgentPool }} + diff --git a/.ado/ci-pipeline.yml b/.ado/ci-pipeline.yml new file mode 100644 index 00000000000..f7b84b8ff3f --- /dev/null +++ b/.ado/ci-pipeline.yml @@ -0,0 +1,29 @@ +# +# The CI pipeline entry point. +# Extends build-template.yml with buildEnvironment: Continuous for signed Official builds. +# + +name: 0.0.$(Date:yyMM.d)$(Rev:rrr) + +trigger: none +pr: none + +parameters: + - name: isReleaseBuild + displayName: 'Treat as Release build (skip beachball, use committed versions)' + type: string + default: auto + values: + - auto + - 'true' + - 'false' + +variables: + - template: variables/windows.yml + - group: RNW Secrets + +extends: + template: build-template.yml@self + parameters: + buildEnvironment: Continuous + isReleaseBuild: ${{ parameters.isReleaseBuild }} diff --git a/.ado/compliance.yml b/.ado/compliance.yml deleted file mode 100644 index 415cf0e0ba5..00000000000 --- a/.ado/compliance.yml +++ /dev/null @@ -1,105 +0,0 @@ -name: 0.0.$(Date:yyMM.d)$(Rev:rrr) - -parameters: -- name: AgentPool - type: object - default: - Medium: - name: rnw-pool-4-microsoft - demands: ImageOverride -equals rnw-img-vs2022-node22 - Large: - name: rnw-pool-8-microsoft - demands: ImageOverride -equals rnw-img-vs2022-node22 -- name: forceCodeQL - displayName: Force CodeQL to rebuild databases - type: boolean - default: false -- name: complianceWarnOnly - displayName: Convert compliance errors to warnings - type: boolean - default: true # Let's get all results in this pipeline - -variables: - - template: variables/windows.yml - - group: RNW Secrets - - name: Codeql.Enabled - value: true - - ${{ if eq(parameters.forceCodeQL, true) }}: - - name: Codeql.Cadence - value: 0 - - ${{ if eq(parameters.forceCodeQL, false) }}: - - name: Codeql.Cadence - value: 120 # In hours, default to only run every 5 days - -trigger: none -pr: none - -jobs: - - job: RnwUniversalCompliance - displayName: RNW Universal Compliance - pool: ${{ parameters.AgentPool.Large }} - timeoutInMinutes: 360 # Compliance tasks recommend to 3x usual build timeout - - steps: - - template: templates/checkout-shallow.yml - - - template: templates/prepare-js-env.yml - - - template: templates/set-version-vars.yml - parameters: - buildEnvironment: Continuous - - - template: templates/publish-version-vars.yml - - - template: templates/prepare-build-env.yml - parameters: - platform: x64 - configuration: Release - buildEnvironment: Continuous - - - template: templates/apply-published-version-vars.yml - - # Pre-build compliance tasks - - - template: templates/run-compliance-prebuild.yml - parameters: - complianceWarnOnly: ${{ parameters.complianceWarnOnly }} - - - task: NuGetAuthenticate@1 - - # AgentES Task (https://aka.ms/UES) - # Installs and runs the "Agent ES" tool, which scans the source code for banned file types. - - powershell: | - & nuget.exe install AgentES -FallbackSource https://microsoft.pkgs.visualstudio.com/_packaging/Undocked.Shell.Services/nuget/v3/index.json - $AgentESPath = (Get-ChildItem -Path AgentES* -Filter AgentES.exe -Recurse | %{$_.FullName}) - & $AgentESPath $env:BUILD_SOURCESDIRECTORY -e:$env:BUILD_SOURCESDIRECTORY\.ado\config\AgentES.Exemptions.json -b - displayName: "⚖️ AgentES - Scan of Repository for UES Policy Violations" - workingDirectory: $(Agent.BuildDirectory) - continueOnError: ${{ parameters.complianceWarnOnly }} - - # Initialize CodeQL 3000 Task (https://aka.ms/codeql3000) - # Performs static code analysis. - - task: CodeQL3000Init@0 - displayName: "🛡️ Initialize CodeQL" - continueOnError: ${{ parameters.complianceWarnOnly }} - - # Build RNW - - - template: templates/msbuild-sln.yml - parameters: - solutionDir: vnext - solutionName: Microsoft.ReactNative.sln - buildPlatform: x64 - buildConfiguration: Release - - # Post-build compliance tasks - - - template: templates/run-compliance-postbuild.yml - parameters: - complianceWarnOnly: ${{ parameters.complianceWarnOnly }} - - # Finalize CodeQL 3000 Task (https://aka.ms/codeql3000) - # Performs static code analysis. - - task: CodeQL3000Finalize@0 - displayName: "🛡️ Finalize CodeQL" - continueOnError: ${{ parameters.complianceWarnOnly }} diff --git a/.ado/continuous.yml b/.ado/continuous.yml deleted file mode 100644 index f20e680ad11..00000000000 --- a/.ado/continuous.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: RNW CI $(Date:yyyyMMdd).$(Rev:r) - -trigger: none # will disable CI builds entirely -pr: none - -variables: - - group: RNW Secrets - - group: platform-override-zero-permission-token - -parameters: - - name: AgentPool - type: object - default: - Small: - name: rnw-pool-2 - demands: ImageOverride -equals rnw-img-vs2022-node22 - Medium: - name: rnw-pool-4 - demands: ImageOverride -equals rnw-img-vs2022-node22 - Large: - name: rnw-pool-8 - demands: ImageOverride -equals rnw-img-vs2022-node22 - -stages: - - template: stages.yml - parameters: - buildEnvironment: Continuous - AgentPool: ${{ parameters.AgentPool }} diff --git a/.ado/integrate-rn.yaml b/.ado/integrate-rn.yaml index 092d0424f76..b9ec5384ada 100644 --- a/.ado/integrate-rn.yaml +++ b/.ado/integrate-rn.yaml @@ -33,7 +33,7 @@ jobs: displayName: yarn integrate-rn continueOnError: true - - powershell: | + - pwsh: | if (!(Test-Path "$(Agent.TempDirectory)\integration-report.md")) { dir "$(Agent.TempDirectory)" throw "No integration report generated" @@ -43,7 +43,7 @@ jobs: } displayName: Test for changes - - powershell: | + - pwsh: | $reportWithHeader = "${{ parameters.commitTitle}}`n`n" + (Get-Content -Raw $(Agent.TempDirectory)\integration-report.md) # Trim to max GitHub PR length $trimmedReport = $reportWithHeader.substring(0, [math]::min(65536, $reportWithHeader.length)) @@ -55,12 +55,12 @@ jobs: git commit -F $(Agent.TempDirectory)\commit-message.md displayName: Commit changes - - powershell: | + - pwsh: | $commitHash = git log --format=%H -n 1 Write-Output "##vso[task.setvariable variable=FirstCommit]$commitHash" displayName: Save base commit - - powershell: | + - pwsh: | $patchScope = node -e " const path = require('path'); const {enumerateRepoPackages} = require('@react-native-windows/package-utils'); @@ -72,7 +72,7 @@ jobs: yarn change --scope @($patchScope.split(',')) --message "${{ parameters.commitTitle}}" --type patch displayName: Create patch changefiles - - powershell: | + - pwsh: | $prereleaseScope = node -e " const path = require('path'); const {enumerateRepoPackages} = require('@react-native-windows/package-utils'); @@ -93,7 +93,7 @@ jobs: - script: git push origin integrate-${{ parameters.reactNativeVersion }} displayName: Push changes - - powershell: | + - pwsh: | $headers = @{'Accept'='application/vnd.github.v3+json'; 'Authorization'='Token $(githubAuthToken)'} $body = '{"head": "integrate-${{ parameters.reactNativeVersion }}", "base": "main", "title": "${{ parameters.commitTitle}}"}' Invoke-WebRequest -Method Post -Headers $headers -Body $body https://api.github.com/repos/microsoft/react-native-windows/pulls diff --git a/.ado/jobs/cli-init-windows.yml b/.ado/jobs/cli-init-windows.yml index 85475526370..c3136adc68a 100644 --- a/.ado/jobs/cli-init-windows.yml +++ b/.ado/jobs/cli-init-windows.yml @@ -4,97 +4,44 @@ parameters: default: PullRequest values: - PullRequest - - SecurePullRequest - Continuous - name: AgentPool type: object - - name: buildNuGetOnly - type: boolean - default: false - name: buildMatrix type: object default: - BuildEnvironment: PullRequest Matrix: - - Name: FabricX64Debug - template: cpp-app - configuration: Debug - platform: x64 - additionalRunArguments: --no-autolink - useNuGet: true - Name: FabricX64Release template: cpp-app configuration: Release platform: x64 additionalRunArguments: --no-autolink - useNuGet: true - Name: FabricX86Debug template: cpp-app configuration: Debug platform: x86 additionalRunArguments: --no-autolink - useNuGet: true - - Name: FabricX86Release - template: cpp-app - configuration: Release - platform: x86 - useNuGet: true - - Name: FabricArm64Debug - template: cpp-app - configuration: Debug - platform: ARM64 - additionalRunArguments: --no-autolink --no-deploy - useNuGet: true - Name: FabricArm64Release template: cpp-app configuration: Release platform: ARM64 additionalRunArguments: --no-autolink --no-deploy - useNuGet: true - - Name: FabricLibX64Debug - template: cpp-lib - configuration: Debug - platform: x64 - additionalRunArguments: --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - Name: FabricLibX64Release template: cpp-lib configuration: Release platform: x64 additionalRunArguments: --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - Name: FabricLibX86Debug template: cpp-lib configuration: Debug platform: x86 additionalRunArguments: --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - - Name: FabricLibX86Release - template: cpp-lib - configuration: Release - platform: x86 - additionalRunArguments: --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - - Name: FabricLibArm64Debug - template: cpp-lib - configuration: Debug - platform: ARM64 - additionalRunArguments: --no-deploy --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - Name: FabricLibArm64Release template: cpp-lib configuration: Release platform: ARM64 additionalRunArguments: --no-deploy --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - - BuildEnvironment: SecurePullRequest - Matrix: - - Name: FabricX64Release - template: cpp-app - configuration: Release - platform: x64 - additionalRunArguments: --no-autolink - useNuGet: true - BuildEnvironment: Continuous Matrix: - Name: FabricX64Debug @@ -102,120 +49,112 @@ parameters: configuration: Debug platform: x64 additionalRunArguments: --no-autolink - useNuGet: true - Name: FabricX64Release template: cpp-app configuration: Release platform: x64 additionalRunArguments: --no-autolink - useNuGet: true - Name: FabricX86Debug template: cpp-app configuration: Debug platform: x86 additionalRunArguments: --no-autolink - useNuGet: true - Name: FabricX86Release template: cpp-app configuration: Release platform: x86 - useNuGet: true - Name: FabricArm64Debug template: cpp-app configuration: Debug platform: ARM64 additionalRunArguments: --no-autolink --no-deploy - useNuGet: true - Name: FabricArm64Release template: cpp-app configuration: Release platform: ARM64 additionalRunArguments: --no-autolink --no-deploy - useNuGet: true - Name: FabricLibX64Debug template: cpp-lib configuration: Debug platform: x64 additionalRunArguments: --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - Name: FabricLibX64Release template: cpp-lib configuration: Release platform: x64 additionalRunArguments: --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - Name: FabricLibX86Debug template: cpp-lib configuration: Debug platform: x86 additionalRunArguments: --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - Name: FabricLibX86Release template: cpp-lib configuration: Release platform: x86 additionalRunArguments: --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - Name: FabricLibArm64Debug template: cpp-lib configuration: Debug platform: ARM64 additionalRunArguments: --no-deploy --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true - Name: FabricLibArm64Release template: cpp-lib configuration: Release platform: ARM64 additionalRunArguments: --no-deploy --singleproc # --singleproc required to workaround issue #13599 - useNuGet: true jobs: - ${{ each config in parameters.buildMatrix }}: - ${{ if eq(config.BuildEnvironment, parameters.buildEnvironment) }}: - ${{ each matrix in config.Matrix }}: - - ${{ if eq(coalesce(matrix.useNuGet, false), parameters.buildNuGetOnly) }}: - - job: CliInitWindows${{ matrix.Name }} - displayName: Verify CliInitWindows ${{ matrix.Name }} + - job: CliInitWindows${{ matrix.Name }} + displayName: Verify CliInitWindows ${{ matrix.Name }} + + # No job-level dependsOn needed — the CLI stage depends on the Build stage, + # which guarantees all build artifacts are available before CLI jobs start. - ${{ if eq(matrix.useNuGet, true) }}: - dependsOn: - - UniversalBuild${{ matrix.platform }}ReleaseFabric + variables: [template: ../variables/windows.yml] - variables: [template: ../variables/windows.yml] + pool: ${{ parameters.AgentPool.Medium }} + timeoutInMinutes: 60 + cancelTimeoutInMinutes: 5 - ${{ if eq(matrix.lowResource, true) }}: - pool: ${{ parameters.AgentPool.Small }} - ${{ else }}: - pool: ${{ parameters.AgentPool.Medium }} - timeoutInMinutes: 60 - cancelTimeoutInMinutes: 5 + steps: + - template: ../templates/checkout-full.yml + parameters: + persistCredentials: false # We don't need git creds in this job - steps: - - template: ../templates/checkout-full.yml - parameters: - persistCredentials: false # We don't need git creds in this job + - template: ../templates/prepare-js-env.yml - - template: ../templates/prepare-js-env.yml + - template: ../templates/prepare-build-env.yml + parameters: + platform: ${{ matrix.platform }} + configuration: ${{ matrix.configuration }} + buildEnvironment: ${{ parameters.buildEnvironment }} - - template: ../templates/prepare-build-env.yml - parameters: - platform: ${{ parameters.platform }} - configuration: ${{ parameters.configuration }} - buildEnvironment: ${{ parameters.buildEnvironment }} + - task: CmdLine@2 + displayName: Create npm directory + name: createNpmDirectory + inputs: + script: mkdir %APPDATA%\npm - - task: CmdLine@2 - displayName: Create npm directory - name: createNpmDirectory - inputs: - script: mkdir %APPDATA%\npm - - - template: ../templates/react-native-init-windows.yml - parameters: - template: ${{ matrix.template }} - configuration: ${{ matrix.configuration }} - platform: ${{ matrix.platform }} - additionalInitArguments: ${{ matrix.additionalInitArguments }} - additionalRunArguments: ${{ matrix.additionalRunArguments }} - runWack: ${{ coalesce(matrix.runWack, false) }} - buildEnvironment: ${{ parameters.buildEnvironment }} - useChakra: ${{ coalesce(matrix.useChakra, false) }} - useNuGet: ${{ coalesce(matrix.useNuGet, false) }} \ No newline at end of file + - template: ../templates/react-native-init-windows.yml + parameters: + template: ${{ matrix.template }} + configuration: ${{ matrix.configuration }} + platform: ${{ matrix.platform }} + additionalInitArguments: ${{ matrix.additionalInitArguments }} + additionalRunArguments: ${{ matrix.additionalRunArguments }} + buildEnvironment: ${{ parameters.buildEnvironment }} + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Upload traces' + condition: succeededOrFailed() + targetPath: $(Build.StagingDirectory)/Tracing + artifactName: Traces - $(Agent.JobName)-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Upload Verdaccio.log (on failure)' + condition: failed() + targetPath: verdaccio.log + artifactName: $(Agent.JobName).Verdaccio.log-$(System.JobAttempt) \ No newline at end of file diff --git a/.ado/jobs/desktop-single.yml b/.ado/jobs/desktop-single.yml new file mode 100644 index 00000000000..fc3ebe9a4c1 --- /dev/null +++ b/.ado/jobs/desktop-single.yml @@ -0,0 +1,221 @@ +# +# Step template: Build and test one Desktop platform/config combination. +# Called from build-template.yml which owns the job definition, artifact +# publishing, ESRP signing, and templateContext. +# +# Note: Desktop test filter variables (Desktop.IntegrationTests.Filter, +# Desktop.UnitTests.Filter, Desktop.IntegrationTests.SkipRNTester) must +# be defined at the job level in build-template.yml. +# + +parameters: + - name: buildPlatform + type: string + - name: buildConfiguration + type: string + - name: buildEnvironment + type: string + default: PullRequest + values: + - PullRequest + - Continuous + - name: useFabric + type: boolean + default: false + +steps: + # Set up IIS for integration tests + - pwsh: | + Install-WindowsFeature -Name Web-Server, Web-Scripting-Tools + displayName: Install IIS + + - pwsh: | + Invoke-WebRequest ` + -Uri 'https://download.visualstudio.microsoft.com/download/pr/20598243-c38f-4538-b2aa-af33bc232f80/ea9b2ca232f59a6fdc84b7a31da88464/dotnet-hosting-8.0.3-win.exe' ` + -OutFile dotnet-hosting-8.0.3-win.exe + + Write-Host 'Installing .NET hosting bundle' + Start-Process -Wait -FilePath .\dotnet-hosting-8.0.3-win.exe -ArgumentList '/INSTALL', '/QUIET', '/NORESTART' + Write-Host 'Installed .NET hosting bundle' + + Invoke-WebRequest ` + -Uri 'https://download.visualstudio.microsoft.com/download/pr/f2ec926e-0d98-4a8b-8c70-722ccc2ca0e5/b59941b0c60f16421679baafdb7e9338/dotnet-sdk-7.0.407-win-x64.exe' ` + -OutFile dotnet-sdk-7.0.407-win-x64.exe + + Write-Host 'Installing .NET 7 SDK' + Start-Process -Wait -FilePath .\dotnet-sdk-7.0.407-win-x64.exe -ArgumentList '/INSTALL', '/QUIET', '/NORESTART' + Write-Host 'Installed .NET 7 SDK' + displayName: Install the .NET Core Hosting Bundle + + - template: ../templates/checkout-shallow.yml + + - template: ../templates/prepare-js-env.yml + + - template: ../templates/prepare-build-env.yml + parameters: + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.buildConfiguration }} + buildEnvironment: ${{ parameters.buildEnvironment }} + + - template: ../templates/apply-published-version-vars.yml + + - ${{ if eq(parameters.useFabric, true) }}: + - template: ../templates/enable-fabric-experimental-feature.yml + + - ${{ if eq(variables['Desktop.IntegrationTests.SkipRNTester'], true) }}: + - pwsh: | + $newValue = '(FullyQualifiedName!~RNTesterIntegrationTests::)&' + "$(Desktop.IntegrationTests.Filter)" + Write-Host "##vso[task.setvariable variable=Desktop.IntegrationTests.Filter]$newValue" + displayName: Update Desktop.IntegrationTests.Filter to exclude RNTester integration tests + + - template: ../templates/msbuild-sln.yml + parameters: + solutionDir: vnext + solutionName: ReactWindows-Desktop.sln + buildPlatform: ${{ parameters.buildPlatform }} + buildConfiguration: ${{ parameters.buildConfiguration }} + msbuildArguments: /p:ForceImportAfterCppTargets=$(Build.SourcesDirectory)\vnext\PropertySheets\CIBuildOptimizations.props + + - ${{ if and(eq(parameters.buildConfiguration, 'Debug'), eq(parameters.buildPlatform, 'x64')) }}: + - script: yarn bundle + displayName: Build react-native-win32 RNTester bundle + workingDirectory: packages/@office-iss/react-native-win32 + + - ${{ if eq(parameters.buildEnvironment, 'Continuous') }}: + - template: ../templates/component-governance.yml + + # --- Tests --- + - template: ../templates/discover-google-test-adapter.yml + + - ${{ if ne(parameters.buildPlatform, 'ARM64EC') }}: + - task: VSTest@2 + displayName: Run Desktop Unit Tests + timeoutInMinutes: 5 # Set smaller timeout, due to hangs + inputs: + testSelector: testAssemblies + testAssemblyVer2: | + React.Windows.Desktop.UnitTests/React.Windows.Desktop.UnitTests.dll + # Bug #8000: Tracks fixing the tests + # ReactCommon.UnitTests/ReactCommon.UnitTests.exe + pathtoCustomTestAdapters: $(GoogleTestAdapterPath) + searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ parameters.buildPlatform }}/${{ parameters.buildConfiguration }} + testFiltercriteria: $(Desktop.UnitTests.Filter) + runTestsInIsolation: true + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.buildConfiguration }} + publishRunAttachments: true + collectDumpOn: onAbortOnly + vsTestVersion: latest + failOnMinTestsNotRun: true + + # Suspected debug assert in TestRunner hanging tests randomly. Run only on Release for now. + - ${{ if and(eq(parameters.buildConfiguration, 'Release'), ne(variables['Desktop.IntegrationTests.SkipRNTester'], true), ne(parameters.buildPlatform, 'ARM64EC')) }}: + - task: PowerShell@2 + displayName: Set up test servers + inputs: + targetType: filePath + filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tfs\Start-TestServers.ps1 + arguments: -SourcesDirectory $(Build.SourcesDirectory)\vnext -Preload -SleepSeconds 120 + pwsh: true + + - task: DotNetCoreCLI@2 + displayName: Publish Test Website + inputs: + command: publish + publishWebProjects: false + zipAfterPublish: false + projects: $(Build.SourcesDirectory)\vnext\TestWebsite\Microsoft.ReactNative.Test.Website.csproj + arguments: --configuration ${{ parameters.buildConfiguration }} + + - pwsh: | + # Create and make available to IIS + $cert = New-SelfSignedCertificate ` + -Type SSLServerAuthentication ` + -KeyExportPolicy Exportable ` + -Subject 'CN=localhost' ` + -NotAfter ([DateTime]::Now).AddHours(2) ` + -CertStoreLocation Cert:\LocalMachine\My\ + + $certPath = "${env:TEMP}\localhost.pfx" + $certPass = -join ('a'..'z' | Get-Random -Count 32) | ConvertTo-SecureString -AsPlainText -Force + $certHash = $cert.Thumbprint + Write-Host "##vso[task.setvariable variable=TestWebsiteCertificateThumbprint]$certHash" + + # Export PFX + $cert | Export-PfxCertificate -FilePath $certPath -Password $certPass + + # Trust globally + Import-PfxCertificate ` + -Exportable ` + -FilePath $certPath ` + -Password $certPass ` + -CertStoreLocation Cert:\LocalMachine\Root\ + displayName: Install SSL Certificate + + - task: IISWebAppManagementOnMachineGroup@0 + displayName: Create Test Website + inputs: + EnableIIS: false + IISDeploymentType: IISWebsite + ActionIISWebsite: CreateOrUpdateWebsite + SSLCertThumbPrint: $(TestWebsiteCertificateThumbprint) + WebsiteName: RNW Test Website + # Hard-coding x64 for publish path. + # Our MSBuild customizations cause dotnet commands to assume the default PlatformTarget + WebsitePhysicalPath: $(Build.SourcesDirectory)\vnext\target\x64\${{ parameters.buildConfiguration }}\Microsoft.ReactNative.Test.Website\Publish + WebsitePhysicalPathAuth: WebsiteUserPassThrough + CreateOrUpdateAppPoolForWebsite: false + ConfigureAuthenticationForWebsite: false + AppPoolNameForWebsite: DefaultAppPool + AddBinding: true + Bindings: | + { + bindings: [ + { + "protocol": "http", + "ipAddress": "*", + "port": "5555", + "sslThumbprint": "", + "sniFlag": false + }, + { + "protocol": "https", + "ipAddress": "*", + "port": "5543", + "sslThumbprint": "$(TestWebsiteCertificateThumbprint)", + "sniFlag": false + } + ] + } + + - task: PowerShell@2 + displayName: Ensure servers readiness + inputs: + targetType: 'inline' + pwsh: true + script: | + # Test website + Invoke-WebRequest -UseBasicParsing -Uri 'http://localhost:5555' + Invoke-WebRequest -UseBasicParsing -Uri 'https://localhost:5543' + + # Bundler + Invoke-WebRequest -UseBasicParsing -Uri "http://localhost:8081/IntegrationTests/IntegrationTestsApp.bundle?platform=windows&dev=true" + continueOnError: true + + - task: VSTest@2 + displayName: Run Desktop Integration Tests + inputs: + testSelector: testAssemblies + testAssemblyVer2: React.Windows.Desktop.IntegrationTests\React.Windows.Desktop.IntegrationTests.dll + searchFolder: $(Build.SourcesDirectory)\vnext\target\${{ parameters.buildPlatform }}\${{ parameters.buildConfiguration }} + testFiltercriteria: $(Desktop.IntegrationTests.Filter) + runTestsInIsolation: true + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.buildConfiguration }} + publishRunAttachments: true + collectDumpOn: onAbortOnly + vsTestVersion: latest + failOnMinTestsNotRun: true + otherConsoleOptions: '/blame -- RunConfiguration.TestSessionTimeout=300000' + + - template: ../templates/stop-packagers.yml diff --git a/.ado/jobs/desktop.yml b/.ado/jobs/desktop.yml deleted file mode 100644 index e1cfc6e872c..00000000000 --- a/.ado/jobs/desktop.yml +++ /dev/null @@ -1,359 +0,0 @@ -parameters: - - name: buildEnvironment - type: string - default : PullRequest - values: - - PullRequest - - SecurePullRequest - - Continuous - - - name: AgentPool - type: object - - - name: buildMatrix - type: object - default: - - BuildEnvironment: PullRequest - Matrix: - - Name: X64Debug - BuildConfiguration: Debug - BuildPlatform: x64 - - Name: X64Release - BuildConfiguration: Release - BuildPlatform: x64 - - Name: X86Debug - BuildConfiguration: Debug - BuildPlatform: x86 - - Name: X86Release - BuildConfiguration: Release - BuildPlatform: x86 - - Name: ARM64ECDebug - BuildConfiguration: Debug - BuildPlatform: ARM64EC - - Name: ARM64ECRelease - BuildConfiguration: Release - BuildPlatform: ARM64EC - - Name: X64DebugFabric - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: true - - Name: X86ReleaseFabric # Specifically built so binskim / tests get run on fabric - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: true - - BuildEnvironment: SecurePullRequest - Matrix: - - Name: X64DebugFabric - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: true - - BuildEnvironment: Continuous - Matrix: - - Name: X64Debug - BuildConfiguration: Debug - BuildPlatform: x64 - - Name: X64Release - BuildConfiguration: Release - BuildPlatform: x64 - - Name: X86Debug - BuildConfiguration: Debug - BuildPlatform: x86 - - Name: X86Release - BuildConfiguration: Release - BuildPlatform: x86 - - Name: ARM64ECDebug - BuildConfiguration: Debug - BuildPlatform: ARM64EC - - Name: ARM64ECRelease - BuildConfiguration: Release - BuildPlatform: ARM64EC - - Name: X64DebugFabric - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: true - - Name: X86ReleaseFabric # Specifically built so binskim / tests get run on fabric - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: true - -jobs: - - ${{ each config in parameters.buildMatrix }}: - - ${{ if eq(config.BuildEnvironment, parameters.buildEnvironment) }}: - - ${{ each matrix in config.Matrix }}: - - job: Desktop${{ matrix.Name }} - displayName: Desktop ${{ matrix.Name }} - - variables: - - template: ../variables/windows.yml - - # Enable if any issues RNTesterIntegrationTests::* become unstable. - - name: Desktop.IntegrationTests.SkipRNTester - value: false - - #5059 - Disable failing or intermittent tests (IntegrationTestHarness,WebSocket,Logging). - #10732 - WebSocketIntegrationTest::SendReceiveSsl fails on Windows Server 2022. - #12714 - Disable for first deployment of test website. - # RNTesterIntegrationTests::WebSocket - # RNTesterIntegrationTests::WebSocketBlob - # RNTesterIntegrationTests::WebSocketMultipleSend - #14217 - Reneable RNTesterIntegrationTests - # RNTesterIntegrationTests::Dummy - # RNTesterIntegrationTests::Fetch - # RNTesterIntegrationTests::XHRSample - # RNTesterIntegrationTests::Blob - # RNTesterIntegrationTests::Logging - # - CI agents show the following server-side errors (local runs succeed): - # - [0x801901f4] Internal server error (500). - # - [0x800710dd] The operation identifier is not valid. - # WebSocketIntegrationTest::ConnectClose)& - # WebSocketIntegrationTest::ConnectNoClose)& - # WebSocketIntegrationTest::SendReceiveClose)& - # WebSocketIntegrationTest::SendConsecutive)& - # WebSocketIntegrationTest::SendReceiveLargeMessage)& - # WebSocketIntegrationTest::SendReceiveSsl)& - - name: Desktop.IntegrationTests.Filter - value: > - (FullyQualifiedName!=RNTesterIntegrationTests::IntegrationTestHarness)& - (FullyQualifiedName!=RNTesterIntegrationTests::WebSocket)& - (FullyQualifiedName!=RNTesterIntegrationTests::WebSocketBlob)& - (FullyQualifiedName!=RNTesterIntegrationTests::WebSocketMultipleSend)& - (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::ConnectClose)& - (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::ConnectNoClose)& - (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::SendReceiveClose)& - (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::SendConsecutive)& - (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::SendReceiveLargeMessage)& - (FullyQualifiedName!=Microsoft::React::Test::WebSocketIntegrationTest::SendReceiveSsl)& - (FullyQualifiedName!=Microsoft::React::Test::HttpOriginPolicyIntegrationTest)& - (FullyQualifiedName!=RNTesterIntegrationTests::Dummy)& - (FullyQualifiedName!=RNTesterIntegrationTests::Fetch)& - (FullyQualifiedName!=RNTesterIntegrationTests::XHRSample)& - (FullyQualifiedName!=RNTesterIntegrationTests::Blob)& - (FullyQualifiedName!=RNTesterIntegrationTests::Logging) - #6799 - - # HostFunctionTest - Crashes under JSI/V8 - # HostObjectProtoTest - Crashes under JSI/V8 - # PreparedJavaScriptSourceTest - Asserts/Fails under JSI/ChakraCore - - name: Desktop.UnitTests.Filter - value: > - (FullyQualifiedName!~HostFunctionTest)& - (FullyQualifiedName!~HostObjectProtoTest)& - (FullyQualifiedName!~PreparedJavaScriptSourceTest) - - pool: ${{ parameters.AgentPool.Medium }} - timeoutInMinutes: 80 # how long to run the job before automatically cancelling - Issue 13442 - cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them - - steps: - # Set up IIS tests { - - pwsh: | - Install-WindowsFeature -Name Web-Server, Web-Scripting-Tools - displayName: Install IIS - - - pwsh: | - Invoke-WebRequest ` - -Uri 'https://download.visualstudio.microsoft.com/download/pr/20598243-c38f-4538-b2aa-af33bc232f80/ea9b2ca232f59a6fdc84b7a31da88464/dotnet-hosting-8.0.3-win.exe' ` - -OutFile dotnet-hosting-8.0.3-win.exe - - Write-Host 'Installing .NET hosting bundle' - Start-Process -Wait -FilePath .\dotnet-hosting-8.0.3-win.exe -ArgumentList '/INSTALL', '/QUIET', '/NORESTART' - Write-Host 'Installed .NET hosting bundle' - - Invoke-WebRequest ` - -Uri 'https://download.visualstudio.microsoft.com/download/pr/f2ec926e-0d98-4a8b-8c70-722ccc2ca0e5/b59941b0c60f16421679baafdb7e9338/dotnet-sdk-7.0.407-win-x64.exe' ` - -OutFile dotnet-sdk-7.0.407-win-x64.exe - - Write-Host 'Installing .NET 7 SDK' - Start-Process -Wait -FilePath .\dotnet-sdk-7.0.407-win-x64.exe -ArgumentList '/INSTALL', '/QUIET', '/NORESTART' - Write-Host 'Installed .NET 7 SDK' - displayName: Install the .NET Core Hosting Bundle - - # } Set up IIS tests - - - template: ../templates/checkout-shallow.yml - - - template: ../templates/prepare-js-env.yml - - - template: ../templates/prepare-build-env.yml - parameters: - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - buildEnvironment: ${{ config.BuildEnvironment }} - - - template: ../templates/apply-published-version-vars.yml - - - ${{ if eq(variables['Desktop.IntegrationTests.SkipRNTester'], true) }}: - - powershell: | - $newValue = '(FullyQualifiedName!~RNTesterIntegrationTests::)&' + "$(Desktop.IntegrationTests.Filter)" - Write-Host "##vso[task.setvariable variable=Desktop.IntegrationTests.Filter]$newValue" - displayName: Update Desktop.IntegrationTests.Filter to exclude RNTester integration tests - - - ${{ if eq(matrix.UseFabric, true) }}: - - template: ../templates/enable-fabric-experimental-feature.yml - - - template: ../templates/msbuild-sln.yml - parameters: - solutionDir: vnext - solutionName: ReactWindows-Desktop.sln - buildPlatform: ${{ matrix.BuildPlatform }} - buildConfiguration: ${{ matrix.BuildConfiguration }} - - - ${{ if and(eq(matrix.BuildConfiguration, 'Debug'), eq(matrix.BuildPlatform, 'x64')) }}: - - script: yarn bundle - displayName: Build react-native-win32 RNTester bundle - workingDirectory: packages/@office-iss/react-native-win32 - - - ${{ if eq(config.BuildEnvironment, 'Continuous') }}: - - template: ../templates/component-governance.yml - - - template: ../templates/discover-google-test-adapter.yml - - - ${{ if ne(matrix.BuildPlatform, 'ARM64EC') }}: - - task: VSTest@2 - displayName: Run Desktop Unit Tests - timeoutInMinutes: 5 # Set smaller timeout , due to hangs - inputs: - testSelector: testAssemblies - testAssemblyVer2: | - React.Windows.Desktop.UnitTests/React.Windows.Desktop.UnitTests.dll - # Bug #8000: Tracks fixing the tests - # ReactCommon.UnitTests/ReactCommon.UnitTests.exe - pathtoCustomTestAdapters: $(GoogleTestAdapterPath) - searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - testFiltercriteria: $(Desktop.UnitTests.Filter) - runTestsInIsolation: true - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - publishRunAttachments: true - collectDumpOn: onAbortOnly - vsTestVersion: latest - failOnMinTestsNotRun: true - - # Suspected debug assert in TestRunner hanging tests randomly. Run only on Release for now. - - ${{ if and(eq(matrix.BuildConfiguration, 'Release'), ne(variables['Desktop.IntegrationTests.SkipRNTester'], true), ne(matrix.BuildPlatform, 'ARM64EC')) }}: - - task: PowerShell@2 - displayName: Set up test servers - inputs: - targetType: filePath # filePath | inline - filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tfs\Start-TestServers.ps1 - arguments: -SourcesDirectory $(Build.SourcesDirectory)\vnext -Preload -SleepSeconds 120 - - - task: DotNetCoreCLI@2 - displayName: Publish Test Website - inputs: - command: publish - publishWebProjects: false - zipAfterPublish: false - projects: $(Build.SourcesDirectory)\vnext\TestWebsite\Microsoft.ReactNative.Test.Website.csproj - arguments: --configuration ${{ matrix.BuildConfiguration }} - - - pwsh: | - # Create and make available to IIS - $cert = New-SelfSignedCertificate ` - -Type SSLServerAuthentication ` - -KeyExportPolicy Exportable ` - -Subject 'CN=localhost' ` - -NotAfter ([DateTime]::Now).AddHours(2) ` - -CertStoreLocation Cert:\LocalMachine\My\ - - $certPath = "${env:TEMP}\localhost.pfx" - $certPass = -join ('a'..'z' | Get-Random -Count 32) | ConvertTo-SecureString -AsPlainText -Force - $certHash = $cert.Thumbprint - Write-Host "##vso[task.setvariable variable=TestWebsiteCertificateThumbprint]$certHash" - - # Export PFX - $cert | Export-PfxCertificate -FilePath $certPath -Password $certPass - - # Trust globally - Import-PfxCertificate ` - -Exportable ` - -FilePath $certPath ` - -Password $certPass ` - -CertStoreLocation Cert:\LocalMachine\Root\ - displayName: Install SSL Certificate - - - task: IISWebAppManagementOnMachineGroup@0 - displayName: Create Test Website - inputs: - EnableIIS: false - IISDeploymentType: IISWebsite - ActionIISWebsite: CreateOrUpdateWebsite - SSLCertThumbPrint: $(TestWebsiteCertificateThumbprint) - # IIS Website - WebsiteName: RNW Test Website - # Hard-coding x64 for publish path. - # Our MSBuild customizations cause dotnet commans to assume the default PlatformTarget - WebsitePhysicalPath: $(Build.SourcesDirectory)\vnext\target\x64\${{ matrix.BuildConfiguration }}\Microsoft.ReactNative.Test.Website\Publish - WebsitePhysicalPathAuth: WebsiteUserPassThrough - CreateOrUpdateAppPoolForWebsite: false - ConfigureAuthenticationForWebsite: false - # IIS Application pool - AppPoolNameForWebsite: DefaultAppPool - # IIS Bindings - # See https://stackoverflow.com/questions/60089756 - AddBinding: true - Bindings: | - { - bindings: [ - { - "protocol": "http", - "ipAddress": "*", - "port": "5555", - "sslThumbprint": "", - "sniFlag": false - }, - { - "protocol": "https", - "ipAddress": "*", - "port": "5543", - "sslThumbprint": "$(TestWebsiteCertificateThumbprint)", - "sniFlag": false - } - ] - } - - - task: PowerShell@2 - displayName: Ensure servers readiness - inputs: - targetType: 'inline' - script: | - # Test website - Invoke-WebRequest -UseBasicParsing -Uri 'http://localhost:5555' - Invoke-WebRequest -UseBasicParsing -Uri 'https://localhost:5543' - - # Bundler - Invoke-WebRequest -UseBasicParsing -Uri "http://localhost:8081/IntegrationTests/IntegrationTestsApp.bundle?platform=windows&dev=true" - - - task: VSTest@2 - displayName: Run Desktop Integration Tests - inputs: - testSelector: testAssemblies - testAssemblyVer2: React.Windows.Desktop.IntegrationTests\React.Windows.Desktop.IntegrationTests.dll - searchFolder: $(Build.SourcesDirectory)\vnext\target\${{ matrix.BuildPlatform }}\${{ matrix.BuildConfiguration }} - testFiltercriteria: $(Desktop.IntegrationTests.Filter) - runTestsInIsolation: true - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - publishRunAttachments: true - collectDumpOn: onAbortOnly - vsTestVersion: latest - failOnMinTestsNotRun: true - otherConsoleOptions: '/blame -- RunConfiguration.TestSessionTimeout=300000' - - - template: ../templates/stop-packagers.yml - - - script: node .ado/scripts/build.js --binskim --platform ${{ matrix.BuildPlatform }} --configuration ${{ matrix.BuildConfiguration }} --target desktop - displayName: Run BinSkim Analysis - condition: eq('${{ matrix.BuildConfiguration }}', 'Release') - - - template: ../templates/publish-build-artifacts.yml - parameters: - ${{ if eq(matrix.UseFabric, true) }}: - artifactName: DesktopFabric - ${{ else }}: - artifactName: Desktop - buildPlatform: ${{ matrix.BuildPlatform }} - buildConfiguration: ${{ matrix.BuildConfiguration }} - contents: | - React.Windows.Desktop\** - React.Windows.Desktop.DLL\** - React.Windows.Desktop.Test.DLL\** diff --git a/.ado/jobs/e2e-test.yml b/.ado/jobs/e2e-test.yml index 324485261da..3f10b06c489 100644 --- a/.ado/jobs/e2e-test.yml +++ b/.ado/jobs/e2e-test.yml @@ -5,7 +5,6 @@ parameters: default : PullRequest values: - PullRequest - - SecurePullRequest - Continuous - name: AgentPool type: object @@ -115,14 +114,7 @@ jobs: targetType: filePath # filePath | inline filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tracing\Stop-Tracing.ps1 arguments: -NoAnalysis -outputFolder $(Build.StagingDirectory)/Tracing - condition: true - - - task: PublishBuildArtifacts@1 - displayName: Upload traces - inputs: - pathtoPublish: '$(Build.StagingDirectory)/Tracing' - artifactName: 'Traces - $(Agent.JobName)-$(System.JobAttempt)' - condition: true + condition: always() - task: CopyFiles@2 displayName: Copy snapshots @@ -140,128 +132,152 @@ jobs: contents: AppPackages\** condition: failed() - - task: PublishPipelineArtifact@1 - displayName: "Publish Artifact: RNTesterApp" + - template: ../templates/upload-build-logs.yml + parameters: + buildLogDirectory: '$(BuildLogDirectory)' + + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Upload traces' + condition: always() + targetPath: $(Build.StagingDirectory)/Tracing + artifactName: Traces - $(Agent.JobName)-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Publish Artifact: RNTesterApp' + condition: failed() + targetPath: $(Build.StagingDirectory)/RNTesterApp + artifactName: RNTesterApp-${{ matrix.Name }}-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Publish Artifact: Snapshots' + condition: failed() + targetPath: $(Build.StagingDirectory)/snapshots + artifactName: Snapshots - RNTesterApp-${{ matrix.Name }}-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Upload build logs' + condition: succeededOrFailed() + targetPath: $(BuildLogDirectory) + artifactName: Build logs - $(Agent.JobName)-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Upload crash dumps' + condition: and(succeededOrFailed(), eq(variables.HasCrashDumps, 'True')) + targetPath: '$(CrashDumpRootPath)' + artifactName: Crash dumps - $(Agent.JobName)-$(System.JobAttempt) + - ${{ each config in parameters.buildMatrix }}: + - ${{ if eq(config.BuildEnvironment, parameters.buildEnvironment) }}: + - ${{ each matrix in config.Matrix }}: + - job: E2ETestFabric${{ matrix.Name }} + displayName: E2E Test App Fabric ${{ matrix.Name }} + + variables: [template: ../variables/windows.yml] + pool: ${{ parameters.AgentPool.Medium }} + timeoutInMinutes: 60 # how long to run the job before automatically cancelling + cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them + + steps: + - template: ../templates/checkout-shallow.yml + + - template: ../templates/prepare-js-env.yml + + - template: ../templates/prepare-build-env.yml + parameters: + platform: ${{ matrix.BuildPlatform }} + configuration: Release + buildEnvironment: ${{ config.buildEnvironment }} + + - pwsh: | + Write-Host "##vso[task.setvariable variable=BuildLogDirectory]$(Build.BinariesDirectory)\${{ matrix.BuildPlatform }}\BuildLogs" + displayName: Set BuildLogDirectory + + - task: PowerShell@2 + displayName: Start tracing inputs: - artifactName: RNTesterApp-${{ matrix.Name }}-$(System.JobAttempt) - targetPath: $(Build.StagingDirectory)/RNTesterApp + targetType: filePath # filePath | inline + filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tracing\Start-Tracing.ps1 + pwsh: true + + - template: ../templates/run-windows-with-certificates.yml + parameters: + buildEnvironment: ${{ parameters.BuildEnvironment }} + buildConfiguration: Release + buildPlatform: ${{ matrix.BuildPlatform }} + buildLogDirectory: $(BuildLogDirectory) + workingDirectory: packages/e2e-test-app-fabric + + - script: | + echo ##vso[task.setvariable variable=StartedFabricTests]true + displayName: Set StartedFabricTests + + - script: | + yarn e2etest + displayName: yarn e2etest + workingDirectory: packages/e2e-test-app-fabric + timeoutInMinutes: 10 # Time to wait for this task to complete before the server kills it. + + - script: npx jest --clearCache + displayName: clear jest cache + workingDirectory: packages/e2e-test-app-fabric + condition: and(failed(), eq(variables.StartedFabricTests, 'true')) + + - script: yarn e2etest -u + displayName: Update snapshots + workingDirectory: packages/e2e-test-app-fabric + condition: and(failed(), eq(variables.StartedFabricTests, 'true')) + timeoutInMinutes: 10 # Time to wait for this task to complete before the server kills it. + + - task: PowerShell@2 + displayName: Stop tracing + inputs: + targetType: filePath # filePath | inline + filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tracing\Stop-Tracing.ps1 + arguments: -NoAnalysis -outputFolder $(Build.StagingDirectory)/Tracing + pwsh: true + condition: always() + + - task: CopyFiles@2 + displayName: Copy Fabric snapshots + inputs: + sourceFolder: packages/e2e-test-app-fabric/test/__snapshots__ + targetFolder: $(Build.StagingDirectory)/snapshots-fabric + contents: "**" condition: failed() - - task: PublishPipelineArtifact@1 - displayName: "Publish Artifact: Snapshots" + - task: CopyFiles@2 + displayName: Copy RNTesterApp artifacts inputs: - artifactName: Snapshots - RNTesterApp-${{ matrix.Name }}-$(System.JobAttempt) - targetPath: $(Build.StagingDirectory)/snapshots + sourceFolder: $(Build.SourcesDirectory)/packages/e2e-test-app-fabric/windows/${{ matrix.BuildPlatform }}/Release + targetFolder: $(Build.StagingDirectory)/RNTesterApp-Fabric + contents: "**" condition: failed() - template: ../templates/upload-build-logs.yml parameters: buildLogDirectory: '$(BuildLogDirectory)' - - ${{ each config in parameters.buildMatrix }}: - - ${{ if eq(config.BuildEnvironment, parameters.buildEnvironment) }}: - - ${{ each matrix in config.Matrix }}: - - ${{ if eq(matrix.UseChakra, false) }}: - - job: E2ETestFabric${{ matrix.Name }} - displayName: E2E Test App Fabric ${{ matrix.Name }} - - variables: [template: ../variables/windows.yml] - pool: ${{ parameters.AgentPool.Medium }} - timeoutInMinutes: 60 # how long to run the job before automatically cancelling - cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them - - steps: - - template: ../templates/checkout-shallow.yml - - - template: ../templates/prepare-js-env.yml - - - template: ../templates/prepare-build-env.yml - parameters: - platform: ${{ matrix.BuildPlatform }} - configuration: Release - buildEnvironment: ${{ config.buildEnvironment }} - - - powershell: | - Write-Host "##vso[task.setvariable variable=BuildLogDirectory]$(Build.BinariesDirectory)\${{ matrix.BuildPlatform }}\BuildLogs" - displayName: Set BuildLogDirectory - - - task: PowerShell@2 - displayName: Start tracing - inputs: - targetType: filePath # filePath | inline - filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tracing\Start-Tracing.ps1 - - - template: ../templates/run-windows-with-certificates.yml - parameters: - buildEnvironment: ${{ parameters.BuildEnvironment }} - buildConfiguration: Release - buildPlatform: ${{ matrix.BuildPlatform }} - buildLogDirectory: $(BuildLogDirectory) - workingDirectory: packages/e2e-test-app-fabric - - - script: | - echo ##vso[task.setvariable variable=StartedFabricTests]true - displayName: Set StartedFabricTests - - - script: | - yarn e2etest - displayName: yarn e2etest - workingDirectory: packages/e2e-test-app-fabric - - script: npx jest --clearCache - displayName: clear jest cache - workingDirectory: packages/e2e-test-app-fabric - condition: and(failed(), eq(variables.StartedFabricTests, 'true')) - - - script: yarn e2etest -u - displayName: Update snapshots - workingDirectory: packages/e2e-test-app-fabric - condition: and(failed(), eq(variables.StartedFabricTests, 'true')) - - - task: PowerShell@2 - displayName: Stop tracing - inputs: - targetType: filePath # filePath | inline - filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tracing\Stop-Tracing.ps1 - arguments: -NoAnalysis -outputFolder $(Build.StagingDirectory)/Tracing - condition: true - - - task: PublishBuildArtifacts@1 - displayName: Upload traces - inputs: - pathtoPublish: '$(Build.StagingDirectory)/Tracing' - artifactName: 'Traces - $(Agent.JobName)-$(System.JobAttempt)' - condition: true - - - task: CopyFiles@2 - displayName: Copy Fabric snapshots - inputs: - sourceFolder: packages/e2e-test-app-fabric/test/__snapshots__ - targetFolder: $(Build.StagingDirectory)/snapshots-fabric - contents: "**" - condition: failed() - - - task: CopyFiles@2 - displayName: Copy RNTesterApp artifacts - inputs: - sourceFolder: $(Build.SourcesDirectory)/packages/e2e-test-app-fabric/windows/${{ matrix.BuildPlatform }}/Release - targetFolder: $(Build.StagingDirectory)/RNTesterApp-Fabric - contents: "**" - condition: failed() - - - task: PublishPipelineArtifact@1 - displayName: "Publish Artifact: RNTesterApp Fabric" - inputs: - artifactName: RNTesterApp-Fabric-${{ matrix.Name }}-$(System.JobAttempt) - targetPath: $(Build.StagingDirectory)/RNTesterApp-Fabric - condition: failed() - - - task: PublishPipelineArtifact@1 - displayName: "Publish Artifact: Fabric Snapshots" - inputs: - artifactName: Snapshots - RNTesterApp-Fabric-${{ matrix.Name }}-$(System.JobAttempt) - targetPath: $(Build.StagingDirectory)/snapshots-fabric - condition: failed() - - - template: ../templates/upload-build-logs.yml - parameters: - buildLogDirectory: '$(BuildLogDirectory)' + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Upload traces' + condition: always() + targetPath: $(Build.StagingDirectory)/Tracing + artifactName: Traces - $(Agent.JobName)-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Publish Artifact: RNTesterApp Fabric' + condition: failed() + targetPath: $(Build.StagingDirectory)/RNTesterApp-Fabric + artifactName: RNTesterApp-Fabric-${{ matrix.Name }}-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Publish Artifact: Fabric Snapshots' + condition: failed() + targetPath: $(Build.StagingDirectory)/snapshots-fabric + artifactName: Snapshots - RNTesterApp-Fabric-${{ matrix.Name }}-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Upload build logs' + condition: succeededOrFailed() + targetPath: $(BuildLogDirectory) + artifactName: Build logs - $(Agent.JobName)-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Upload crash dumps' + condition: and(succeededOrFailed(), eq(variables.HasCrashDumps, 'True')) + targetPath: '$(CrashDumpRootPath)' + artifactName: Crash dumps - $(Agent.JobName)-$(System.JobAttempt) diff --git a/.ado/jobs/linting.yml b/.ado/jobs/linting.yml index 612a0fe6738..7e4c85d8d67 100644 --- a/.ado/jobs/linting.yml +++ b/.ado/jobs/linting.yml @@ -4,7 +4,6 @@ parameters: default : PullRequest values: - PullRequest - - SecurePullRequest - Continuous - name: AgentPool @@ -21,8 +20,6 @@ jobs: - template: ../templates/prepare-js-env.yml - - template: ../templates/run-compliance-prebuild.yml - - script: yarn format:verify displayName: yarn format:verify diff --git a/.ado/jobs/node-tests.yml b/.ado/jobs/node-tests.yml index ef1167cefa2..8824f5504ba 100644 --- a/.ado/jobs/node-tests.yml +++ b/.ado/jobs/node-tests.yml @@ -4,7 +4,6 @@ parameters: default : PullRequest values: - PullRequest - - SecurePullRequest - Continuous - name: AgentPool diff --git a/.ado/jobs/nuget-desktop.yml b/.ado/jobs/nuget-desktop.yml deleted file mode 100644 index e93822c4bfd..00000000000 --- a/.ado/jobs/nuget-desktop.yml +++ /dev/null @@ -1,44 +0,0 @@ -parameters: - - name: buildEnvironment - type: string - default : PullRequest - values: - - PullRequest - - SecurePullRequest - - Continuous - - name: AgentPool - type: object - -jobs: - - ${{if ne(parameters.buildEnvironment, 'SecurePullRequest')}}: - - job: PackDesktop - displayName: Pack Desktop NuGet Package - variables: [template: ../variables/windows.yml] - dependsOn: - - DesktopX64Release - - DesktopX86Debug - - DesktopARM64ECRelease - - pool: ${{ parameters.AgentPool.Small }} - timeoutInMinutes: 30 # how long to run the job before automatically cancelling - cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them - steps: - - template: ../templates/checkout-shallow.yml - - - template: ../templates/yarn-install.yml - - - task: NuGetToolInstaller@1 - inputs: - versionSpec: ">=5.8.0" - - - template: ../templates/prep-and-pack-nuget.yml - parameters: - artifactName: Desktop - packDesktop: true - slices: - - platform: x64 - configuration: Release - - platform: x86 - configuration: Debug - - platform: ARM64EC - configuration: Release diff --git a/.ado/jobs/playground.yml b/.ado/jobs/playground.yml index f9b2c22732a..50494834df6 100644 --- a/.ado/jobs/playground.yml +++ b/.ado/jobs/playground.yml @@ -4,7 +4,6 @@ parameters: default : PullRequest values: - PullRequest - - SecurePullRequest - Continuous - name: AgentPool type: object @@ -49,23 +48,6 @@ parameters: BuildConfiguration: Release BuildPlatform: x64 SolutionFile: Playground-Win32.sln - - BuildEnvironment: SecurePullRequest - Matrix: - - Name: X86DebugCompositionExperimentalWinUI3 - BuildConfiguration: Debug - BuildPlatform: x86 - SolutionFile: Playground-Composition.sln - UseExperimentalWinUI3: false - - Name: X64DebugCompositionExperimentalWinUI3 - BuildConfiguration: Debug - BuildPlatform: x64 - SolutionFile: Playground-Composition.sln - UseExperimentalWinUI3: false - - Name: X64ReleaseCompositionExperimentalWinUI3 - BuildConfiguration: Release - BuildPlatform: x64 - SolutionFile: Playground-Composition.sln - UseExperimentalWinUI3: false - BuildEnvironment: Continuous Matrix: - Name: X86DebugUniversal @@ -93,17 +75,7 @@ parameters: BuildConfiguration: Release BuildPlatform: x64 SolutionFile: Playground-Composition.sln - # - Name: X86DebugCompositionExperimentalWinUI3 - # BuildConfiguration: Debug - # BuildPlatform: x86 - # SolutionFile: Playground-Composition.sln - # UseExperimentalWinUI3: true - # - Name: X64ReleaseCompositionExperimentalWinUI3 - # BuildConfiguration: Release - # BuildPlatform: x64 - # SolutionFile: Playground-Composition.sln - # UseExperimentalWinUI3: true - - Name: X86DebugWin32 + - Name: X86DebugCompositionExperimentalWinUI3 BuildConfiguration: Debug BuildPlatform: x86 SolutionFile: Playground-Win32.sln @@ -184,19 +156,19 @@ jobs: # Execute debug feature tests (skip this step for the Win32 Playground app and for release builds) # Need to re-setup ProcDump a 2nd time for this to work correctly - - powershell: | + - pwsh: | Write-Host "##vso[task.setvariable variable=CrashDumpRootPath]$(Build.StagingDirectory)\DebugTestCrashDumps" New-Item -Path '$(Build.StagingDirectory)\DebugTestCrashDumps' -ItemType Directory displayName: Set CrashDumpRootPath - - powershell: | + - pwsh: | & $(Build.SourcesDirectory)\.ado\scripts\RunProcDump.ps1 -ProcDumpArgs @("-mm", "-i", "$(CrashDumpRootPath)") -ProcDumpInstallPath "$(ProcDumpPath)" -Verbose displayName: Setup ProcDump as AeDebug # This step loose-file-deploys the UWP Playground app and uses it as an RNW host for a series # of debug feature tests. In the future, these tests should be performed against a host app # better suited for automated tests (probably the E2E test app). - - powershell: | + - pwsh: | $appRecipeToolPath = Join-Path (& "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath) "Common7\IDE\DeployAppRecipe.exe" if (!(Test-Path $appRecipeToolPath)) { throw "can't find '$appRecipeToolPath'" } $platDirs = @{ "x64" = "x64\"; "x86" = ""} # map from ADO BuildPlatform arg to VS build output dir part @@ -210,7 +182,7 @@ jobs: displayName: Run Debug Feature Tests timeoutInMinutes: 5 - - powershell: | + - pwsh: | foreach ($logFile in (ls "$(Build.StagingDirectory)\DebugTestLogs\*.log")) { Write-Host "logFile: '$logFile'" Get-Content $logFile | ForEach-Object {Write-Host "##[debug]$_"} @@ -226,10 +198,23 @@ jobs: - ${{if eq(config.BuildEnvironment, 'Continuous')}}: - template: ../templates/cleanup-certificate.yml + # App Package publish moved to templateContext.outputs (1ES compliance) + + templateContext: + outputs: - ${{ if eq(matrix.UploadAppx, true) }}: - - task: PublishBuildArtifacts@1 - displayName: Upload App Package - inputs: - pathtoPublish: 'packages/playground/windows/AppPackages/playground' - artifactName: 'Playground-${{ matrix.Name }}-$(System.JobAttempt)' + - output: pipelineArtifact + displayName: 'Upload App Package' condition: succeededOrFailed() + targetPath: packages/playground/windows/AppPackages/playground + artifactName: Playground-${{ matrix.Name }}-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Upload build logs' + condition: succeededOrFailed() + targetPath: $(BuildLogDirectory) + artifactName: Build logs - $(Agent.JobName)-$(System.JobAttempt) + - output: pipelineArtifact + displayName: 'Upload crash dumps' + condition: and(succeededOrFailed(), eq(variables.HasCrashDumps, 'True')) + targetPath: '$(CrashDumpRootPath)' + artifactName: Crash dumps - $(Agent.JobName)-$(System.JobAttempt) diff --git a/.ado/jobs/setup.yml b/.ado/jobs/setup.yml deleted file mode 100644 index 4369851ad26..00000000000 --- a/.ado/jobs/setup.yml +++ /dev/null @@ -1,64 +0,0 @@ -parameters: - - name: buildEnvironment - type: string - values: - - PullRequest - - SecurePullRequest - - Continuous - -jobs: - - job: Setup - displayName: Setup - timeoutInMinutes: 4 # Kill the job early to catch Beachball hangs - variables: [template: ../variables/shared.yml] - pool: {vmImage: ubuntu-latest} - - steps: - - task: UseNode@1 - inputs: - version: '22.14.0' - displayName: 'Use Node.js 22.14.0' - - - template: ../templates/checkout-full.yml - parameters: - persistCredentials: true # Git creds needed for beachball - - - powershell: gci env:/BUILD_* - displayName: Show build information - - - template: ../templates/compute-beachball-branch-name.yml - - - template: ../templates/strict-yarn-install.yml - parameters: - workspace: '@rnw-scripts/beachball-config' - - - script: npx lage build --scope @rnw-scripts/beachball-config --no-deps - displayName: Build @rnw-scripts/beachball-config - - - script: | - echo "System.PullRequest.SourceBranch = $(System.PullRequest.SourceBranch)" - echo "Build.SourceBranch = $(Build.SourceBranch)" - echo "Build.SourceBranchName = $(Build.SourceBranchName)" - displayName: Print branch variables - - - pwsh: | - npx --yes beachball check --branch origin/$(BeachBallBranchName) --verbose 2>&1 | Tee-Object -Variable beachballOutput - $beachballErrors = $beachballOutput | Where-Object { $_ -match "ERROR: *"} - $beachballErrors | ForEach { Write-Host "##vso[task.logissue type=warning]POSSIBLE $_" } - displayName: Warn for possible invalid change files - condition: not(startsWith(variables['System.PullRequest.SourceBranch'], 'prepare-release/')) - - - ${{ if endsWith(parameters.buildEnvironment, 'PullRequest') }}: - - script: npx --yes beachball check --branch origin/$(BeachBallBranchName) --verbose --changehint "##vso[task.logissue type=error]Run \"yarn change\" from root of repo to generate a change file." - displayName: Check for change files - condition: not(startsWith(variables['System.PullRequest.SourceBranch'], 'prepare-release/')) - - - script: npx --yes beachball bump --branch origin/$(BeachBallBranchName) --yes --verbose - displayName: beachball bump - condition: not(startsWith(variables['System.PullRequest.SourceBranch'], 'prepare-release/')) - - - template: ../templates/set-version-vars.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - - - template: ../templates/publish-version-vars.yml diff --git a/.ado/jobs/universal-single.yml b/.ado/jobs/universal-single.yml new file mode 100644 index 00000000000..377e9e4e13c --- /dev/null +++ b/.ado/jobs/universal-single.yml @@ -0,0 +1,138 @@ +# +# Step template: Build and test one Universal platform/config combination. +# Called from build-template.yml which owns the job definition, artifact +# publishing, ESRP signing, and templateContext. +# + +parameters: + - name: buildPlatform + type: string + - name: buildConfiguration + type: string + - name: buildEnvironment + type: string + default: PullRequest + values: + - PullRequest + - Continuous + - name: useFabric + type: boolean + default: true +steps: + - template: ../templates/checkout-shallow.yml + + - template: ../templates/prepare-js-env.yml + + - template: ../templates/prepare-build-env.yml + parameters: + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.buildConfiguration }} + buildEnvironment: ${{ parameters.buildEnvironment }} + + - template: ../templates/apply-published-version-vars.yml + + - ${{ if eq(parameters.useFabric, true) }}: + - template: ../templates/enable-fabric-experimental-feature.yml + + - template: ../templates/msbuild-sln.yml + parameters: + solutionDir: vnext + ${{ if eq(parameters.useFabric, true) }}: + solutionName: Microsoft.ReactNative.CppOnly.slnf + ${{ else }}: + solutionName: Microsoft.ReactNative.sln + buildPlatform: ${{ parameters.buildPlatform }} + buildConfiguration: ${{ parameters.buildConfiguration }} + msbuildArguments: /p:ForceImportAfterCppTargets=$(Build.SourcesDirectory)\vnext\PropertySheets\CIBuildOptimizations.props + + - ${{ if eq(parameters.buildEnvironment, 'Continuous') }}: + - template: ../templates/component-governance.yml + + - task: PowerShell@2 + displayName: Make AnyCPU Reference Assemblies + inputs: + filePath: vnext/Scripts/Tfs/Make-AnyCPU-RefAssemblies.ps1 + arguments: -TargetRoot $(Build.SourcesDirectory)\vnext\target -BuildRoot $(Build.SourcesDirectory)\vnext\target + pwsh: true + + # --- Tests (run against the just-built binaries, no download/restore needed) --- + - template: ../templates/discover-google-test-adapter.yml + + - task: VSTest@2 + displayName: Run Universal Unit Tests (Native) + timeoutInMinutes: 5 # Set smaller timeout, due to hangs + inputs: + testSelector: testAssemblies + testAssemblyVer2: | + Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.exe + Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.exe + Mso.UnitTests/Mso.UnitTests.exe + pathtoCustomTestAdapters: $(GoogleTestAdapterPath) + searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ parameters.buildPlatform }}/${{ parameters.buildConfiguration }} + runTestsInIsolation: true + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.buildConfiguration }} + publishRunAttachments: true + collectDumpOn: onAbortOnly + vsTestVersion: latest + failOnMinTestsNotRun: true + condition: and(succeeded(), not(eq('${{ parameters.buildPlatform }}', 'ARM64'))) + + # Component tests — Debug/x64 only + - task: VSTest@2 + displayName: Run Universal Unit Tests (Native - ComponentTests) + timeoutInMinutes: 5 + inputs: + testSelector: testAssemblies + testAssemblyVer2: | + Microsoft.ReactNative.ComponentTests/Microsoft.ReactNative.ComponentTests.exe + pathtoCustomTestAdapters: $(GoogleTestAdapterPath) + searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ parameters.buildPlatform }}/${{ parameters.buildConfiguration }} + runTestsInIsolation: true + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.buildConfiguration }} + publishRunAttachments: true + collectDumpOn: onAbortOnly + vsTestVersion: latest + failOnMinTestsNotRun: true + condition: and(succeeded(), eq('${{ parameters.buildConfiguration }}', 'Debug'), eq('${{ parameters.buildPlatform }}', 'x64')) + + # Managed UWP unit tests — non-Fabric only, skip ARM64 + - ${{ if ne(parameters.useFabric, true) }}: + - task: VSTest@2 + displayName: Run Universal Unit Tests (UWP) + timeoutInMinutes: 5 + inputs: + testSelector: testAssemblies + testAssemblyVer2: | + Microsoft.ReactNative.Managed.UnitTests/Microsoft.ReactNative.Managed.UnitTests.build.appxrecipe + searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ parameters.buildPlatform }}/${{ parameters.buildConfiguration }} + runTestsInIsolation: true + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.buildConfiguration }} + publishRunAttachments: true + codeCoverageEnabled: true + collectDumpOn: onAbortOnly + vsTestVersion: latest + failOnMinTestsNotRun: true + condition: and(succeeded(), not(eq('${{ parameters.buildPlatform }}', 'ARM64'))) + + # Managed CodeGen unit tests — non-Fabric only, x64 only + - ${{ if ne(parameters.useFabric, true) }}: + - task: VSTest@2 + displayName: Run Universal Unit Tests (NetCore) + timeoutInMinutes: 5 + inputs: + testSelector: testAssemblies + testAssemblyVer2: | + Microsoft.ReactNative.Managed.CodeGen.UnitTests/Microsoft.ReactNative.Managed.CodeGen.UnitTests.dll + searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ parameters.buildPlatform }}/${{ parameters.buildConfiguration }} + runTestsInIsolation: true + platform: ${{ parameters.buildPlatform }} + configuration: ${{ parameters.buildConfiguration }} + publishRunAttachments: true + codeCoverageEnabled: true + collectDumpOn: onAbortOnly + vsTestVersion: latest + failOnMinTestsNotRun: true + condition: and(succeeded(), eq('${{ parameters.buildPlatform }}', 'x64')) diff --git a/.ado/jobs/universal.yml b/.ado/jobs/universal.yml deleted file mode 100644 index 85971dfdfa5..00000000000 --- a/.ado/jobs/universal.yml +++ /dev/null @@ -1,338 +0,0 @@ - parameters: - - name: buildEnvironment - type: string - default : PullRequest - values: - - PullRequest - - SecurePullRequest - - Continuous - - name: AgentPool - type: object - - name: buildMatrix - type: object - default: - - BuildEnvironment: PullRequest - Matrix: - - Name: X64Debug - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: false - - Name: X64Release - BuildConfiguration: Release - BuildPlatform: x64 - UseFabric: false - - Name: X86Debug - BuildConfiguration: Debug - BuildPlatform: x86 - UseFabric: false - CreateApiDocs: true - - Name: X86Release - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: false - - Name: Arm64Debug - BuildConfiguration: Debug - BuildPlatform: ARM64 - UseFabric: false - - Name: Arm64Release - BuildConfiguration: Release - BuildPlatform: ARM64 - UseFabric: false - - Name: X64DebugFabric - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: true - - Name: X64ReleaseFabric - BuildConfiguration: Release - BuildPlatform: x64 - UseFabric: true - - Name: X86ReleaseFabric # Specifically built so binskim / tests get run on fabric - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: true - - Name: Arm64ReleaseFabric - BuildConfiguration: Release - BuildPlatform: ARM64 - UseFabric: true - - BuildEnvironment: SecurePullRequest - Matrix: - - Name: X64ReleaseFabric - BuildConfiguration: Release - BuildPlatform: x64 - UseFabric: true - - Name: X86ReleaseFabric # Specifically built so binskim / tests get run on fabric - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: true - - BuildEnvironment: Continuous - Matrix: - - Name: X64Debug - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: false - - Name: X64Release - BuildConfiguration: Release - BuildPlatform: x64 - UseFabric: false - - Name: X86Debug - BuildConfiguration: Debug - BuildPlatform: x86 - UseFabric: false - CreateApiDocs: true - - Name: X86Release - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: false - - Name: Arm64Debug - BuildConfiguration: Debug - BuildPlatform: ARM64 - UseFabric: false - - Name: Arm64Release - BuildConfiguration: Release - BuildPlatform: ARM64 - UseFabric: false - - Name: X64DebugFabric - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: true - - Name: X64ReleaseFabric - BuildConfiguration: Release - BuildPlatform: x64 - UseFabric: true - - Name: X86DebugFabric - BuildConfiguration: Debug - BuildPlatform: x86 - UseFabric: true - - Name: X86ReleaseFabric # Specifically built so binskim / tests get run on fabric - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: true - - Name: Arm64DebugFabric - BuildConfiguration: Debug - BuildPlatform: ARM64 - UseFabric: true - - Name: Arm64ReleaseFabric - BuildConfiguration: Release - BuildPlatform: ARM64 - UseFabric: true - - jobs: - - ${{ each config in parameters.buildMatrix }}: - - ${{ if eq(config.BuildEnvironment, parameters.buildEnvironment) }}: - - ${{ each matrix in config.Matrix }}: - - job: UniversalBuild${{ matrix.Name }} - variables: - - template: ../variables/windows.yml - # Some tasks run on a different user (VssAdministrator) instead of the default user (AzDevOps). - # Keep NuGet cache independent from the user directory. - - name: NUGET_PACKAGES - value: $(Agent.TempDirectory)/NuGetPackages - displayName: Universal Build ${{ matrix.Name }} - pool: ${{ parameters.AgentPool.Large }} - timeoutInMinutes: 60 - cancelTimeoutInMinutes: 5 - - steps: - - template: ../templates/checkout-shallow.yml - - - template: ../templates/prepare-js-env.yml - - - template: ../templates/prepare-build-env.yml - parameters: - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - buildEnvironment: ${{ config.BuildEnvironment }} - - - template: ../templates/apply-published-version-vars.yml - - - ${{ if eq(matrix.UseFabric, true) }}: - - template: ../templates/enable-fabric-experimental-feature.yml - - - template: ../templates/msbuild-sln.yml - parameters: - solutionDir: vnext - ${{ if eq(matrix.UseFabric, true) }}: - solutionName: Microsoft.ReactNative.CppOnly.slnf - ${{ else }}: - solutionName: Microsoft.ReactNative.sln - buildPlatform: ${{ matrix.BuildPlatform }} - buildConfiguration: ${{ matrix.BuildConfiguration }} - - - ${{ if eq(config.BuildEnvironment, 'Continuous') }}: - - template: ../templates/component-governance.yml - - - ${{ if eq(matrix.CreateApiDocs, true) }}: - - powershell: | - $winmd2md_url = "https://github.com/asklar/winmd2md/releases/download/v0.1.13/winmd2md.exe" - Invoke-WebRequest -UseBasicParsing $winmd2md_url -OutFile $env:TEMP\winmd2md.exe - & $env:TEMP\winmd2md.exe /experimental /outputDirectory vnext\target\winmd2md vnext\target\x86\Debug\Microsoft.ReactNative\Microsoft.ReactNative.winmd - displayName: "Generate WinRT API docs" - - - task: PublishBuildArtifacts@1 - displayName: Upload WinRT API docs - inputs: - pathtoPublish: 'vnext\target\winmd2md' - artifactName: 'WinRT API docs - $(Agent.JobName)-$(System.JobAttempt)' - - - task: PowerShell@2 - displayName: Make AnyCPU Reference Assemblies - inputs: - filePath: vnext/Scripts/Tfs/Make-AnyCPU-RefAssemblies.ps1 - arguments: -TargetRoot $(Build.SourcesDirectory)\vnext\target -BuildRoot $(Build.SourcesDirectory)\vnext\target - - - template: ../templates/publish-build-artifacts.yml - parameters: - ${{ if eq(matrix.UseFabric, true) }}: - artifactName: ReactWindowsFabric - ${{ else }}: - artifactName: ReactWindows - buildPlatform: ${{ matrix.BuildPlatform }} - buildConfiguration: ${{ matrix.BuildConfiguration }} - contents: | - Microsoft.ReactNative\** - Microsoft.ReactNative.Cxx.UnitTests\** - Microsoft.ReactNative.IntegrationTests\** - Microsoft.ReactNative.ComponentTests\** - Microsoft.ReactNative.Managed\** - Microsoft.ReactNative.Managed.CodeGen\** - Microsoft.ReactNative.Managed.CodeGen.UnitTests\** - Microsoft.ReactNative.Managed.UnitTests\** - Mso.UnitTests\** - - - job: UniversalTest${{ matrix.Name }} - variables: - - template: ../variables/windows.yml - # Some tasks run on a different user (VssAdministrator) instead of the default user (AzDevOps). - # Keep NuGet cache independent from the user directory. - - name: NUGET_PACKAGES - value: $(Agent.TempDirectory)/NuGetPackages - displayName: Universal Test ${{ matrix.Name }} - dependsOn: - - UniversalBuild${{ matrix.Name }} - - pool: ${{ parameters.AgentPool.Medium }} - timeoutInMinutes: 60 - cancelTimeoutInMinutes: 5 - - steps: - - template: ../templates/checkout-shallow.yml - - - template: ../templates/prepare-js-env.yml - - - template: ../templates/prepare-build-env.yml - parameters: - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - buildEnvironment: ${{ config.BuildEnvironment }} - - - task: PowerShell@2 - displayName: Check if this environment meets the development dependencies - inputs: - targetType: filePath - filePath: $(Build.SourcesDirectory)\vnext\Scripts\rnw-dependencies.ps1 - arguments: -NoPrompt -Tags buildLab - - - task: DownloadPipelineArtifact@1 - ${{ if eq(matrix.UseFabric, true) }}: - displayName: Download "ReactWindowsFabric.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }}" - ${{ else }}: - displayName: Download "ReactWindows.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }}" - inputs: - targetPath: $(Build.SourcesDirectory)/vnext/target/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - ${{ if eq(matrix.UseFabric, true) }}: - artifactName: ReactWindowsFabric.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }} - ${{ else }}: - artifactName: ReactWindows.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }} - - - script: node .ado/scripts/build.js --binskim --platform ${{ matrix.BuildPlatform }} --configuration ${{ matrix.BuildConfiguration }} --target universal - displayName: Run BinSkim Analysis - condition: and(succeeded(), eq('${{ matrix.BuildConfiguration }}', 'Release'), ne('${{ matrix.BuildPlatform }}', 'ARM64')) - - - template: ../templates/discover-google-test-adapter.yml - - - task: MSBuild@1 - displayName: Restore NuGet packages - # Should be kept in sync with UniversalBuild - template: ../templates/msbuild-sln.yml - inputs: - solution: vnext/Microsoft.ReactNative.sln - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - msbuildArchitecture: x64 - msbuildArguments: - /t:Restore - - - task: VSTest@2 - displayName: Run Universal Unit Tests (Native) - timeoutInMinutes: 5 # Set smaller timeout , due to hangs - inputs: - testSelector: testAssemblies - testAssemblyVer2: | - Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.exe - Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.exe - Mso.UnitTests/Mso.UnitTests.exe - pathtoCustomTestAdapters: $(GoogleTestAdapterPath) - searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - runTestsInIsolation: true - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - publishRunAttachments: true - collectDumpOn: onAbortOnly - vsTestVersion: latest - failOnMinTestsNotRun: true - # Issue #8003 Tracks restoring this test whose condition should be resotred disabled as it times out on releasex64... - # condition: and(succeeded(), not(eq('${{ matrix.BuildPlatform }}', 'ARM64'))) - condition: and(succeeded(), eq('${{ matrix.BuildPlatform }}', 'x86')) - - - task: VSTest@2 - displayName: Run Universal Unit Tests (Native - ComponentTests) - timeoutInMinutes: 5 # Set smaller timeout , due to hangs - inputs: - testSelector: testAssemblies - testAssemblyVer2: | - Microsoft.ReactNative.ComponentTests/Microsoft.ReactNative.ComponentTests.exe - pathtoCustomTestAdapters: $(GoogleTestAdapterPath) - searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - runTestsInIsolation: true - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - publishRunAttachments: true - collectDumpOn: onAbortOnly - vsTestVersion: latest - failOnMinTestsNotRun: true - condition: and(succeeded(), and(eq('${{ matrix.BuildConfiguration }}', 'Debug'), eq('${{ matrix.BuildPlatform }}', 'x64'))) - - - task: VSTest@2 - displayName: Run Universal Unit Tests (UWP) - timeoutInMinutes: 5 # Set smaller timeout , due to hangs - inputs: - testSelector: testAssemblies - testAssemblyVer2: | - Microsoft.ReactNative.Managed.UnitTests/Microsoft.ReactNative.Managed.UnitTests.build.appxrecipe - searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - runTestsInIsolation: true - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - publishRunAttachments: true - codeCoverageEnabled: true - collectDumpOn: onAbortOnly - vsTestVersion: latest - failOnMinTestsNotRun: true - condition: and(succeeded(), not(eq('${{ matrix.BuildPlatform }}', 'ARM64')), eq('${{ matrix.UseFabric }}', 'false')) - - - task: VSTest@2 - displayName: Run Universal Unit Tests (NetCore) - timeoutInMinutes: 5 # Set smaller timeout , due to hangs - inputs: - testSelector: testAssemblies - testAssemblyVer2: | - Microsoft.ReactNative.Managed.CodeGen.UnitTests/Microsoft.ReactNative.Managed.CodeGen.UnitTests.dll - searchFolder: $(Build.SourcesDirectory)/vnext/target/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - runTestsInIsolation: true - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - publishRunAttachments: true - codeCoverageEnabled: true - collectDumpOn: onAbortOnly - vsTestVersion: latest - failOnMinTestsNotRun: true - condition: and(succeeded(), eq('${{ matrix.BuildPlatform }}', 'x64'), eq('${{ matrix.UseFabric }}', 'false')) diff --git a/.ado/pr-pipeline.yml b/.ado/pr-pipeline.yml new file mode 100644 index 00000000000..dc744e0b64b --- /dev/null +++ b/.ado/pr-pipeline.yml @@ -0,0 +1,28 @@ +# +# The PR pipeline entry point. +# Extends build-template.yml with buildEnvironment: PullRequest for Unofficial validation builds. +# + +name: $(Date:yyyyMMdd).$(Rev:r) + +trigger: none + +pr: + - main + - master + - "*-stable" + +variables: + - group: platform-override-zero-permission-token + +extends: + template: build-template.yml@self + parameters: + buildEnvironment: PullRequest + AgentPool: + Medium: + name: rnw-pool-4 + demands: ImageOverride -equals rnw-img-vs2022-node22 + Large: + name: rnw-pool-8 + demands: ImageOverride -equals rnw-img-vs2022-node22 diff --git a/.ado/prepare-release-bot.yml b/.ado/prepare-release-bot.yml index 89bd28de7cb..8ec0586c128 100644 --- a/.ado/prepare-release-bot.yml +++ b/.ado/prepare-release-bot.yml @@ -70,10 +70,13 @@ jobs: - pwsh: Write-Host "##vso[task.setvariable variable=TargetBranch]${{ parameters.targetBranch }}" displayName: Set target branch from parameter - ${{ else }}: - - pwsh: Write-Host "##vso[task.setvariable variable=TargetBranch]$(Build.SourceBranchName)" + - pwsh: Write-Host "##vso[task.setvariable variable=TargetBranch]$env:SOURCE_BRANCH_NAME" displayName: Set target branch from source + env: + SOURCE_BRANCH_NAME: $(Build.SourceBranchName) - - script: npx prepare-release --branch $(TargetBranch) --no-color + - pwsh: npx prepare-release --branch "$env:TARGET_BRANCH" --no-color displayName: Prepare Release env: GH_TOKEN: $(GitHubOAuthToken) + TARGET_BRANCH: $(TargetBranch) diff --git a/.ado/publish.yml b/.ado/publish.yml index 08bce326528..c78eb7e3bf1 100644 --- a/.ado/publish.yml +++ b/.ado/publish.yml @@ -1,505 +1,31 @@ -name: 0.0.$(Date:yyMM.d)$(Rev:rrr) +# +# The Publish pipeline entry point. +# This file is a copy of ci-pipeline.yml kept for backward compatibility +# with *-stable branches that haven't been updated yet. +# Once all branches use ci-pipeline.yml, this file can be deleted. +# -parameters: -- name: AgentPool - type: object - default: - Medium: - name: rnw-pool-4-microsoft - demands: ImageOverride -equals rnw-img-vs2022-node22 - Large: - name: rnw-pool-8-microsoft - demands: ImageOverride -equals rnw-img-vs2022-node22 +name: 0.0.$(Date:yyMM.d)$(Rev:rrr) -- name: desktopBuildMatrix - type: object - default: - - Name: X64Debug - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: false - - Name: X64Release - BuildConfiguration: Release - BuildPlatform: x64 - UseFabric: false - - Name: X86Debug - BuildConfiguration: Debug - BuildPlatform: x86 - UseFabric: false - - Name: X86Release - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: false - - Name: ARM64ECDebug - BuildConfiguration: Debug - BuildPlatform: ARM64EC - UseFabric: false - - Name: ARM64ECRelease - BuildConfiguration: Release - BuildPlatform: ARM64EC - UseFabric: false - - Name: X64DebugFabric - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: true - - Name: X64ReleaseFabric - BuildConfiguration: Release - BuildPlatform: x64 - UseFabric: true - - Name: X86DebugFabric - BuildConfiguration: Debug - BuildPlatform: x86 - UseFabric: true - - Name: X86ReleaseFabric - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: true - - Name: ARM64ECDebugFabric - BuildConfiguration: Debug - BuildPlatform: ARM64EC - UseFabric: true - - Name: ARM64ECReleaseFabric - BuildConfiguration: Release - BuildPlatform: ARM64EC - UseFabric: true +trigger: none +pr: none -- name: universalBuildMatrix - type: object - default: - - Name: X64Release - BuildConfiguration: Release - BuildPlatform: x64 - UseFabric: false - - Name: X86Release - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: false - - Name: Arm64Release - BuildConfiguration: Release - BuildPlatform: ARM64 - UseFabric: false - - Name: X64Debug - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: false - - Name: X86Debug - BuildConfiguration: Debug - BuildPlatform: x86 - UseFabric: false - - Name: Arm64Debug - BuildConfiguration: Debug - BuildPlatform: ARM64 - UseFabric: false - - Name: X64ReleaseFabric - BuildConfiguration: Release - BuildPlatform: x64 - UseFabric: true - - Name: X86ReleaseFabric - BuildConfiguration: Release - BuildPlatform: x86 - UseFabric: true - - Name: Arm64ReleaseFabric - BuildConfiguration: Release - BuildPlatform: ARM64 - UseFabric: true - - Name: X64DebugFabric - BuildConfiguration: Debug - BuildPlatform: x64 - UseFabric: true - - Name: X86DebugFabric - BuildConfiguration: Debug - BuildPlatform: x86 - UseFabric: true - - Name: Arm64DebugFabric - BuildConfiguration: Debug - BuildPlatform: ARM64 - UseFabric: true +parameters: + - name: isReleaseBuild + displayName: 'Treat as Release build (skip beachball, use committed versions)' + type: string + default: auto + values: + - auto + - 'true' + - 'false' variables: - template: variables/windows.yml - group: RNW Secrets -trigger: none -pr: none - -resources: - repositories: - - repository: 1ESPipelineTemplates - type: git - name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release extends: - template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + template: build-template.yml@self parameters: - pool: ${{ parameters.AgentPool.Medium }} - featureFlags: - autoEnablePREfastWithNewRuleset: false # PREfast produces 0 actionable findings; auto-enable injects /analyze into every C++ TU, generating ~2656 SARIF files that Guardian uploads for ~19 min per native build - sdl: - credscan: - suppressionsFile: $(Build.SourcesDirectory)\.ado\config\CredScanSuppressions.json - spotBugs: - enabled: false # We don't have any java, but random packages in node_modules do - prefast: - enabled: false - stages: - - stage: RNWPublish - jobs: - # Set version variables - - job: SetVersionVars - displayName: Set Version Variables - pool: ${{ parameters.AgentPool.Medium }} - timeoutInMinutes: 15 - steps: - - template: .ado/templates/checkout-shallow.yml@self - - - template: .ado/templates/set-version-vars.yml@self - parameters: - buildEnvironment: Continuous - - # We new npmPack.js in Release pipeline to detect already published NPM packages and avoid publishing them again - - script: copy ".ado\scripts\npmPack.js" "$(Build.StagingDirectory)\versionEnvVars\npmPack.js" - displayName: Include npmPack.js in VersionEnvVars artifact - - templateContext: - outputs: - - output: pipelineArtifact - displayName: 'Publish version variables' - targetPath: $(Build.StagingDirectory)/versionEnvVars - artifactName: VersionEnvVars - - # Create NPM packages - - job: RnwNpmPack - displayName: Create NPM packages - pool: ${{ parameters.AgentPool.Medium }} - timeoutInMinutes: 60 - cancelTimeoutInMinutes: 5 - steps: - - template: .ado/templates/checkout-shallow.yml@self - - - template: .ado/templates/prepare-js-env.yml@self - parameters: - agentImage: HostedImage - - - script: node .ado/scripts/npmPack.js --clean --no-color "$(Pipeline.Workspace)\published-packages" - displayName: Pack npm packages - - - script: dir /s "$(Pipeline.Workspace)\published-packages" - displayName: Show created npm packages - - templateContext: - outputs: - - output: pipelineArtifact - displayName: 'Publish npm pack artifacts' - condition: succeededOrFailed() - targetPath: $(Pipeline.Workspace)/published-packages - artifactName: NpmPackedTarballs - - # Run linting - - template: .ado/jobs/linting.yml@self - parameters: - buildEnvironment: Continuous - AgentPool: ${{ parameters.AgentPool }} - - # Create and sign Destop DLLs - - ${{ each matrix in parameters.desktopBuildMatrix }}: - - job: RnwNativeBuildDesktop${{ matrix.Name }} - displayName: Build Desktop ${{ matrix.Name }} - dependsOn: SetVersionVars - pool: ${{ parameters.AgentPool.Large }} - timeoutInMinutes: 360 # CodeQL requires 3x usual build timeout - steps: - - template: .ado/templates/checkout-shallow.yml@self - - - template: .ado/templates/prepare-js-env.yml@self - - - template: .ado/templates/prepare-build-env.yml@self - parameters: - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - buildEnvironment: Publish - - - template: .ado/templates/apply-published-version-vars.yml@self - - - ${{ if eq(matrix.UseFabric, true) }}: - - template: .ado/templates/enable-fabric-experimental-feature.yml@self - - - template: .ado/templates/msbuild-sln.yml@self - parameters: - solutionDir: vnext - solutionName: ReactWindows-Desktop.sln - buildPlatform: ${{ matrix.BuildPlatform }} - buildConfiguration: ${{ matrix.BuildConfiguration }} - oneESMode: true ## Files are only copied to staging, not published - msbuildArguments: /p:ForceImportAfterCppTargets=$(Build.SourcesDirectory)\vnext\PropertySheets\CIBuildOptimizations.props - - - template: .ado/templates/publish-build-artifacts.yml@self - parameters: - oneESMode: true ## Files are only copied to staging, not published - ${{ if eq(matrix.UseFabric, true) }}: - artifactName: DesktopFabric - ${{ else }}: - artifactName: Desktop - buildPlatform: ${{ matrix.BuildPlatform }} - buildConfiguration: ${{ matrix.BuildConfiguration }} - contents: | - React.Windows.Desktop\** - React.Windows.Desktop.DLL\** - React.Windows.Desktop.Test.DLL\** - - - template: .ado/templates/esrp-codesign-binaries.yml@self - parameters: - displayName: 'CodeSign Desktop Binaries' - ${{ if eq(matrix.UseFabric, true) }}: - folderPath: $(Build.StagingDirectory)/NuGet/DesktopFabric/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - ${{ else }}: - folderPath: $(Build.StagingDirectory)/NuGet/Desktop/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - pattern: | - **/react-native-win32.dll - - templateContext: - sdl: - prefast: - enabled: false - binskim: - analyzeTargetGlob: '$(Build.SourcesDirectory)\vnext\target\${{ matrix.BuildPlatform }}\${{ matrix.BuildConfiguration }}\React.Windows.Desktop.DLL\react-native-win32.dll' - outputs: - - output: pipelineArtifact - displayName: 'Upload build logs' - condition: succeededOrFailed() - targetPath: $(BuildLogDirectory) - artifactName: Build logs - $(Agent.JobName)-$(System.JobAttempt) - - output: pipelineArtifact - displayName: 'Upload crash dumps' - condition: and(succeededOrFailed(), eq(variables.HasCrashDumps, 'True')) - targetPath: '$(CrashDumpRootPath)' - artifactName: Crash dumps - $(Agent.JobName)-$(System.JobAttempt) - - output: pipelineArtifact - ${{ if eq(matrix.UseFabric, true) }}: - displayName: 'Publish Artifact: DesktopFabric.${{matrix.buildPlatform}}.${{matrix.buildConfiguration}}' - artifactName: DesktopFabric.${{matrix.buildPlatform}}.${{matrix.buildConfiguration}} - targetPath: $(Build.StagingDirectory)/NuGet/DesktopFabric/${{matrix.buildPlatform}}/${{matrix.buildConfiguration}} - ${{ else }}: - displayName: 'Publish Artifact: Desktop.${{matrix.buildPlatform}}.${{matrix.buildConfiguration}}' - artifactName: Desktop.${{matrix.buildPlatform}}.${{matrix.buildConfiguration}} - targetPath: $(Build.StagingDirectory)/NuGet/Desktop/${{matrix.buildPlatform}}/${{matrix.buildConfiguration}} - - # Create and sign Universal DLLs - - ${{ each matrix in parameters.universalBuildMatrix }}: - - job: RnwNativeBuildUniversal${{ matrix.Name }} - displayName: Build Universal ${{ matrix.Name }} - dependsOn: SetVersionVars - pool: ${{ parameters.AgentPool.Large }} - timeoutInMinutes: 360 # CodeQL requires 3x usual build timeout - steps: - - template: .ado/templates/checkout-shallow.yml@self - - - template: .ado/templates/prepare-js-env.yml@self - - - template: .ado/templates/prepare-build-env.yml@self - parameters: - platform: ${{ matrix.BuildPlatform }} - configuration: ${{ matrix.BuildConfiguration }} - buildEnvironment: Publish - - - template: .ado/templates/apply-published-version-vars.yml@self - - - ${{ if eq(matrix.UseFabric, true) }}: - - template: .ado/templates/enable-fabric-experimental-feature.yml@self - - - template: .ado/templates/msbuild-sln.yml@self - parameters: - solutionDir: vnext - ${{ if eq(matrix.UseFabric, true) }}: - solutionName: Microsoft.ReactNative.CppOnly.slnf - ${{ else }}: - solutionName: Microsoft.ReactNative.sln - buildPlatform: ${{ matrix.BuildPlatform }} - buildConfiguration: ${{ matrix.BuildConfiguration }} - oneESMode: true ## Files are only copied to staging, not published - msbuildArguments: /p:ForceImportAfterCppTargets=$(Build.SourcesDirectory)\vnext\PropertySheets\CIBuildOptimizations.props - - - task: PowerShell@2 - displayName: Make AnyCPU Reference Assemblies - inputs: - filePath: vnext/Scripts/Tfs/Make-AnyCPU-RefAssemblies.ps1 - arguments: -TargetRoot $(Build.SourcesDirectory)\vnext\target -BuildRoot $(Build.SourcesDirectory)\vnext\target - - - template: .ado/templates/publish-build-artifacts.yml@self - parameters: - oneESMode: true ## Files are only copied to staging, not published - ${{ if eq(matrix.UseFabric, true) }}: - artifactName: ReactWindowsFabric - ${{ else }}: - artifactName: ReactWindows - buildPlatform: ${{ matrix.BuildPlatform }} - buildConfiguration: ${{ matrix.BuildConfiguration }} - contents: | - Microsoft.ReactNative\** - Microsoft.ReactNative.Managed\** - Microsoft.ReactNative.Managed.CodeGen\** - - - template: .ado/templates/esrp-codesign-binaries.yml@self - parameters: - displayName: 'CodeSign Microsoft.ReactNative Binaries' - ${{ if eq(matrix.UseFabric, true) }}: - folderPath: $(Build.StagingDirectory)/NuGet/ReactWindowsFabric/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - ${{ else }}: - folderPath: $(Build.StagingDirectory)/NuGet/ReactWindows/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - pattern: | - **/Microsoft.ReactNative.dll - **/Microsoft.ReactNative.winmd - **/Microsoft.ReactNative.Projection.dll - - templateContext: - sdl: - prefast: - enabled: false - binskim: - analyzeTargetGlob: '$(Build.SourcesDirectory)\vnext\target\${{ matrix.BuildPlatform }}\${{ matrix.BuildConfiguration }}\Microsoft.ReactNative\Microsoft.ReactNative.dll' - outputs: - - output: pipelineArtifact - displayName: 'Upload build logs' - condition: succeededOrFailed() - targetPath: $(BuildLogDirectory) - artifactName: Build logs - $(Agent.JobName)-$(System.JobAttempt) - - output: pipelineArtifact - displayName: 'Upload crash dumps' - condition: and(succeededOrFailed(), eq(variables.HasCrashDumps, 'True')) - targetPath: '$(CrashDumpRootPath)' - artifactName: Crash dumps - $(Agent.JobName)-$(System.JobAttempt) - - output: pipelineArtifact - ${{ if eq(matrix.UseFabric, true) }}: - displayName: 'Publish Artifact: ReactWindowsFabric.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }}' - artifactName: ReactWindowsFabric.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }} - targetPath: $(Build.StagingDirectory)/NuGet/ReactWindowsFabric/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - ${{ else }}: - displayName: 'Publish Artifact: ReactWindows.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }}' - artifactName: ReactWindows.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }} - targetPath: $(Build.StagingDirectory)/NuGet/ReactWindows/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} - - # Create Nuget packages - - job: RNWNuget - displayName: Pack NuGet - dependsOn: - - RnwNpmPack - - Linting - - ${{ each matrix in parameters.desktopBuildMatrix }}: - - RnwNativeBuildDesktop${{ matrix.Name }} - - ${{ each matrix in parameters.universalBuildMatrix }}: - - RnwNativeBuildUniversal${{ matrix.Name }} - pool: ${{ parameters.AgentPool.Medium }} - timeoutInMinutes: 60 # Protect against the long CodeSign task - - steps: - - template: .ado/templates/checkout-shallow.yml@self - - - template: .ado/templates/prepare-js-env.yml@self - - - template: .ado/templates/apply-published-version-vars.yml@self - - # The commit tag in the nuspec requires that we use at least nuget 5.8 (because things break with nuget versions before and VS 16.8 or later) - - task: NuGetToolInstaller@1 - inputs: - versionSpec: ">=5.8.0" - - - template: .ado/templates/prep-and-pack-nuget.yml@self - parameters: - artifactName: ReactWindows - publishCommitId: $(publishCommitId) - npmVersion: $(npmVersion) - packMicrosoftReactNative: true - packMicrosoftReactNativeCxx: true - packMicrosoftReactNativeManaged: true - packMicrosoftReactNativeManagedCodeGen: true - slices: - - platform: x64 - configuration: Release - - platform: x86 - configuration: Release - - platform: ARM64 - configuration: Release - - platform: x64 - configuration: Debug - - platform: x86 - configuration: Debug - - platform: ARM64 - configuration: Debug - - - template: .ado/templates/prep-and-pack-nuget.yml@self - parameters: - artifactName: ReactWindowsFabric - publishCommitId: $(publishCommitId) - npmVersion: $(npmVersion)-Fabric - packMicrosoftReactNative: true - packMicrosoftReactNativeCxx: true - # packMicrosoftReactNativeManaged: true - # packMicrosoftReactNativeManagedCodeGen: true - slices: - - platform: x64 - configuration: Release - - platform: x86 - configuration: Release - - platform: ARM64 - configuration: Release - - platform: x64 - configuration: Debug - - platform: x86 - configuration: Debug - - platform: ARM64 - configuration: Debug - - - template: .ado/templates/prep-and-pack-nuget.yml@self - parameters: - artifactName: Desktop - publishCommitId: $(publishCommitId) - npmVersion: $(npmVersion) - packDesktop: true - slices: - - platform: x64 - configuration: Release - - platform: x86 - configuration: Release - - platform: ARM64EC - configuration: Release - - platform: x64 - configuration: Debug - - platform: x86 - configuration: Debug - - platform: ARM64EC - configuration: Debug - - - template: .ado/templates/prep-and-pack-nuget.yml@self - parameters: - artifactName: DesktopFabric - publishCommitId: $(publishCommitId) - npmVersion: $(npmVersion)-Fabric - packDesktop: true - slices: - - platform: x64 - configuration: Release - - platform: x86 - configuration: Release - - platform: ARM64EC - configuration: Release - - platform: x64 - configuration: Debug - - platform: x86 - configuration: Debug - - platform: ARM64EC - configuration: Debug - - - template: .ado/templates/esrp-codesign-nuget.yml@self - parameters: - displayName: 'CodeSign all NuGet packages' - folderPath: $(System.DefaultWorkingDirectory)/NugetRootFinal - pattern: '**/*.nupkg' - - templateContext: - sdl: - binskim: - analyzeTargetGlob: '$(System.DefaultWorkingDirectory)\NugetRoot\**\Microsoft.ReactNative\Microsoft.ReactNative.dll;$(System.DefaultWorkingDirectory)\NugetRoot\**\React.Windows.Desktop.DLL\react-native-win32.dll' - outputs: - - output: pipelineArtifact - displayName: 'Publish final nuget artifacts' - targetPath: $(System.DefaultWorkingDirectory)\NugetRootFinal - artifactName: "ReactWindows-final-nuget" + buildEnvironment: Continuous + isReleaseBuild: ${{ parameters.isReleaseBuild }} diff --git a/.ado/release.yml b/.ado/release.yml index 4bd8ffe7f58..73928e6f5ed 100644 --- a/.ado/release.yml +++ b/.ado/release.yml @@ -55,29 +55,46 @@ extends: steps: - checkout: none - - script: | - echo == Build Variables == - echo Build.Reason: $(Build.Reason) - echo Build.SourceBranch: $(Build.SourceBranch) - echo Build.SourceVersion: $(Build.SourceVersion) - echo Build.SourceVersionMessage: $(Build.SourceVersionMessage) - echo Build.BuildNumber: $(Build.BuildNumber) - echo Build.BuildId: $(Build.BuildId) - echo Build.DefinitionName: $(Build.DefinitionName) - echo Build.Repository.Name: $(Build.Repository.Name) - echo System.TeamProject: $(System.TeamProject) - echo. - echo == Pipeline Resource: Publish == - echo Publish.runName: $(resources.pipeline.Publish.runName) - echo Publish.runID: $(resources.pipeline.Publish.runID) - echo Publish.sourceBranch: $(resources.pipeline.Publish.sourceBranch) - echo Publish.sourceCommit: $(resources.pipeline.Publish.sourceCommit) - echo Publish.pipelineID: $(resources.pipeline.Publish.pipelineID) - echo Publish.requestedFor: $(resources.pipeline.Publish.requestedFor) - echo Publish.requestedForID: $(resources.pipeline.Publish.requestedForID) + - pwsh: | + Write-Host "== Build Variables ==" + Write-Host "Build.Reason: $env:BUILD_REASON" + Write-Host "Build.SourceBranch: $env:BUILD_SOURCEBRANCH" + Write-Host "Build.SourceVersion: $env:BUILD_SOURCEVERSION" + Write-Host "Build.SourceVersionMessage: $env:BUILD_SOURCEVERSIONMESSAGE" + Write-Host "Build.BuildNumber: $env:BUILD_BUILDNUMBER" + Write-Host "Build.BuildId: $env:BUILD_BUILDID" + Write-Host "Build.DefinitionName: $env:BUILD_DEFINITIONNAME" + Write-Host "Build.Repository.Name: $env:BUILD_REPOSITORY_NAME" + Write-Host "System.TeamProject: $env:SYSTEM_TEAMPROJECT" + Write-Host "" + Write-Host "== Pipeline Resource: Publish ==" + Write-Host "Publish.runName: $env:PUBLISH_RUNNAME" + Write-Host "Publish.runID: $env:PUBLISH_RUNID" + Write-Host "Publish.sourceBranch: $env:PUBLISH_SOURCEBRANCH" + Write-Host "Publish.sourceCommit: $env:PUBLISH_SOURCECOMMIT" + Write-Host "Publish.pipelineID: $env:PUBLISH_PIPELINEID" + Write-Host "Publish.requestedFor: $env:PUBLISH_REQUESTEDFOR" + Write-Host "Publish.requestedForID: $env:PUBLISH_REQUESTEDFORID" displayName: Log all pipeline variables + env: + BUILD_REASON: $(Build.Reason) + BUILD_SOURCEBRANCH: $(Build.SourceBranch) + BUILD_SOURCEVERSION: $(Build.SourceVersion) + BUILD_SOURCEVERSIONMESSAGE: $(Build.SourceVersionMessage) + BUILD_BUILDNUMBER: $(Build.BuildNumber) + BUILD_BUILDID: $(Build.BuildId) + BUILD_DEFINITIONNAME: $(Build.DefinitionName) + BUILD_REPOSITORY_NAME: $(Build.Repository.Name) + SYSTEM_TEAMPROJECT: $(System.TeamProject) + PUBLISH_RUNNAME: $(resources.pipeline.Publish.runName) + PUBLISH_RUNID: $(resources.pipeline.Publish.runID) + PUBLISH_SOURCEBRANCH: $(resources.pipeline.Publish.sourceBranch) + PUBLISH_SOURCECOMMIT: $(resources.pipeline.Publish.sourceCommit) + PUBLISH_PIPELINEID: $(resources.pipeline.Publish.pipelineID) + PUBLISH_REQUESTEDFOR: $(resources.pipeline.Publish.requestedFor) + PUBLISH_REQUESTEDFORID: $(resources.pipeline.Publish.requestedForID) - - powershell: | + - pwsh: | $buildReason = $env:BUILD_REASON # Use only the first line of the commit message $sourceMessage = ($env:SOURCE_MESSAGE -split "`n")[0].Trim() @@ -174,7 +191,7 @@ extends: displayName: Remove already published packages - script: dir /s "$(Pipeline.Workspace)\published-packages" displayName: Show npm packages after cleanup - - powershell: | + - pwsh: | $tgzFiles = Get-ChildItem -Path "$(Pipeline.Workspace)\published-packages" -Filter "*.tgz" -Recurse $tgzCount = $tgzFiles.Count Write-Host "Found $tgzCount .tgz files" @@ -255,11 +272,11 @@ extends: steps: - task: NuGetToolInstaller@1 displayName: 'Use NuGet' - - task: CmdLine@2 + - pwsh: nuget.exe SetApiKey "$env:NUGET_API_KEY" displayName: NuGet SetApiKey (nuget.org) - inputs: - script: nuget.exe SetApiKey $(nugetorg-apiKey-push) - workingDirectory: $(Pipeline.Workspace)/ReactWindows-final-nuget + workingDirectory: $(Pipeline.Workspace)/ReactWindows-final-nuget + env: + NUGET_API_KEY: $(nugetorg-apiKey-push) - script: dir /S "$(Pipeline.Workspace)\ReactWindows-final-nuget" displayName: Show directory contents - script: nuget.exe push .\Microsoft.ReactNative.*.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -NoSymbol -NonInteractive -Verbosity Detailed @@ -278,7 +295,7 @@ extends: artifactName: 'ReactWindows-final-nuget' targetPath: '$(Pipeline.Workspace)/ReactWindows-final-nuget' steps: - - powershell: | + - pwsh: | # Extract PDB files from all NuGet packages (.nupkg are ZIP archives) $nugetDir = "$(Pipeline.Workspace)/ReactWindows-final-nuget" $symbolsDir = "$(Pipeline.Workspace)/symbols" diff --git a/.ado/stages.yml b/.ado/stages.yml deleted file mode 100644 index d727a4c7194..00000000000 --- a/.ado/stages.yml +++ /dev/null @@ -1,102 +0,0 @@ -parameters: - - name: buildEnvironment - type: string - default: PullRequest - values: - - PullRequest - - SecurePullRequest - - Continuous - - name: AgentPool - type: object - -stages: - - stage: Setup - jobs: - - template: jobs/setup.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - - - stage: Build - displayName: Build 🔨 - dependsOn: Setup - jobs: - - template: jobs/universal.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - AgentPool: ${{ parameters.AgentPool }} - - - template: jobs/desktop.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - AgentPool: ${{ parameters.AgentPool }} - - - template: jobs/nuget-desktop.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - AgentPool: ${{ parameters.AgentPool }} - - # Disabling CLI Stage as branch is Unsupported, see https://microsoft.github.io/react-native-windows/support - # - template: jobs/cli-init-windows.yml - # parameters: - # buildEnvironment: ${{ parameters.buildEnvironment }} - # AgentPool: ${{ parameters.AgentPool }} - # buildNuGetOnly: true - - # # NuGet using tests rely on "UniversalBuild" which is done in the build stage - # - template: jobs/cli-init.yml - # parameters: - # buildEnvironment: ${{ parameters.buildEnvironment }} - # AgentPool: ${{ parameters.AgentPool }} - # buildNuGetOnly: true - - - stage: IntegrationTests - displayName: Tests 🧪 - dependsOn: Setup - jobs: - - template: jobs/linting.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - AgentPool: ${{ parameters.AgentPool }} - - # - template: jobs/node-tests.yml - # parameters: - # buildEnvironment: ${{ parameters.buildEnvironment }} - # AgentPool: ${{ parameters.AgentPool }} - - - template: jobs/macos-tests.yml - - - template: jobs/playground.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - AgentPool: ${{ parameters.AgentPool }} - - - template: jobs/sample-apps.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - AgentPool: ${{ parameters.AgentPool }} - - - template: jobs/e2e-test.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - AgentPool: ${{ parameters.AgentPool }} - - - template: jobs/integration-test.yml - parameters: - buildEnvironment: ${{ parameters.buildEnvironment }} - AgentPool: ${{ parameters.AgentPool }} - - # Disabling CLI Stage as branch is Unsupported, see https://microsoft.github.io/react-native-windows/support - # - stage: CLI - # displayName: Cli 🖥 - # dependsOn: Setup - # jobs: - # - template: jobs/cli-init.yml - # parameters: - # buildEnvironment: ${{ parameters.buildEnvironment }} - # AgentPool: ${{ parameters.AgentPool }} - # buildNuGetOnly: false - - # - template: jobs/cli-init-windows.yml - # parameters: - # buildEnvironment: ${{ parameters.buildEnvironment }} - # AgentPool: ${{ parameters.AgentPool }} diff --git a/.ado/templates/cleanup-certificate.yml b/.ado/templates/cleanup-certificate.yml index 525276acb9c..70c92c7f5d3 100644 --- a/.ado/templates/cleanup-certificate.yml +++ b/.ado/templates/cleanup-certificate.yml @@ -1,5 +1,5 @@ steps: - - powershell: | + - pwsh: | $PfxPath = Join-Path -Path $(Build.SourcesDirectory) -ChildPath EncodedKey.pfx Write-Host $PfxPath Remove-Item -path $PfxPath diff --git a/.ado/templates/compute-beachball-branch-name.yml b/.ado/templates/compute-beachball-branch-name.yml index a9fb43462f1..93a578a1e11 100644 --- a/.ado/templates/compute-beachball-branch-name.yml +++ b/.ado/templates/compute-beachball-branch-name.yml @@ -1,12 +1,16 @@ steps: - - powershell: | - Write-Host "Setting BeachBallBranchName to $(System.PullRequest.TargetBranch)" - Write-Host "##vso[task.setvariable variable=BeachBallBranchName]$(System.PullRequest.TargetBranch)" + - pwsh: | + Write-Host "Setting BeachBallBranchName to $env:PR_TARGET_BRANCH" + Write-Host "##vso[task.setvariable variable=BeachBallBranchName]$env:PR_TARGET_BRANCH" displayName: Set BeachBallBranchName for Pull Request condition: ${{ eq(variables['Build.Reason'], 'PullRequest') }} + env: + PR_TARGET_BRANCH: $(System.PullRequest.TargetBranch) - - powershell: | - Write-Host "Setting BeachBallBranchName to $(Build.SourceBranchName)" - Write-Host "##vso[task.setvariable variable=BeachBallBranchName]$(Build.SourceBranchName)" + - pwsh: | + Write-Host "Setting BeachBallBranchName to $env:SOURCE_BRANCH_NAME" + Write-Host "##vso[task.setvariable variable=BeachBallBranchName]$env:SOURCE_BRANCH_NAME" displayName: Set BeachBallBranchName for CI condition: ${{ ne(variables['Build.Reason'], 'PullRequest') }} + env: + SOURCE_BRANCH_NAME: $(Build.SourceBranchName) diff --git a/.ado/templates/detect-nuget-lockfile-changes.yml b/.ado/templates/detect-nuget-lockfile-changes.yml new file mode 100644 index 00000000000..068f625b219 --- /dev/null +++ b/.ado/templates/detect-nuget-lockfile-changes.yml @@ -0,0 +1,22 @@ +parameters: + - name: errorOnNuGetLockChanges + type: boolean + default: true + +steps: + - pwsh: | + & git add */packages*.lock.json + $changed = git status --porcelain=v1 */packages*.lock.json + if ($changed -ne $null) { + Write-Host "Detected NuGet lock file changes during the build:" + Write-Host Files changed:`n([string]::Join("`n", $changed)) + $diff = git diff --cached -- */packages*.lock.json + Write-Host Diff:`n([string]::Join("`n", $diff)) + $msg = "Detected NuGet lock file changes during the build. Run vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 locally in a VS Dev PowerShell to update lock files, then submit the changes." + if ("${{ parameters.errorOnNuGetLockChanges }}" -eq "True") { + Write-Host "##vso[task.logissue type=error]Detected NuGet lock file changes during the build. Run vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 locally in a VS Dev PowerShell to update lock files, then submit the changes." + [Environment]::Exit(-1) + } + } + displayName: Detect NuGet lock file changes during build + condition: succeededOrFailed() diff --git a/.ado/templates/discover-google-test-adapter.yml b/.ado/templates/discover-google-test-adapter.yml index d2e63281ac1..2a0c05a100e 100644 --- a/.ado/templates/discover-google-test-adapter.yml +++ b/.ado/templates/discover-google-test-adapter.yml @@ -1,6 +1,6 @@ steps: - - powershell: | + - pwsh: | $vsExtensionPath="${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\Extensions\"; $GoogleTestAdapterPath=(Get-ChildItem $vsExtensionPath -Directory | Where-Object -FilterScript {Test-Path (Join-Path -Path $_.FullName -ChildPath "GoogleTestAdapter.Core.dll")}).FullName diff --git a/.ado/templates/enable-experimental-winui3.yml b/.ado/templates/enable-experimental-winui3.yml new file mode 100644 index 00000000000..a5cba36dae1 --- /dev/null +++ b/.ado/templates/enable-experimental-winui3.yml @@ -0,0 +1,26 @@ +parameters: +- name: workingDir + type: string +- name: enableInternalFeed + type: boolean + default: false # If WinUI3ExperimentalVersion in WinUI.props is only available on the ProjectReuinion feed, set to true, else if is on nuget.org, set to false + +steps: + - template: ../templates/set-experimental-feature.yml + parameters: + workingDir: ${{ parameters.workingDir }} + feature: UseExperimentalWinUI3 + value: true + + - ${{ if eq(parameters.enableInternalFeed, true) }}: + - task: PowerShell@2 + displayName: Enable the internal WinAppSDK Feed + inputs: + targetType: filePath # filePath | inline + filePath: $(Build.SourcesDirectory)\vnext\Scripts\EnableInternalWinAppSDKFeed.ps1 + pwsh: true + + - task: NuGetAuthenticate@1 + displayName: 'NuGet Authenticate Internal WinAppSDK Feed' + inputs: + nuGetServiceConnections: 'WinAppSDK Experimental NuGet for RNW' diff --git a/.ado/templates/msbuild-sln.yml b/.ado/templates/msbuild-sln.yml index 46b6842f543..9b1192c99c5 100644 --- a/.ado/templates/msbuild-sln.yml +++ b/.ado/templates/msbuild-sln.yml @@ -14,15 +14,15 @@ parameters: buildConfiguration: Debug msbuildArguments: '' warnAsError: true - oneESMode: false + parallelBuild: true steps: - - powershell: | + - pwsh: | Write-Host "##vso[task.setvariable variable=BuildLogDirectory]$(Build.BinariesDirectory)\${{ parameters.buildPlatform }}\${{ parameters.buildConfiguration }}\BuildLogs" Write-Host "##vso[task.setvariable variable=MsBuildWarnAsErrorArgument]/warnaserror" displayName: Set Log directory and warn as error - - powershell: | + - pwsh: | Write-Host "##vso[task.setvariable variable=MsBuildWarnAsErrorArgument]" condition: not(eq('${{parameters.warnAsError}}', 'true')) displayName: Disable WarnAsError @@ -36,7 +36,7 @@ steps: platform: ${{ parameters.buildPlatform }} configuration: ${{ parameters.buildConfiguration }} clean: false # Optional - maximumCpuCount: true + maximumCpuCount: ${{parameters.parallelBuild}} restoreNugetPackages: false # Optional createLogFile: true logFileVerbosity: detailed @@ -55,19 +55,8 @@ steps: $(MsBuildWarnAsErrorArgument) ${{parameters.msbuildArguments}} - - powershell: | - $changed = git status --porcelain=v1 */packages.lock.json - if ($changed -ne $null) { - Write-Host "##[warning] Detected packages.lock.json changes. See full log for details." - Write-Host Files changed:`n([string]::Join("`n", $changed)) - $diff = git diff */packages.lock.json - Write-Host Diff:`n([string]::Join("`n", $diff)) - Write-Host "Run vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 to update lock files locally." - } - displayName: Process NuGet Restore Issues - condition: succeededOrFailed() + - template: detect-nuget-lockfile-changes.yml - template: upload-build-logs.yml parameters: buildLogDirectory: $(BuildLogDirectory) - oneESMode: ${{ parameters.oneESMode }} diff --git a/.ado/templates/prep-and-pack-nuget.yml b/.ado/templates/prep-and-pack-nuget.yml index 91f1fcbc060..194bb2cebb4 100644 --- a/.ado/templates/prep-and-pack-nuget.yml +++ b/.ado/templates/prep-and-pack-nuget.yml @@ -61,11 +61,16 @@ steps: artifact: ${{ parameters.artifactName }}.${{ slice.platform }}.${{ slice.configuration }} path: ${{parameters.nugetroot}}/${{ slice.platform }}/${{ slice.configuration }} + + - pwsh: yarn build + displayName: Run yarn build + - task: PowerShell@2 displayName: Copy MSRN Resources to NuGet layout inputs: filePath: vnext/Scripts/Tfs/Layout-MSRN-Headers.ps1 arguments: -TargetRoot ${{parameters.nugetroot}} + pwsh: true - ${{ if eq(parameters.packDesktop, true) }}: - task: PowerShell@2 @@ -73,9 +78,10 @@ steps: inputs: filePath: vnext/Scripts/Tfs/Layout-Desktop-Headers.ps1 arguments: -TargetRoot ${{parameters.nugetroot}} + pwsh: true - ${{ if or(eq(parameters.packMicrosoftReactNative, true), eq(parameters.packMicrosoftReactNativeCxx, true), eq(parameters.packMicrosoftReactNativeManaged, true), eq(parameters.packMicrosoftReactNativeManagedCodeGen, true)) }}: - - powershell: | + - pwsh: | (Get-Content -Path ${{parameters.nugetroot}}\Microsoft.ReactNative.VersionCheck.targets) -replace '\$\$nuGetPackageVersion\$\$', '${{parameters.npmVersion}}' | Set-Content -Path ${{parameters.nugetroot}}\Microsoft.ReactNative.VersionCheck.targets displayName: Patch version check file with version ${{parameters.npmVersion}} diff --git a/.ado/templates/prep-and-pack-single.yml b/.ado/templates/prep-and-pack-single.yml index cdc7d7f4081..9bc1246e211 100644 --- a/.ado/templates/prep-and-pack-single.yml +++ b/.ado/templates/prep-and-pack-single.yml @@ -25,11 +25,11 @@ parameters: steps: - - powershell: gci $(System.DefaultWorkingDirectory)/NugetRoot + - pwsh: gci $(System.DefaultWorkingDirectory)/NugetRoot displayName: List files in NugetRoot - ${{ if ne(parameters.slices, '') }}: - - powershell: > + - pwsh: > .\StripAdditionalPlatformsFromNuspec.ps1 -nuspec ${{ coalesce(parameters.nuspec, parameters.outputPackage) }}.nuspec -outfile ${{ parameters.outputPackage }}.nuspec @@ -51,7 +51,7 @@ steps: packDestination: $(System.DefaultWorkingDirectory)/NugetRootFinal buildProperties: version=${{ parameters.packageVersion }};id=${{ parameters.outputPackage }};${{ parameters.buildProperties }} - - powershell: gci $(System.DefaultWorkingDirectory)/NugetRootFinal + - pwsh: gci $(System.DefaultWorkingDirectory)/NugetRootFinal displayName: List files in NugetRootFinal - script: | diff --git a/.ado/templates/prepare-build-env.yml b/.ado/templates/prepare-build-env.yml index ab5dc7e6bc8..2e81a4bad40 100644 --- a/.ado/templates/prepare-build-env.yml +++ b/.ado/templates/prepare-build-env.yml @@ -36,27 +36,27 @@ steps: configuration: ${{ parameters.configuration }} buildEnvironment: ${{ parameters.buildEnvironment }} - - powershell: | + - pwsh: | & reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /s & reg query "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /s & reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug" /s Enable-WindowsErrorReporting displayName: Check and enable Windows Error Reporting - - powershell: | + - pwsh: | Write-Host "##vso[task.setvariable variable=CrashDumpRootPath]$(Build.StagingDirectory)\CrashDumps" New-Item -Path '$(Build.StagingDirectory)\CrashDumps' -ItemType Directory displayName: Set CrashDumpRootPath - - powershell: | + - pwsh: | Write-Host "##vso[task.setvariable variable=MSBUILDDEBUGPATH]$(CrashDumpRootPath)" displayName: Set MSBUILDDEBUGPATH - - powershell: | + - pwsh: | Write-Host "##vso[task.setvariable variable=ProcDumpPath]$(Build.StagingDirectory)\Procdump" displayName: Set ProcDumpPath - - powershell: | + - pwsh: | & $(Build.SourcesDirectory)\.ado\scripts\RunProcDump.ps1 -ProcDumpArgs @("-mm", "-i", "$(CrashDumpRootPath)") -ProcDumpInstallPath "$(ProcDumpPath)" -Verbose displayName: Setup ProcDump as AeDebug \ No newline at end of file diff --git a/.ado/templates/prepare-js-env.yml b/.ado/templates/prepare-js-env.yml index 7719c91f5dc..9c7039a0716 100644 --- a/.ado/templates/prepare-js-env.yml +++ b/.ado/templates/prepare-js-env.yml @@ -13,7 +13,7 @@ steps: - task: NodeTool@0 displayName: Set Node Version inputs: - versionSpec: '22.x' + versionSpec: '24.x' - template: yarn-install.yml parameters: diff --git a/.ado/templates/publish-build-artifacts.yml b/.ado/templates/publish-build-artifacts.yml index d19f283502a..b874cfda33c 100644 --- a/.ado/templates/publish-build-artifacts.yml +++ b/.ado/templates/publish-build-artifacts.yml @@ -9,10 +9,6 @@ parameters: - name: buildConfiguration type: string default: Debug - - name: oneESMode - type: boolean - default: false - steps: - task: CopyFiles@2 displayName: Copy build artifacts to staging @@ -20,12 +16,3 @@ steps: sourceFolder: $(Build.SourcesDirectory)/vnext/target/${{ parameters.buildPlatform }}/${{ parameters.buildConfiguration }} targetFolder: $(Build.StagingDirectory)/NuGet/${{ parameters.artifactName }}/${{ parameters.buildPlatform }}/${{ parameters.buildConfiguration }} contents: ${{parameters.contents}} - - - ${{ if not(parameters.oneESMode) }}: - - task: PublishPipelineArtifact@1 - displayName: "Publish Artifact: ${{parameters.artifactName}}.${{parameters.buildPlatform}}.${{parameters.buildConfiguration}}" - # Do nothing if the artifact was already published. E.g. after rerunning a past successful job attempt - continueOnError: true - inputs: - artifactName: ${{parameters.artifactName}}.${{parameters.buildPlatform}}.${{parameters.buildConfiguration}} - targetPath: $(Build.StagingDirectory)/NuGet/${{ parameters.artifactName }}/${{ parameters.buildPlatform }}/${{ parameters.buildConfiguration }} diff --git a/.ado/templates/publish-nuget-to-ado-feed.yml b/.ado/templates/publish-nuget-to-ado-feed.yml index 48c38c92364..c716639638d 100644 --- a/.ado/templates/publish-nuget-to-ado-feed.yml +++ b/.ado/templates/publish-nuget-to-ado-feed.yml @@ -35,7 +35,7 @@ steps: # Also expose the token for the pre-push duplicate check Write-Host "##vso[task.setvariable variable=NuGetAccessToken;issecret=true]$accessToken" -- powershell: | +- pwsh: | Add-Type -AssemblyName System.IO.Compression.FileSystem $feedUrl = "${{ parameters.nugetFeedUrl }}" diff --git a/.ado/templates/react-native-init-windows.yml b/.ado/templates/react-native-init-windows.yml index 3217904e693..b1744cf3e6d 100644 --- a/.ado/templates/react-native-init-windows.yml +++ b/.ado/templates/react-native-init-windows.yml @@ -22,18 +22,14 @@ parameters: - name: useChakra type: boolean default: false - - name: useNuGet - type: boolean - default: false - name: runWack type: boolean default: false - name: buildEnvironment type: string default: PullRequest - values: + values: - PullRequest - - SecurePullRequest - Continuous steps: @@ -44,17 +40,12 @@ steps: parameters: buildEnvironment: ${{ parameters.buildEnvironment }} - - ${{ if eq(parameters.useNuGet, true) }}: - - template: prep-and-pack-nuget.yml - parameters: - artifactName: ReactWindowsFabric - npmVersion: $(npmVersion)-Fabric - packMicrosoftReactNative: true - packMicrosoftReactNativeCxx: true - slices: - - platform: ${{ parameters.platform }} - configuration: Release - + # Download the final NuGet packages produced by the RNWNuget job + - task: DownloadPipelineArtifact@2 + displayName: 'Download final NuGet packages' + inputs: + artifact: ReactWindows-final-nuget + path: $(System.DefaultWorkingDirectory)\NugetTestFeed - ${{ if endsWith(parameters.template, '-app') }}: - script: | npx --yes @react-native-community/cli@latest init testcli --version $(reactNativeDevDependency) --verbose --skip-install --install-pods false --skip-git-init true @@ -138,16 +129,16 @@ steps: value: false - ${{ if or(endsWith(parameters.template, '-app'), and(endsWith(parameters.template, '-lib'), not(startsWith(parameters.template, 'old')))) }}: - - powershell: | + - pwsh: | $path = (Get-ChildItem -Filter "Package.appxmanifest" -File -Recurse).FullName; [xml] $manifest = Get-Content $path $manifest.Package.Identity.Name = 'ReactNative.InitTest' $manifest.Save("$path") displayName: Set AppX package name to "ReactNative.InitTest" ${{ if and(endsWith(parameters.template, '-lib'), not(startsWith(parameters.template, 'old'))) }}: - workingDirectory: $(Agent.BuildDirectory)\testcli\example\windows + workingDirectory: $(Agent.BuildDirectory)\testcli\example\windows ${{ else }}: - workingDirectory: $(Agent.BuildDirectory)\testcli\windows + workingDirectory: $(Agent.BuildDirectory)\testcli\windows # End npm test server - template: verdaccio-stop.yml @@ -157,6 +148,7 @@ steps: inputs: targetType: filePath # filePath | inline filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tracing\Start-Tracing.ps1 + pwsh: true - template: react-native-debug-info.yml parameters: @@ -165,14 +157,13 @@ steps: ${{ else }}: workingDirectory: $(Agent.BuildDirectory)\testcli - - ${{ if eq(parameters.useNuGet, true) }}: - - powershell: | - nuget.exe sources add -name TestFeed -source $(System.DefaultWorkingDirectory)\NugetTestFeed - nuget.exe sources remove -name react-native - nuget.exe sources remove -name Nuget.org - nuget.exe sources add -name Nuget.org -source https://api.nuget.org/v3/index.json - displayName: Add local NuGet test feed - workingDirectory: $(Agent.BuildDirectory)\testcli + - pwsh: | + nuget.exe sources add -name TestFeed -source $(System.DefaultWorkingDirectory)\NugetTestFeed + nuget.exe sources remove -name react-native + nuget.exe sources remove -name Nuget.org + nuget.exe sources add -name Nuget.org -source https://api.nuget.org/v3/index.json + displayName: Add local NuGet test feed + workingDirectory: $(Agent.BuildDirectory)\testcli - template: ../templates/run-windows-with-certificates.yml parameters: @@ -216,11 +207,7 @@ steps: targetType: filePath # filePath | inline filePath: $(Build.SourcesDirectory)\vnext\Scripts\Tracing\Stop-Tracing.ps1 arguments: -NoAnalysis -outputFolder $(Build.StagingDirectory)/Tracing + pwsh: true condition: succeededOrFailed() - - task: PublishBuildArtifacts@1 - displayName: Upload traces - inputs: - pathtoPublish: '$(Build.StagingDirectory)/Tracing' - artifactName: 'Traces - $(Agent.JobName)-$(System.JobAttempt)' - condition: succeededOrFailed() + # Traces artifact publishing moved to templateContext.outputs in cli-init-windows.yml (1ES compliance) diff --git a/.ado/templates/run-compliance-postbuild.yml b/.ado/templates/run-compliance-postbuild.yml deleted file mode 100644 index 4b6931be493..00000000000 --- a/.ado/templates/run-compliance-postbuild.yml +++ /dev/null @@ -1,14 +0,0 @@ -# Compliance tasks to be run post build -parameters: -- name: complianceWarnOnly - displayName: Convert compliance errors to warnings - type: boolean - default: false - -steps: - # Component Governance Detection Task (https://docs.opensource.microsoft.com/tools/cg/) - # Detects open source you use and alerts you to whether it has security vulnerabilities or legal issues. - # TODO: Reconcile with existing component-governance.yml template - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: '⚖️ Component Governance Detection' - continueOnError: ${{ parameters.complianceWarnOnly }} diff --git a/.ado/templates/run-compliance-prebuild.yml b/.ado/templates/run-compliance-prebuild.yml deleted file mode 100644 index 2e0b5598406..00000000000 --- a/.ado/templates/run-compliance-prebuild.yml +++ /dev/null @@ -1,76 +0,0 @@ -# Compliance tasks to be run pre build -parameters: -- name: complianceWarnOnly - displayName: Convert compliance errors to warnings - type: boolean - default: false - -steps: - # Anti-Malware Scan Task (https://aka.ms/gdn-azdo-antimalware) - # Runs an Anti-Malware Scan on Windows agents, using Windows Defender. - - task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@4 - displayName: '⚖️ Run Anti-Malware Scan' - inputs: - InputType: 'Basic' - ScanType: 'CustomScan' - FileDirPath: $(Build.SourcesDirectory) - EnableServices: true - SupportLogOnError: false - TreatSignatureUpdateFailureAs: 'Warning' - SignatureFreshness: 'OneDay' - TreatStaleSignatureAs: 'Error' - continueOnError: ${{ parameters.complianceWarnOnly }} - - # PoliCheck Build Task (https://aka.ms/gdn-azdo-policheck) - # Scans the text of source code, comments, and content for terminology that could be sensitive for legal, cultural, or geopolitical reasons. - - task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@2 - displayName: '⚖️ Run PoliCheck' - inputs: - targetType: F - targetArgument: $(Build.SourcesDirectory) - result: PoliCheck.xml - optionsFC: 1 - optionsXS: 1 - optionsHMENABLE: 0 - optionsPE: 1|2|3|4 - optionsSEV: 1|2|3|4 - optionsUEPath: $(Build.SourcesDirectory)\.ado\config\PoliCheckExclusions.xml - optionsRulesDBPath: $(Build.SourcesDirectory)\.ado\config\PoliCheckRules.mdb - continueOnError: ${{ parameters.complianceWarnOnly }} - - # CredScan Task (https://aka.ms/gdn-azdo-credscan) - # Searches through source code and build outputs for credentials left behind in the open. - - task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@3 - displayName: '⚖️ Run CredScan' - inputs: - outputFormat: pre - suppressionsFile: $(Build.SourcesDirectory)\.ado\config\CredScanSuppressions.json - batchSize: 20 - debugMode: false - continueOnError: ${{ parameters.complianceWarnOnly }} - - - task: PublishSecurityAnalysisLogs@3 - displayName: 'Publish Guardian Artifacts' - inputs: - ArtifactName: CodeAnalysisLogs - ArtifactType: Container - PublishProcessedResults: false - AllTools: true - - # PostAnalysis Task (https://docs.microsoft.com/en-us/azure/security/develop/yaml-configuration#post-analysis-task) - # Breaks the build if any of the tasks failed. - - task: PostAnalysis@2 - displayName: "⚖️ Compliance Pre-Build Analysis" - inputs: - AllTools: false - AntiMalware: true - CredScan: true - PoliCheck: true - PoliCheckBreakOn: Severity4Above - ToolLogsNotFoundAction: "Error" - continueOnError: ${{ parameters.complianceWarnOnly }} - - # Restore unnecessary changes that were made by the compliance tasks - - script: | - git restore $(Build.SourcesDirectory)\.ado\config\PoliCheckRules.mdb - displayName: "⚖️ Compliance Pre-Build Cleanup" diff --git a/.ado/templates/run-wack.yml b/.ado/templates/run-wack.yml index fa692a3fd71..c697385e97f 100644 --- a/.ado/templates/run-wack.yml +++ b/.ado/templates/run-wack.yml @@ -5,7 +5,7 @@ parameters: type: string steps: - - powershell: .ado/scripts/TestWACK.ps1 -PackageName ${{ parameters.packageName }} -OutputDir $(Build.StagingDirectory)\WACK + - pwsh: .ado/scripts/TestWACK.ps1 -PackageName ${{ parameters.packageName }} -OutputDir $(Build.StagingDirectory)\WACK displayName: Run WACK - task: PublishBuildArtifacts@1 diff --git a/.ado/templates/run-windows-with-certificates.yml b/.ado/templates/run-windows-with-certificates.yml index 0a109108b96..820c98929a0 100644 --- a/.ado/templates/run-windows-with-certificates.yml +++ b/.ado/templates/run-windows-with-certificates.yml @@ -4,7 +4,6 @@ parameters: default: PullRequest values: - PullRequest - - SecurePullRequest - Continuous - name: buildConfiguration type: string diff --git a/.ado/templates/set-appx-platforms.yml b/.ado/templates/set-appx-platforms.yml index 47830ade907..4a949c64f51 100644 --- a/.ado/templates/set-appx-platforms.yml +++ b/.ado/templates/set-appx-platforms.yml @@ -26,5 +26,5 @@ parameters: # un-overriden path in official tests. steps: - ${{ if and(endsWith(parameters.buildEnvironment, 'PullRequest'), eq(parameters.configuration, 'Release')) }}: - - powershell: $env:AppxBundlePlatforms = "${{ parameters.platform }}" + - pwsh: $env:AppxBundlePlatforms = "${{ parameters.platform }}" displayName: Set AppxBundlePlatforms to "${{ parameters.platform }}" diff --git a/.ado/templates/set-experimental-feature.yml b/.ado/templates/set-experimental-feature.yml index d1839bed9aa..4104f316bd0 100644 --- a/.ado/templates/set-experimental-feature.yml +++ b/.ado/templates/set-experimental-feature.yml @@ -7,7 +7,7 @@ parameters: type: string steps: - - powershell: | + - pwsh: | [xml] $experimentalFeatures = Get-Content .\ExperimentalFeatures.props $nsm = New-Object Xml.XmlNamespaceManager($experimentalFeatures.NameTable) $nsm.AddNamespace('ns', $experimentalFeatures.DocumentElement.NamespaceURI) diff --git a/.ado/templates/set-version-vars.yml b/.ado/templates/set-version-vars.yml index 9d47d5d511c..a409bacf7d6 100644 --- a/.ado/templates/set-version-vars.yml +++ b/.ado/templates/set-version-vars.yml @@ -5,7 +5,6 @@ parameters: default: PullRequest values: - PullRequest - - SecurePullRequest - Continuous steps: diff --git a/.ado/templates/stop-packagers.yml b/.ado/templates/stop-packagers.yml index c121c3945ac..d83421fc9bc 100644 --- a/.ado/templates/stop-packagers.yml +++ b/.ado/templates/stop-packagers.yml @@ -3,6 +3,7 @@ steps: displayName: Cleanup any packagers left over from other builds inputs: targetType: inline # filePath | inline + pwsh: true script: | echo "ports:{" echo ${env:RNTester.PackagerPort} diff --git a/.ado/templates/upload-build-logs.yml b/.ado/templates/upload-build-logs.yml index cf2d04737ab..1e76e1187de 100644 --- a/.ado/templates/upload-build-logs.yml +++ b/.ado/templates/upload-build-logs.yml @@ -3,22 +3,13 @@ parameters: buildLogDirectory: $(Build.BinariesDirectory)\$(BuildPlatform)\$(BuildConfiguration)\BuildLogs uploadBuildLogs: true uploadCrashDumps: true - oneESMode: false - steps: - - ${{ if not(parameters.oneESMode) }}: - - task: PublishBuildArtifacts@1 - displayName: Upload build logs - condition: and(succeededOrFailed(), ${{ parameters.uploadBuildLogs }}, not(parameters.oneESMode)) - inputs: - pathtoPublish: '${{ parameters.buildLogDirectory }}' - artifactName: 'Build logs - ${{ parameters.artifactName }}' - - task: PowerShell@2 displayName: Cleanup ProcDump condition: succeededOrFailed() inputs: targetType: inline # filePath | inline + pwsh: true script: | Write-Host "Looking for procdump64 processes..."; Get-Process | ForEach-Object { @@ -39,16 +30,9 @@ steps: condition: and(succeededOrFailed(), ${{ parameters.uploadCrashDumps }}) inputs: targetType: inline # filePath | inline + pwsh: true script: | Write-Host "Looking for crash dumps in $(CrashDumpRootPath)..."; Get-ChildItem -Path $(CrashDumpRootPath) -File -Recurse; $HasCrashDumps = (Get-ChildItem -Path $(CrashDumpRootPath) -File -Recurse | Measure-Object).Count -gt 0; Write-Host "##vso[task.setvariable variable=HasCrashDumps]$HasCrashDumps"; - - - ${{ if not(parameters.oneESMode) }}: - - task: PublishBuildArtifacts@1 - displayName: Upload crash dumps - condition: and(succeededOrFailed(), ${{ parameters.uploadCrashDumps }}, eq(variables.HasCrashDumps, 'True'), not(parameters.oneESMode)) - inputs: - pathtoPublish: '$(CrashDumpRootPath)' - artifactName: 'Crash dumps - ${{ parameters.artifactName }}' diff --git a/.ado/templates/verdaccio-start.yml b/.ado/templates/verdaccio-start.yml index 6326c25d357..ade7e1f953b 100644 --- a/.ado/templates/verdaccio-start.yml +++ b/.ado/templates/verdaccio-start.yml @@ -5,7 +5,7 @@ parameters: default: true steps: - - powershell: start-process verdaccio.cmd -ArgumentList @('--config', './.ado/verdaccio/config.yaml') + - pwsh: start-process verdaccio.cmd -ArgumentList @('--config', './.ado/verdaccio/config.yaml') displayName: Launch test npm server (verdaccio) - script: node .ado/scripts/waitForVerdaccio.js @@ -17,8 +17,10 @@ steps: - template: compute-beachball-branch-name.yml - ${{ if eq(parameters.beachballPublish, true) }}: - - script: npx --yes beachball bump --branch origin/$(BeachBallBranchName) --no-push --yes --verbose --changehint "Run `yarn change` from root of repo to generate a change file." + - pwsh: npx --yes beachball bump --branch "origin/$env:BEACHBALL_BRANCH" --no-push --yes --verbose --changehint "Run 'yarn change' from root of repo to generate a change file." displayName: Beachball bump versions + env: + BEACHBALL_BRANCH: $(BeachBallBranchName) - script: node .ado/scripts/npmPack.js --clean --no-color displayName: Pack all workspace packages @@ -33,5 +35,11 @@ steps: ) displayName: Publish packages to verdaccio - - script: yarn config set registry http://localhost:4873 - displayName: Modify yarn config to point to local verdaccio server + - script: | + call npm config set registry http://localhost:4873 + call yarn config set registry http://localhost:4873 + call yarn config set npmRegistryServer http://localhost:4873 + call yarn config set unsafeHttpWhitelist --json "[\"localhost\"]" + displayName: Modify npm/yarn config to point to local verdaccio server + env: + YARN_ENABLE_IMMUTABLE_INSTALLS: false diff --git a/.ado/templates/verdaccio-stop.yml b/.ado/templates/verdaccio-stop.yml index 18c7a21566f..b7a4108fc4f 100644 --- a/.ado/templates/verdaccio-stop.yml +++ b/.ado/templates/verdaccio-stop.yml @@ -10,12 +10,4 @@ steps: displayName: Kill Verdaccio condition: succeededOrFailed() - - ${{ if eq(parameters.uploadLogs, true) }}: - # We are experiencing random package restore failures. - # We want to uploading the vedaccio logs to aid in diagnosing if it is verdaccio or npmjs.org - - task: PublishPipelineArtifact@1 - displayName: Upload Verdaccio.log (on failure) - inputs: - targetPath: 'verdaccio.log' - artifact: '$(Agent.JobName).Verdaccio.log-$(System.JobAttempt)' - condition: failed() + # Verdaccio log artifact publishing moved to templateContext.outputs in cli-init-windows.yml (1ES compliance) diff --git a/.ado/templates/write-certificate.yml b/.ado/templates/write-certificate.yml index 271272f1ffd..88d770b0569 100644 --- a/.ado/templates/write-certificate.yml +++ b/.ado/templates/write-certificate.yml @@ -4,7 +4,7 @@ parameters: default: 'pwd' steps: - - powershell: | + - pwsh: | $certStoreRoot="cert:\CurrentUser\My" $rootFolder="$(Build.SourcesDirectory)" diff --git a/.ado/variables/shared.yml b/.ado/variables/shared.yml index 4b9be6e5fc9..8a41ec1889e 100644 --- a/.ado/variables/shared.yml +++ b/.ado/variables/shared.yml @@ -1,10 +1,4 @@ variables: - # Task auto-injection configuration - Codeql.SkipTaskAutoInjection: true - NugetSecurityAnalysisWarningLevel: 'warn' - runCodesignValidationInjection: false - skipComponentGovernanceDetection: true - # Enables `chalk` to show colored output to Azure Pipelines FORCE_COLOR: 3 diff --git a/.ado/windows-vs-pr-secure.yml b/.ado/windows-vs-pr-secure.yml deleted file mode 100644 index 3601bce96c8..00000000000 --- a/.ado/windows-vs-pr-secure.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: $(Date:yyyyMMdd).$(Rev:r) - -trigger: none # will disable CI builds entirely - -pr: - - main - - master - - "*-stable" - -variables: - - group: platform-override-zero-permission-token - -parameters: - - name: AgentPool - type: object - default: - Small: - name: rnw-pool-2 - demands: ImageOverride -equals rnw-img-vs2022-node22 - Medium: - name: rnw-pool-4 - demands: ImageOverride -equals rnw-img-vs2022-node22 - Large: - name: rnw-pool-8 - demands: ImageOverride -equals rnw-img-vs2022-node22 - -stages: - - template: stages.yml - parameters: - buildEnvironment: SecurePullRequest - AgentPool: ${{ parameters.AgentPool }} diff --git a/.ado/windows-vs-pr.yml b/.ado/windows-vs-pr.yml index ae79db81131..c97e1695768 100644 --- a/.ado/windows-vs-pr.yml +++ b/.ado/windows-vs-pr.yml @@ -1,6 +1,13 @@ +# +# The PR pipeline entry point. +# This file is a copy of pr-pipeline.yml kept for backward compatibility +# with *-stable branches that haven't been updated yet. +# Once all branches use pr-pipeline.yml, this file can be deleted. +# + name: $(Date:yyyyMMdd).$(Rev:r) -trigger: none # will disable CI builds entirely +trigger: none pr: - main @@ -10,22 +17,14 @@ pr: variables: - group: platform-override-zero-permission-token -parameters: - - name: AgentPool - type: object - default: - Small: - name: rnw-pool-2 - demands: ImageOverride -equals rnw-img-vs2022-node22 +extends: + template: build-template.yml@self + parameters: + buildEnvironment: PullRequest + AgentPool: Medium: name: rnw-pool-4 demands: ImageOverride -equals rnw-img-vs2022-node22 Large: name: rnw-pool-8 demands: ImageOverride -equals rnw-img-vs2022-node22 - -stages: - - template: stages.yml - parameters: - buildEnvironment: PullRequest - AgentPool: ${{ parameters.AgentPool }} diff --git a/docs/build-pipelines.md b/docs/build-pipelines.md new file mode 100644 index 00000000000..35327b6782b --- /dev/null +++ b/docs/build-pipelines.md @@ -0,0 +1,105 @@ +# Build Pipelines + +React Native Windows uses three Azure DevOps pipelines, all built on the 1ES Pipeline Templates. + +## Pipeline Overview + +| Pipeline | File | Template | Trigger | +|----------|------|----------|---------| +| **CI** | `ci-pipeline.yml` | 1ES Official | Push to `main`, `*-stable` | +| **PR** | `pr-pipeline.yml` | 1ES Unofficial | PRs to `main`, `*-stable` | +| **Release** | `release.yml` | 1ES Official | Triggered by successful CI run | + +CI and PR share a single `build-template.yml` that contains all build, test, and packaging logic. The `buildEnvironment` parameter (`Continuous` or `PullRequest`) controls what runs: + +- **Both**: build, test, lint, NuGet pack, CLI init verification +- **CI only**: ESRP code signing, release tagging +- **PR only**: beachball change file check + +## Stages + +``` +Setup ──┬── Build ──── CLI + │ + └── Tests +``` + +### Setup + +Detects whether this is a **release build** (commit message starts with `RELEASE:`) or a **developer build**. For developer builds, runs beachball to bump versions. Publishes version variables for all downstream stages. + +### Build + +Runs in parallel for each platform/configuration in the build matrix: + +- **Desktop** (x64/x86/ARM64EC, Debug/Release) — builds, runs unit and integration tests, signs shipping binaries (CI) +- **Universal** (x64/x86/ARM64, Debug/Release) — builds, runs unit tests, signs shipping binaries (CI) +- **Linting** — JS/TS lint, format check, override validation +- **NPM Pack** — creates npm tarballs +- **NuGet Pack** — downloads all build artifacts, packs NuGet packages, ESRP signs them (CI) + +Each build job uses `*-single.yml` step templates that build the full `.sln`, run tests, and stage shipping artifacts — we test what we ship. + +### Tests + +Runs in parallel with Build (both depend only on Setup): + +- **Node Tests** — Jest-based JavaScript tests +- **Playground** — builds playground apps across configs +- **E2E Tests** — Fabric end-to-end tests + +### CLI + +Depends on Build (needs the NuGet packages). Runs `react-native init` + `react-native-windows init` against the just-built packages to verify the developer experience works. + +## Agent Pools + +| Pool | Used By | +|------|---------| +| `rnw-pool-4-microsoft` | CI: most jobs (default) | +| `rnw-pool-8-microsoft` | CI: native builds (Desktop, Universal) | +| `rnw-pool-4` | PR: most jobs (default) | +| `rnw-pool-8` | PR: native builds | + +PR uses public pools (no `-microsoft` suffix). The PR entry point overrides the pool defaults. + +## SDL & Compliance + +The 1ES Official template (CI) handles SDL automatically: + +- **CredScan** — credential scanning +- **BinSkim** — binary security analysis (per-job targets via `templateContext.sdl`) +- **Component Governance** — open-source license compliance +- **CodeQL** — static analysis +- **ESLint** — JS/TS analysis (with exclusions) + +PREfast, SpotBugs, and Bandit are disabled (no actionable findings for this repo). + +## Release Flow + +1. Developer merges a PR to `main` +2. **CI pipeline** runs: build, test, sign, pack +3. On success, a separate **prepare-release-bot** pipeline creates/updates a release PR (e.g., `prepare-release/main`) +4. When the release PR is merged (commit message: `RELEASE: ...`), CI runs again as a **release build**: + - Skips beachball bump (versions already committed) + - Builds, tests, signs, packs + - Tags the source commit (`react-native-windows_v`) +5. **Release pipeline** triggers on successful CI, publishing packages to npm and NuGet feeds + +## Key Files + +| File | Purpose | +|------|---------| +| `.ado/ci-pipeline.yml` | CI entry point | +| `.ado/pr-pipeline.yml` | PR entry point | +| `.ado/build-template.yml` | Shared build/test/pack logic | +| `.ado/release.yml` | Release pipeline (publishes to feeds) | +| `.ado/jobs/desktop-single.yml` | Desktop build + test steps | +| `.ado/jobs/universal-single.yml` | Universal build + test steps | +| `.ado/jobs/cli-init-windows.yml` | CLI init verification | +| `.ado/jobs/e2e-test.yml` | E2E test job | +| `.ado/jobs/playground.yml` | Playground build job | +| `.ado/jobs/linting.yml` | Linting job | +| `.ado/jobs/node-tests.yml` | Node/Jest test job | +| `.ado/templates/prep-and-pack-nuget.yml` | NuGet packing steps | +| `.ado/templates/esrp-codesign-*.yml` | ESRP signing steps | diff --git a/packages/@rnw-scripts/prepare-release/src/beachballBump.ts b/packages/@rnw-scripts/prepare-release/src/beachballBump.ts index 8658d308d5e..68c57c3f8e7 100644 --- a/packages/@rnw-scripts/prepare-release/src/beachballBump.ts +++ b/packages/@rnw-scripts/prepare-release/src/beachballBump.ts @@ -25,7 +25,7 @@ export function hasChangeFiles(repoRoot: string): boolean { } const entries = fs.readdirSync(changeDir); - return entries.some(entry => entry.endsWith('.json')); + return entries.some((entry: string) => entry.endsWith('.json')); } /** diff --git a/packages/@rnw-scripts/prepare-release/src/prepareRelease.ts b/packages/@rnw-scripts/prepare-release/src/prepareRelease.ts index 0b247386978..3056f061de0 100644 --- a/packages/@rnw-scripts/prepare-release/src/prepareRelease.ts +++ b/packages/@rnw-scripts/prepare-release/src/prepareRelease.ts @@ -7,7 +7,7 @@ * "Version Packages" pull request. * * Usage: - * npx prepare-release --branch [--dry-run] [--no-color] [--help] + * npx prepare-release --branch [--bump-only] [--dry-run] [--no-color] [--help] * * @format */ @@ -64,13 +64,15 @@ Usage: npx prepare-release --branch [options] Options: - --branch Target branch to prepare release for (required) + --branch Target branch for version baseline (required) + --bump-only Only run beachball bump in current working tree, skip git/PR operations --dry-run Do everything except push and PR create/update --no-color Disable colored output --help, -h Show this help message Examples: npx prepare-release --branch main + npx prepare-release --branch main --bump-only npx prepare-release --branch 0.76-stable --dry-run `); } @@ -161,6 +163,7 @@ async function detectRemote(git: GitRepo, repoUrl: string): Promise { const {values} = parseArgs({ options: { branch: {type: 'string'}, + 'bump-only': {type: 'boolean', default: false}, 'dry-run': {type: 'boolean', default: false}, help: {type: 'boolean', short: 'h', default: false}, 'no-color': {type: 'boolean', default: false}, @@ -181,9 +184,12 @@ async function detectRemote(git: GitRepo, repoUrl: string): Promise { process.exit(1); } + const bumpOnly = values['bump-only']; const dryRun = values['dry-run']; - if (dryRun) { + if (bumpOnly) { + console.log(colorize('[BUMP-ONLY MODE]', ansi.yellow)); + } else if (dryRun) { console.log(colorize('[DRY RUN MODE]', ansi.yellow)); } @@ -225,6 +231,20 @@ async function detectRemote(git: GitRepo, repoUrl: string): Promise { } console.log(colorize('Found pending change files.', ansi.green)); + // 6b. Bump-only mode: run beachball bump in-place and exit + if (bumpOnly) { + console.log(colorize('Running beachball bump...', ansi.bright)); + await bumpVersions({ + targetBranch, + remote: remoteName, + cwd: repoRoot, + }); + console.log( + colorize('Bump complete (--bump-only mode).', ansi.green + ansi.bright), + ); + process.exit(0); + } + // 7. Check for existing PR const prBranch = `prepare-release/${targetBranch}`; console.log( From b18bf56c07c51bec1b00194aeed3b8d7036fb714 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Mon, 30 Mar 2026 16:51:00 -0700 Subject: [PATCH 02/10] Update packages.lock files --- .../packages.lock.json | 16 ++++++++-------- .../packages.lock.json | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/vnext/Microsoft.ReactNative.Managed.IntegrationTests/packages.lock.json b/vnext/Microsoft.ReactNative.Managed.IntegrationTests/packages.lock.json index afc979a07a8..b86fcbf82e5 100644 --- a/vnext/Microsoft.ReactNative.Managed.IntegrationTests/packages.lock.json +++ b/vnext/Microsoft.ReactNative.Managed.IntegrationTests/packages.lock.json @@ -264,7 +264,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1" @@ -500,7 +500,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -719,7 +719,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -950,7 +950,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -1159,7 +1159,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -1378,7 +1378,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -1587,7 +1587,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -1806,7 +1806,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", diff --git a/vnext/Microsoft.ReactNative.Managed.UnitTests/packages.lock.json b/vnext/Microsoft.ReactNative.Managed.UnitTests/packages.lock.json index afc979a07a8..b86fcbf82e5 100644 --- a/vnext/Microsoft.ReactNative.Managed.UnitTests/packages.lock.json +++ b/vnext/Microsoft.ReactNative.Managed.UnitTests/packages.lock.json @@ -264,7 +264,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1" @@ -500,7 +500,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -719,7 +719,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -950,7 +950,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -1159,7 +1159,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -1378,7 +1378,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -1587,7 +1587,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", @@ -1806,7 +1806,7 @@ "System.Runtime": { "type": "Transitive", "resolved": "4.1.0", - "contentHash": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==", + "contentHash": "SwXraLtIWEZwfE/jOT+WFtP/tsX2KhIdgRQt330CQckx/pbRk7e/Aigak2hFjgdkRmdmVXz6lwkDXcdtj913Bg==", "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Targets": "1.0.1", From 96855930015b53806fcc3dab28548d5e9e1526cc Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Mon, 30 Mar 2026 17:55:23 -0700 Subject: [PATCH 03/10] Change files --- ...ative-windows-85865597-3803-4fce-b212-a51f3bcf9666.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/react-native-windows-85865597-3803-4fce-b212-a51f3bcf9666.json diff --git a/change/react-native-windows-85865597-3803-4fce-b212-a51f3bcf9666.json b/change/react-native-windows-85865597-3803-4fce-b212-a51f3bcf9666.json new file mode 100644 index 00000000000..8ae68d8c419 --- /dev/null +++ b/change/react-native-windows-85865597-3803-4fce-b212-a51f3bcf9666.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "[0.74] Changes to PR, CI, and Release pipelines", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch" +} From 07c2e1c9251c4f80e577a122310276c72f930d13 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Mon, 30 Mar 2026 18:24:58 -0700 Subject: [PATCH 04/10] Fix package name --- .../telemetry/src/test/projectUtils.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-native-windows/telemetry/src/test/projectUtils.test.ts b/packages/@react-native-windows/telemetry/src/test/projectUtils.test.ts index f7c314f132a..d1a37ab50db 100644 --- a/packages/@react-native-windows/telemetry/src/test/projectUtils.test.ts +++ b/packages/@react-native-windows/telemetry/src/test/projectUtils.test.ts @@ -75,7 +75,7 @@ test('configToProjectInfo() works with playground project info', async () => { const projectInfo = info as projectUtils.AppProjectInfo; expect(projectInfo.id).toBe( - projectUtils.getProjectId('@rnw-scripts/playground'), + projectUtils.getProjectId('playground'), ); expect(projectInfo.platforms).toStrictEqual(['windows']); expect(projectInfo.rnwLang).toBe('cpp'); From a9d1a8587e76e416ea9ba2e96a06de55d2691006 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Mon, 30 Mar 2026 18:37:05 -0700 Subject: [PATCH 05/10] Change files --- ...ows-telemetry-0db59ca1-815a-4439-a294-6a78dd1d3438.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@react-native-windows-telemetry-0db59ca1-815a-4439-a294-6a78dd1d3438.json diff --git a/change/@react-native-windows-telemetry-0db59ca1-815a-4439-a294-6a78dd1d3438.json b/change/@react-native-windows-telemetry-0db59ca1-815a-4439-a294-6a78dd1d3438.json new file mode 100644 index 00000000000..bde86ce9ece --- /dev/null +++ b/change/@react-native-windows-telemetry-0db59ca1-815a-4439-a294-6a78dd1d3438.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "[0.74] Changes to PR, CI, and Release pipelines", + "packageName": "@react-native-windows/telemetry", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch" +} From 1b90721ab3c89a3676112d1694d776ea00f3ee72 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Tue, 31 Mar 2026 10:51:11 -0700 Subject: [PATCH 06/10] New release-pipeline.yml file (#15881) --- .ado/release-pipeline.yml | 348 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 .ado/release-pipeline.yml diff --git a/.ado/release-pipeline.yml b/.ado/release-pipeline.yml new file mode 100644 index 00000000000..9739ec36050 --- /dev/null +++ b/.ado/release-pipeline.yml @@ -0,0 +1,348 @@ +# +# The Release pipeline entry point. +# It publishes npm packages to npmjs.com, NuGet packages to the public +# ms/react-native and ms/react-native-public ADO feeds and to nuget.org, +# and PDB symbols to the Microsoft Symbol Server. +# +# This file replaces release.yml and references the renamed "CI" pipeline +# (formerly "Publish"). Once all branches use this file, release.yml can +# be deleted. +# +# The pipeline completion trigger is defined below in the pipeline resource. +# Do NOT add a build completion trigger in the ADO UI — UI triggers override +# YAML triggers and cause the pipeline to always run against the default branch +# with incorrect metadata (wrong commit message and branch). +# + +name: RNW Release $(Date:yyyyMMdd).$(Rev:r) + +trigger: none +pr: none + +resources: + pipelines: + - pipeline: 'CI' + project: 'ReactNative' + source: 'CI' + trigger: + branches: + include: + - main + - '0.74-stable' + - '0.81-stable' + - '0.82-stable' + - '0.83-stable' + - '0.84-stable' + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + parameters: + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: windows-latest + os: windows + stages: + # + # Gate stage — runs unconditionally for every trigger. + # It determines whether the Release stage should proceed and sets a + # descriptive build number so the pipeline history is easy to scan. + # + - stage: Gate + displayName: Evaluate release + jobs: + - job: Evaluate + displayName: Check if release should proceed + steps: + - checkout: none + + - pwsh: | + Write-Host "== Build Variables ==" + Write-Host "Build.Reason: $env:BUILD_REASON" + Write-Host "Build.SourceBranch: $env:BUILD_SOURCEBRANCH" + Write-Host "Build.SourceVersion: $env:BUILD_SOURCEVERSION" + Write-Host "Build.SourceVersionMessage: $env:BUILD_SOURCEVERSIONMESSAGE" + Write-Host "Build.BuildNumber: $env:BUILD_BUILDNUMBER" + Write-Host "Build.BuildId: $env:BUILD_BUILDID" + Write-Host "Build.DefinitionName: $env:BUILD_DEFINITIONNAME" + Write-Host "Build.Repository.Name: $env:BUILD_REPOSITORY_NAME" + Write-Host "System.TeamProject: $env:SYSTEM_TEAMPROJECT" + Write-Host "" + Write-Host "== Pipeline Resource: CI ==" + Write-Host "CI.runName: $env:CI_RUNNAME" + Write-Host "CI.runID: $env:CI_RUNID" + Write-Host "CI.sourceBranch: $env:CI_SOURCEBRANCH" + Write-Host "CI.sourceCommit: $env:CI_SOURCECOMMIT" + Write-Host "CI.pipelineID: $env:CI_PIPELINEID" + Write-Host "CI.requestedFor: $env:CI_REQUESTEDFOR" + Write-Host "CI.requestedForID: $env:CI_REQUESTEDFORID" + displayName: Log all pipeline variables + env: + BUILD_REASON: $(Build.Reason) + BUILD_SOURCEBRANCH: $(Build.SourceBranch) + BUILD_SOURCEVERSION: $(Build.SourceVersion) + BUILD_SOURCEVERSIONMESSAGE: $(Build.SourceVersionMessage) + BUILD_BUILDNUMBER: $(Build.BuildNumber) + BUILD_BUILDID: $(Build.BuildId) + BUILD_DEFINITIONNAME: $(Build.DefinitionName) + BUILD_REPOSITORY_NAME: $(Build.Repository.Name) + SYSTEM_TEAMPROJECT: $(System.TeamProject) + CI_RUNNAME: $(resources.pipeline.CI.runName) + CI_RUNID: $(resources.pipeline.CI.runID) + CI_SOURCEBRANCH: $(resources.pipeline.CI.sourceBranch) + CI_SOURCECOMMIT: $(resources.pipeline.CI.sourceCommit) + CI_PIPELINEID: $(resources.pipeline.CI.pipelineID) + CI_REQUESTEDFOR: $(resources.pipeline.CI.requestedFor) + CI_REQUESTEDFORID: $(resources.pipeline.CI.requestedForID) + + - pwsh: | + $buildReason = $env:BUILD_REASON + # Use only the first line of the commit message + $sourceMessage = ($env:SOURCE_MESSAGE -split "`n")[0].Trim() + $ciRunName = $env:CI_RUN_NAME + $sourceBranch = $env:SOURCE_BRANCH -replace '^refs/heads/', '' + + # Extract the datestamp (e.g. "20260319.4") from the original build number + # which has the format "RNW Release 20260319.4" + $originalBuildNumber = $env:BUILD_BUILDNUMBER + $dateStamp = if ($originalBuildNumber -match '(\d{8}\.\d+)$') { $Matches[1] } else { "" } + + $shouldRelease = $false + $buildNumber = "" + + if ($buildReason -eq "Manual") { + $shouldRelease = $true + if ($ciRunName) { + $buildNumber = "$ciRunName ($sourceBranch) - $dateStamp" + } else { + $buildNumber = "Release ($sourceBranch) - $dateStamp" + } + } + elseif ($sourceMessage.StartsWith("RELEASE:")) { + $shouldRelease = $true + $buildNumber = "$ciRunName ($sourceBranch) - $dateStamp" + } + else { + $shouldRelease = $false + # Truncate commit message for readability + $shortMsg = $sourceMessage + if ($shortMsg.Length -gt 60) { + $shortMsg = $shortMsg.Substring(0, 57) + "..." + } + $buildNumber = "Skipped - $shortMsg ($sourceBranch) - $dateStamp" + } + + # Sanitize: ADO build numbers cannot contain " / : < > \ | ? @ * + # and cannot end with '.' + $buildNumber = $buildNumber -replace '["/:<>\\|?@*]', '_' + $buildNumber = $buildNumber.TrimEnd('.') + + Write-Host "shouldRelease: $shouldRelease" + Write-Host "buildNumber: $buildNumber" + + Write-Host "##vso[build.updatebuildnumber]$buildNumber" + Write-Host "##vso[task.setvariable variable=shouldRelease;isOutput=true]$shouldRelease" + name: gate + displayName: Determine release eligibility and set build number + env: + BUILD_REASON: $(Build.Reason) + BUILD_BUILDNUMBER: $(Build.BuildNumber) + SOURCE_MESSAGE: $(Build.SourceVersionMessage) + CI_RUN_NAME: $(resources.pipeline.CI.runName) + SOURCE_BRANCH: $(resources.pipeline.CI.sourceBranch) + + - script: echo Proceeding with release + displayName: RELEASING - proceeding to publish + condition: eq(variables['gate.shouldRelease'], 'True') + + - script: echo Skipping release + displayName: SKIPPED - not a RELEASE commit + condition: eq(variables['gate.shouldRelease'], 'False') + + - stage: Release + displayName: Publish artifacts + dependsOn: Gate + condition: eq(dependencies.Gate.outputs['Evaluate.gate.shouldRelease'], 'True') + jobs: + - job: PushNpm + displayName: npmjs.com - Publish npm packages + variables: + - group: RNW Secrets + timeoutInMinutes: 30 + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + pipeline: 'CI' + artifactName: 'NpmPackedTarballs' + targetPath: '$(Pipeline.Workspace)/published-packages' + - input: pipelineArtifact + pipeline: 'CI' + artifactName: 'VersionEnvVars' + targetPath: '$(Pipeline.Workspace)/VersionEnvVars' + steps: + - task: CmdLine@2 + displayName: Apply version variables + inputs: + script: node $(Pipeline.Workspace)/VersionEnvVars/versionEnvVars.js + - script: dir /s "$(Pipeline.Workspace)\published-packages" + displayName: Show npm packages before cleanup + - script: node "$(Pipeline.Workspace)\VersionEnvVars\npmPack.js" --no-pack --check-npm --no-color "$(Pipeline.Workspace)\published-packages" + displayName: Remove already published packages + - script: dir /s "$(Pipeline.Workspace)\published-packages" + displayName: Show npm packages after cleanup + - pwsh: | + $tgzFiles = Get-ChildItem -Path "$(Pipeline.Workspace)\published-packages" -Filter "*.tgz" -Recurse + $tgzCount = $tgzFiles.Count + Write-Host "Found $tgzCount .tgz files" + Write-Host "##vso[task.setvariable variable=HasPackagesToPublish]$($tgzCount -gt 0)" + displayName: Check if there are packages to publish + - task: 'EsrpRelease@11' + displayName: 'ESRP Release to npmjs.com' + condition: and(succeeded(), ne(variables['NpmDistTag'], ''), eq(variables['HasPackagesToPublish'], 'true')) + inputs: + connectedservicename: 'ESRP-CodeSigning-OGX-JSHost-RNW' + usemanagedidentity: false + keyvaultname: 'OGX-JSHost-KV' + authcertname: 'OGX-JSHost-Auth4' + signcertname: 'OGX-JSHost-Sign3' + clientid: '0a35e01f-eadf-420a-a2bf-def002ba898d' + domaintenantid: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' + contenttype: npm + folderlocation: '$(Pipeline.Workspace)\published-packages' + productstate: '$(NpmDistTag)' + owners: 'vmorozov@microsoft.com' + approvers: 'khosany@microsoft.com' + + - job: PushPrivateAdo + displayName: ADO - nuget - react-native + timeoutInMinutes: 30 + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + pipeline: 'CI' + artifactName: 'ReactWindows-final-nuget' + targetPath: '$(Pipeline.Workspace)/ReactWindows-final-nuget' + steps: + - template: .ado/templates/publish-nuget-to-ado-feed.yml@self + parameters: + endpointId: 'a7e33797-4804-4a1d-911d-5bd325e50a85' + nugetFeedUrl: 'https://pkgs.dev.azure.com/ms/_packaging/react-native/nuget/v3/index.json' + packageParentPath: '$(Pipeline.Workspace)/ReactWindows-final-nuget' + packagesToPush: '$(Pipeline.Workspace)/ReactWindows-final-nuget/*.nupkg' + publishFeedCredentials: 'ms/react-native ADO Feed' + feedDisplayName: 'ms/react-native' + + - job: PushPublicAdo + displayName: ADO - nuget - react-native-public + timeoutInMinutes: 30 + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + pipeline: 'CI' + artifactName: 'ReactWindows-final-nuget' + targetPath: '$(Pipeline.Workspace)/ReactWindows-final-nuget' + steps: + - template: .ado/templates/publish-nuget-to-ado-feed.yml@self + parameters: + endpointId: '9a2456d0-c163-405b-be24-c03fd74b155a' + nugetFeedUrl: 'https://pkgs.dev.azure.com/ms/react-native/_packaging/react-native-public/nuget/v3/index.json' + packageParentPath: '$(Pipeline.Workspace)/ReactWindows-final-nuget' + packagesToPush: '$(Pipeline.Workspace)/ReactWindows-final-nuget/*.nupkg' + publishFeedCredentials: 'ms/react-native-public ADO Feed' + feedDisplayName: 'ms/react-native-public' + + - job: PushNuGetOrg + displayName: nuget.org - Push nuget packages + variables: + - group: RNW Secrets + timeoutInMinutes: 30 + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + pipeline: 'CI' + artifactName: 'ReactWindows-final-nuget' + targetPath: '$(Pipeline.Workspace)/ReactWindows-final-nuget' + steps: + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet' + - pwsh: nuget.exe SetApiKey "$env:NUGET_API_KEY" + displayName: NuGet SetApiKey (nuget.org) + workingDirectory: $(Pipeline.Workspace)/ReactWindows-final-nuget + env: + NUGET_API_KEY: $(nugetorg-apiKey-push) + - script: dir /S "$(Pipeline.Workspace)\ReactWindows-final-nuget" + displayName: Show directory contents + - script: nuget.exe push .\Microsoft.ReactNative.*.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -NoSymbol -NonInteractive -Verbosity Detailed + displayName: NuGet push (nuget.org) + workingDirectory: $(Pipeline.Workspace)/ReactWindows-final-nuget + + - job: PublishSymbols + displayName: Publish PDB Symbols to Symbol Server + timeoutInMinutes: 30 + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + pipeline: 'CI' + artifactName: 'ReactWindows-final-nuget' + targetPath: '$(Pipeline.Workspace)/ReactWindows-final-nuget' + steps: + - pwsh: | + # Extract PDB files from all NuGet packages (.nupkg are ZIP archives) + $nugetDir = "$(Pipeline.Workspace)/ReactWindows-final-nuget" + $symbolsDir = "$(Pipeline.Workspace)/symbols" + New-Item -ItemType Directory -Path $symbolsDir -Force | Out-Null + + $nupkgs = Get-ChildItem "$nugetDir/*.nupkg" + Write-Host "Found $($nupkgs.Count) NuGet packages" + + foreach ($nupkg in $nupkgs) { + Write-Host "Extracting PDBs from: $($nupkg.Name)" + $extractDir = "$symbolsDir/$($nupkg.BaseName)" + # Rename to .zip for Expand-Archive compatibility + $zipPath = "$nugetDir/$($nupkg.BaseName).zip" + Copy-Item $nupkg.FullName $zipPath + Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force + Remove-Item $zipPath + } + + # Show extracted PDBs + $pdbs = Get-ChildItem "$symbolsDir" -Recurse -Filter "*.pdb" + Write-Host "`nFound $($pdbs.Count) PDB files:" + foreach ($pdb in $pdbs) { + Write-Host " $($pdb.FullName) ($([math]::Round($pdb.Length / 1MB, 2)) MB)" + } + + if ($pdbs.Count -eq 0) { + Write-Host "##vso[task.logissue type=warning]No PDB files found in NuGet packages" + } + displayName: Extract PDBs from NuGet packages + + - task: PublishSymbols@2 + displayName: 'Publish Symbols to Microsoft Symbol Server' + continueOnError: true + inputs: + UseNetCoreClientTool: true + ConnectedServiceName: Office-React-Native-Windows-Bot + SymbolsFolder: '$(Pipeline.Workspace)/symbols' + SearchPattern: '**/*.pdb' + SymbolServerType: 'TeamServices' + IndexSources: false # SourceLink is already embedded in PDBs at compile time + SymbolsProduct: 'ReactNativeWindows' + SymbolsVersion: '$(Build.BuildNumber)' + SymbolsArtifactName: 'ReactNativeWindows-Symbols-$(Build.BuildId)' + DetailedLog: true + TreatNotIndexedAsWarning: false From e3740d3dbde32d01c37cdcc2ab494e998b8a8ad8 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Tue, 31 Mar 2026 10:51:30 -0700 Subject: [PATCH 07/10] Disable CodeQL in Setup job (#15882) --- .ado/build-template.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.ado/build-template.yml b/.ado/build-template.yml index 80e14c92903..de334fd3180 100644 --- a/.ado/build-template.yml +++ b/.ado/build-template.yml @@ -270,6 +270,9 @@ extends: condition: and(succeeded(), eq('${{ parameters.buildEnvironment }}', 'Continuous')) templateContext: + sdl: + codeql: + enabled: false outputs: - output: pipelineArtifact displayName: 'Publish version variables' From a769d46e98a483a07c6abd77ddaa69f6f88cc48a Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Tue, 31 Mar 2026 11:35:48 -0700 Subject: [PATCH 08/10] Fix linter issues --- .../telemetry/src/test/projectUtils.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/@react-native-windows/telemetry/src/test/projectUtils.test.ts b/packages/@react-native-windows/telemetry/src/test/projectUtils.test.ts index d1a37ab50db..6dc86e05cc1 100644 --- a/packages/@react-native-windows/telemetry/src/test/projectUtils.test.ts +++ b/packages/@react-native-windows/telemetry/src/test/projectUtils.test.ts @@ -74,9 +74,7 @@ test('configToProjectInfo() works with playground project info', async () => { const projectInfo = info as projectUtils.AppProjectInfo; - expect(projectInfo.id).toBe( - projectUtils.getProjectId('playground'), - ); + expect(projectInfo.id).toBe(projectUtils.getProjectId('playground')); expect(projectInfo.platforms).toStrictEqual(['windows']); expect(projectInfo.rnwLang).toBe('cpp'); expect(projectInfo.usesTS).toBe(true); From ecca760c97f057ab331263bca4cd91b7876e09c6 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Tue, 31 Mar 2026 14:04:27 -0700 Subject: [PATCH 09/10] Update packages lock files --- vnext/Desktop.ABITests/packages.lock.json | 52 ++++++++-------- vnext/Desktop.DLL/packages.lock.json | 12 ++-- .../packages.lock.json | 12 ++-- vnext/Desktop.UnitTests/packages.lock.json | 12 ++-- vnext/Desktop/packages.lock.json | 60 +++++++++---------- .../ReactCommon.UnitTests/packages.lock.json | 52 ++++++++-------- .../NuGetRestoreForceEvaluateAllSolutions.ps1 | 26 +++++--- 7 files changed, 117 insertions(+), 109 deletions(-) diff --git a/vnext/Desktop.ABITests/packages.lock.json b/vnext/Desktop.ABITests/packages.lock.json index 8b768819887..93f547e3b57 100644 --- a/vnext/Desktop.ABITests/packages.lock.json +++ b/vnext/Desktop.ABITests/packages.lock.json @@ -45,8 +45,8 @@ }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.Windows.SDK.BuildTools": { "type": "Transitive", @@ -55,10 +55,10 @@ }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, @@ -97,7 +97,7 @@ "FollyWin32": "[1.0.0, )", "Microsoft.JavaScript.Hermes": "[0.0.0-2511.7001-d7ca19b3, )", "Microsoft.SourceLink.GitHub": "[1.1.1, )", - "Microsoft.WindowsAppSDK": "[1.7.250127003-experimental3, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", "ReactCommon": "[1.0.0, )", "ReactNative.V8Jsi.Windows": "[0.71.8, )", "boost": "[1.83.0, )" @@ -124,15 +124,15 @@ "native,Version=v0.0/win": { "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } } @@ -140,15 +140,15 @@ "native,Version=v0.0/win-arm64": { "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } } @@ -156,15 +156,15 @@ "native,Version=v0.0/win-x64": { "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } } @@ -172,15 +172,15 @@ "native,Version=v0.0/win-x86": { "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } } diff --git a/vnext/Desktop.DLL/packages.lock.json b/vnext/Desktop.DLL/packages.lock.json index 0684ef0e6be..b45cddff1ff 100644 --- a/vnext/Desktop.DLL/packages.lock.json +++ b/vnext/Desktop.DLL/packages.lock.json @@ -42,8 +42,8 @@ }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.Windows.SDK.BuildTools": { "type": "Transitive", @@ -52,10 +52,10 @@ }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, @@ -89,7 +89,7 @@ "FollyWin32": "[1.0.0, )", "Microsoft.JavaScript.Hermes": "[0.0.0-2511.7001-d7ca19b3, )", "Microsoft.SourceLink.GitHub": "[1.1.1, )", - "Microsoft.WindowsAppSDK": "[1.7.250127003-experimental3, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", "ReactCommon": "[1.0.0, )", "ReactNative.V8Jsi.Windows": "[0.71.8, )", "boost": "[1.83.0, )" diff --git a/vnext/Desktop.IntegrationTests/packages.lock.json b/vnext/Desktop.IntegrationTests/packages.lock.json index 16de0121f1c..517dffd8caa 100644 --- a/vnext/Desktop.IntegrationTests/packages.lock.json +++ b/vnext/Desktop.IntegrationTests/packages.lock.json @@ -46,8 +46,8 @@ }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.Windows.SDK.BuildTools": { "type": "Transitive", @@ -56,10 +56,10 @@ }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, @@ -98,7 +98,7 @@ "FollyWin32": "[1.0.0, )", "Microsoft.JavaScript.Hermes": "[0.0.0-2511.7001-d7ca19b3, )", "Microsoft.SourceLink.GitHub": "[1.1.1, )", - "Microsoft.WindowsAppSDK": "[1.7.250127003-experimental3, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", "ReactCommon": "[1.0.0, )", "ReactNative.V8Jsi.Windows": "[0.71.8, )", "boost": "[1.83.0, )" diff --git a/vnext/Desktop.UnitTests/packages.lock.json b/vnext/Desktop.UnitTests/packages.lock.json index c676eb8b79a..3271d793e48 100644 --- a/vnext/Desktop.UnitTests/packages.lock.json +++ b/vnext/Desktop.UnitTests/packages.lock.json @@ -46,8 +46,8 @@ }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.Windows.SDK.BuildTools": { "type": "Transitive", @@ -56,10 +56,10 @@ }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, @@ -98,7 +98,7 @@ "FollyWin32": "[1.0.0, )", "Microsoft.JavaScript.Hermes": "[0.0.0-2511.7001-d7ca19b3, )", "Microsoft.SourceLink.GitHub": "[1.1.1, )", - "Microsoft.WindowsAppSDK": "[1.7.250127003-experimental3, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", "ReactCommon": "[1.0.0, )", "ReactNative.V8Jsi.Windows": "[0.71.8, )", "boost": "[1.83.0, )" diff --git a/vnext/Desktop/packages.lock.json b/vnext/Desktop/packages.lock.json index 399b5f8ac80..d9346bc1510 100644 --- a/vnext/Desktop/packages.lock.json +++ b/vnext/Desktop/packages.lock.json @@ -32,11 +32,11 @@ }, "Microsoft.WindowsAppSDK": { "type": "Direct", - "requested": "[1.7.250127003-experimental3, )", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, @@ -58,8 +58,8 @@ }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.Windows.SDK.BuildTools": { "type": "Transitive", @@ -99,69 +99,69 @@ "native,Version=v0.0/win": { "Microsoft.WindowsAppSDK": { "type": "Direct", - "requested": "[1.7.250127003-experimental3, )", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" } }, "native,Version=v0.0/win-arm64": { "Microsoft.WindowsAppSDK": { "type": "Direct", - "requested": "[1.7.250127003-experimental3, )", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" } }, "native,Version=v0.0/win-x64": { "Microsoft.WindowsAppSDK": { "type": "Direct", - "requested": "[1.7.250127003-experimental3, )", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" } }, "native,Version=v0.0/win-x86": { "Microsoft.WindowsAppSDK": { "type": "Direct", - "requested": "[1.7.250127003-experimental3, )", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" } } } diff --git a/vnext/ReactCommon.UnitTests/packages.lock.json b/vnext/ReactCommon.UnitTests/packages.lock.json index 5ab6924f23a..5a861546790 100644 --- a/vnext/ReactCommon.UnitTests/packages.lock.json +++ b/vnext/ReactCommon.UnitTests/packages.lock.json @@ -46,8 +46,8 @@ }, "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.Windows.SDK.BuildTools": { "type": "Transitive", @@ -56,10 +56,10 @@ }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } }, @@ -93,7 +93,7 @@ "FollyWin32": "[1.0.0, )", "Microsoft.JavaScript.Hermes": "[0.0.0-2511.7001-d7ca19b3, )", "Microsoft.SourceLink.GitHub": "[1.1.1, )", - "Microsoft.WindowsAppSDK": "[1.7.250127003-experimental3, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", "ReactCommon": "[1.0.0, )", "ReactNative.V8Jsi.Windows": "[0.71.8, )", "boost": "[1.83.0, )" @@ -110,15 +110,15 @@ "native,Version=v0.0/win": { "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } } @@ -126,15 +126,15 @@ "native,Version=v0.0/win-arm64": { "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } } @@ -142,15 +142,15 @@ "native,Version=v0.0/win-x64": { "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } } @@ -158,15 +158,15 @@ "native,Version=v0.0/win-x86": { "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "1.0.2792.45", - "contentHash": "KOlLJSq70OySfU8mdhWdh9iOyApazWsIb6CmSz+YTJ5MmwLcsCLMW0qemORo7Si3A7VhLDIH3jwpMhPxodfkuA==" + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" }, "Microsoft.WindowsAppSDK": { "type": "Transitive", - "resolved": "1.7.250127003-experimental3", - "contentHash": "oR/J+gLxnx9w9vaSzOUQ8wD7zNtejf4R2x+gS2aPRQAvb12SpMN7zSKJD3bogHPZpA6qbu9w1KouQm0axDyNsQ==", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", "dependencies": { - "Microsoft.Web.WebView2": "1.0.2792.45", + "Microsoft.Web.WebView2": "1.0.2903.40", "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" } } diff --git a/vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 b/vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 index df0adb0f8e3..c339cd2b48e 100644 --- a/vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 +++ b/vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 @@ -1,4 +1,5 @@ param( + [switch] $SkipLockDeletion ) [string] $RepoRoot = Resolve-Path "$PSScriptRoot\..\.." @@ -8,15 +9,20 @@ Set-Location -Path $RepoRoot try { - # Delete existing lock files - $existingLockFiles = (Get-ChildItem -File -Recurse -Path $RepoRoot -Filter *.lock.json) - $existingLockFiles | Foreach-Object { - Write-Host Deleting $_.FullName - Remove-Item $_.FullName + if (-not $SkipLockDeletion) { + # Delete existing lock files + $existingLockFiles = (Get-ChildItem -File -Recurse -Path $RepoRoot -Filter *.lock.json) + $existingLockFiles | Foreach-Object { + Write-Host Deleting $_.FullName + Remove-Item $_.FullName + } } - $packagesSolutions = (Get-ChildItem -File -Recurse -Path $RepoRoot\packages -Filter *.sln )| Where-Object { !$_.FullName.Contains('node_modules') -and !$_.FullName.Contains('e2etest') } - $vnextSolutions = (Get-ChildItem -File -Path $RepoRoot\vnext -Filter *.sln) + # Solutions that fail NuGet restore due to project type incompatibilities (e.g., WAP + native) + $excludedSolutions = @("playground-win32-packaged.sln") + + $packagesSolutions = @(Get-ChildItem -File -Recurse -Path $RepoRoot\packages -Include *.sln,*.slnf) | Where-Object { !$_.FullName.Contains('node_modules') -and !$_.FullName.Contains('e2etest') -and ($excludedSolutions -notcontains $_.Name) } + $vnextSolutions = @(Get-ChildItem -File -Path $RepoRoot\vnext\* -Include *.sln,*.slnf) # Run all solutions with their defaults $($packagesSolutions; $vnextSolutions) | Foreach-Object { @@ -25,7 +31,9 @@ try } # Re-run solutions that build with UseExperimentalWinUI3 - $experimentalSolutions = @("playground-composition.sln", "Microsoft.ReactNative.sln", "Microsoft.ReactNative.NewArch.sln", "ReactWindows-Desktop.sln"); + # Note: ReactWindows-Desktop.sln is NOT included here because ExperimentalFeatures.props + # already sets UseExperimentalWinUI3=false for SolutionName=ReactWindows-Desktop. + $experimentalSolutions = @("playground-composition.sln", "Microsoft.ReactNative.sln", "Microsoft.ReactNative.CppOnly.slnf"); $($packagesSolutions; $vnextSolutions) | Where-Object { $experimentalSolutions -contains $_.Name } | Foreach-Object { Write-Host Restoring $_.FullName with UseExperimentalWinUI3=true & msbuild /t:Restore /p:RestoreForceEvaluate=true /p:UseExperimentalWinUI3=true $_.FullName @@ -41,4 +49,4 @@ try finally { Set-Location -Path "$StartingLocation" -} \ No newline at end of file +} From 5a1c5bb047fcf63507fa7fdb44de1a064bf7ee29 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Tue, 31 Mar 2026 17:16:57 -0700 Subject: [PATCH 10/10] Address Fabric packages.lock issues --- vnext/Mso.UnitTests/packages.lock.json | 92 ++++++++++++++++++- .../NuGetRestoreForceEvaluateAllSolutions.ps1 | 28 +++++- 2 files changed, 114 insertions(+), 6 deletions(-) diff --git a/vnext/Mso.UnitTests/packages.lock.json b/vnext/Mso.UnitTests/packages.lock.json index 9f5f394ce46..5d46582230c 100644 --- a/vnext/Mso.UnitTests/packages.lock.json +++ b/vnext/Mso.UnitTests/packages.lock.json @@ -13,11 +13,95 @@ "requested": "[2.0.230706.1, )", "resolved": "2.0.230706.1", "contentHash": "l0D7oCw/5X+xIKHqZTi62TtV+1qeSz7KVluNFdrJ9hXsst4ghvqQ/Yhura7JqRdZWBXAuDS0G0KwALptdoxweQ==" + }, + "Microsoft.WindowsAppSDK": { + "type": "Direct", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", + "dependencies": { + "Microsoft.Web.WebView2": "1.0.2903.40", + "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" + } + }, + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" + }, + "Microsoft.Windows.SDK.BuildTools": { + "type": "Transitive", + "resolved": "10.0.22621.756", + "contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA==" + } + }, + "native,Version=v0.0/win": { + "Microsoft.WindowsAppSDK": { + "type": "Direct", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", + "dependencies": { + "Microsoft.Web.WebView2": "1.0.2903.40", + "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" + } + }, + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" } }, - "native,Version=v0.0/win": {}, - "native,Version=v0.0/win-arm64": {}, - "native,Version=v0.0/win-x64": {}, - "native,Version=v0.0/win-x86": {} + "native,Version=v0.0/win-arm64": { + "Microsoft.WindowsAppSDK": { + "type": "Direct", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", + "dependencies": { + "Microsoft.Web.WebView2": "1.0.2903.40", + "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" + } + }, + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" + } + }, + "native,Version=v0.0/win-x64": { + "Microsoft.WindowsAppSDK": { + "type": "Direct", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", + "dependencies": { + "Microsoft.Web.WebView2": "1.0.2903.40", + "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" + } + }, + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" + } + }, + "native,Version=v0.0/win-x86": { + "Microsoft.WindowsAppSDK": { + "type": "Direct", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", + "dependencies": { + "Microsoft.Web.WebView2": "1.0.2903.40", + "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" + } + }, + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" + } + } } } \ No newline at end of file diff --git a/vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 b/vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 index c339cd2b48e..8aaf77ba5ea 100644 --- a/vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 +++ b/vnext/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 @@ -31,14 +31,38 @@ try } # Re-run solutions that build with UseExperimentalWinUI3 - # Note: ReactWindows-Desktop.sln is NOT included here because ExperimentalFeatures.props - # already sets UseExperimentalWinUI3=false for SolutionName=ReactWindows-Desktop. + # (sets UseExperimentalWinUI3 which selects the experimental WinUI3 version) $experimentalSolutions = @("playground-composition.sln", "Microsoft.ReactNative.sln", "Microsoft.ReactNative.CppOnly.slnf"); $($packagesSolutions; $vnextSolutions) | Where-Object { $experimentalSolutions -contains $_.Name } | Foreach-Object { Write-Host Restoring $_.FullName with UseExperimentalWinUI3=true & msbuild /t:Restore /p:RestoreForceEvaluate=true /p:UseExperimentalWinUI3=true $_.FullName } + # Re-run Desktop solution with Fabric settings to match CI Fabric Desktop builds. + # The CI enable-fabric-experimental-feature.yml template appends UseFabric=true and + # UseWinUI3=true to ExperimentalFeatures.props. We replicate that here so the lock + # files contain deps for both Fabric and non-Fabric Desktop builds. + $fabricDesktopSolutions = @("ReactWindows-Desktop.sln"); + $propsFile = Join-Path $RepoRoot "vnext\ExperimentalFeatures.props" + $propsBackup = "$propsFile.bak" + Copy-Item $propsFile $propsBackup + try { + # Append Fabric properties — same as enable-fabric-experimental-feature.yml + $content = Get-Content $propsFile -Raw + $fabricProps = " `n true`n true`n `n" + $content = $content -replace '', "$fabricProps" + Set-Content $propsFile -Value $content -NoNewline + + $($packagesSolutions; $vnextSolutions) | Where-Object { $fabricDesktopSolutions -contains $_.Name } | Foreach-Object { + Write-Host "Restoring $($_.FullName) with Fabric via ExperimentalFeatures.props" + & msbuild /t:Restore /p:RestoreForceEvaluate=true $_.FullName + } + } + finally { + # Restore original ExperimentalFeatures.props + Move-Item $propsBackup $propsFile -Force + } + # Re-run solutions that build with Chakra $chakraSolutions = @("ReactUWPTestApp.sln", "integrationtest.sln"); $($packagesSolutions; $vnextSolutions) | Where-Object { $chakraSolutions -contains $_.Name } | Foreach-Object {