diff --git a/.ado/publish.yml b/.ado/publish.yml index 0d00cfa6274..1cf16e3b6ed 100644 --- a/.ado/publish.yml +++ b/.ado/publish.yml @@ -1,10 +1,6 @@ name: 0.0.$(Date:yyMM.d)$(Rev:rrr) parameters: -- name: performBeachballCheck - displayName: Perform Beachball Check (Disable when promoting) - type: boolean - default: true - name: AgentPool type: object default: @@ -49,23 +45,10 @@ parameters: - Name: Arm64ReleaseFabric BuildConfiguration: Release BuildPlatform: ARM64 - - Name: X64DebugFabric - BuildConfiguration: Debug - BuildPlatform: x64 - - Name: X86DebugFabric - BuildConfiguration: Debug - BuildPlatform: x86 - - Name: Arm64DebugFabric - BuildConfiguration: Debug - BuildPlatform: ARM64 variables: - template: variables/windows.yml - group: RNW Secrets - - name: FailCGOnAlert - value: false - - name: EnableCodesign - value: true trigger: none pr: none @@ -80,54 +63,50 @@ extends: template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates parameters: pool: ${{ parameters.AgentPool.Medium }} - customBuildTags: - - ES365AIMigrationTooling + 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: - - job: RnwPublishPrep - displayName: React-Native-Windows Publish Prep + # Set version variables + - job: SetVersionVars + displayName: Set Version Variables pool: ${{ parameters.AgentPool.Medium }} - timeoutInMinutes: 120 - cancelTimeoutInMinutes: 5 + timeoutInMinutes: 15 steps: - - template: .ado/templates/checkout-full.yml@self + - template: .ado/templates/checkout-shallow.yml@self + + - template: .ado/templates/set-version-vars.yml@self parameters: - persistCredentials: false + buildEnvironment: Continuous - - powershell: gci env:/BUILD_* - displayName: Show build information + # 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 - - template: .ado/templates/prepare-js-env.yml@self + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish version variables' + targetPath: $(Build.StagingDirectory)/versionEnvVars + artifactName: VersionEnvVars - - template: .ado/templates/run-compliance-prebuild.yml@self - - - script: if not exist %USERPROFILE%\AppData\Roaming\npm (mkdir %USERPROFILE%\AppData\Roaming\npm) - displayName: Fix missing npm config - - - pwsh: | - npx beachball check --verbose 2>&1 | Tee-Object -Variable beachballOutput - $beachballErrors = $beachballOutput | Where-Object { $_ -match "ERROR: *"} - $beachballErrors | ForEach { Write-Host "##vso[task.logissue type=error]$_" } - if ( $beachballErrors.Count -gt 0) { throw "Beachball check found $($beachballErrors.Count) errors." } - displayName: Beachball Check - condition: ${{ parameters.performBeachballCheck }} - - - job: RnwNpmPublish - displayName: React-Native-Windows Npm Pack - dependsOn: RnwPublishPrep - pool: - name: Azure-Pipelines-1ESPT-ExDShared - image: windows-latest - os: windows - timeoutInMinutes: 120 + # 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 @@ -138,21 +117,6 @@ extends: - script: dir /s "$(Pipeline.Workspace)\published-packages" displayName: Show created npm packages - - template: .ado/templates/set-version-vars.yml@self - parameters: - buildEnvironment: Continuous - - - script: echo NpmDistTag is $(NpmDistTag) - displayName: Show NPM dist tag - - - script: copy ".ado\scripts\npmPack.js" "$(Build.StagingDirectory)\versionEnvVars\npmPack.js" - displayName: Include npmPack.js in VersionEnvVars artifact - - - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 📒 Generate Manifest Npm - inputs: - BuildDropPath: $(System.DefaultWorkingDirectory) - templateContext: outputs: - output: pipelineArtifact @@ -160,23 +124,23 @@ extends: condition: succeededOrFailed() targetPath: $(Pipeline.Workspace)/published-packages artifactName: NpmPackedTarballs - - output: pipelineArtifact - displayName: "📒 Publish Manifest Npm" - artifactName: SBom-$(System.JobAttempt) - targetPath: $(System.DefaultWorkingDirectory)/_manifest - sbomEnabled: false # This output is in fact an SBOM itself - - output: pipelineArtifact - displayName: 'Publish version variables' - targetPath: $(Build.StagingDirectory)/versionEnvVars - artifactName: VersionEnvVars + # 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: RnwNpmPublish + 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 @@ -190,10 +154,11 @@ extends: - template: .ado/templates/msbuild-sln.yml@self parameters: solutionDir: vnext - solutionName: ReactWindows-Desktop.sln + solutionName: ReactWindows-Desktop.Publish.slnf 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: @@ -202,14 +167,20 @@ extends: buildPlatform: ${{ matrix.BuildPlatform }} buildConfiguration: ${{ matrix.BuildConfiguration }} contents: | - React.Windows.Desktop\** - React.Windows.Desktop.DLL\** - React.Windows.Desktop.Test.DLL\** + React.Windows.Desktop\Microsoft.ReactNative.winmd + React.Windows.Desktop.DLL\react-native-win32.* - - template: .ado/templates/component-governance.yml@self + - template: .ado/templates/esrp-codesign-binaries.yml@self + parameters: + displayName: 'CodeSign Desktop Binaries' + 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: @@ -228,13 +199,16 @@ extends: 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: RnwNpmPublish + 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 @@ -248,10 +222,11 @@ extends: - template: .ado/templates/msbuild-sln.yml@self parameters: solutionDir: vnext - solutionName: Microsoft.ReactNative.NewArch.sln + solutionName: Microsoft.ReactNative.NewArch.Publish.slnf 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 @@ -266,13 +241,22 @@ extends: buildPlatform: ${{ matrix.BuildPlatform }} buildConfiguration: ${{ matrix.BuildConfiguration }} contents: | - Microsoft.ReactNative\** - Microsoft.ReactNative.CsWinRT\** + Microsoft.ReactNative\Microsoft.ReactNative.* + Microsoft.ReactNative.CsWinRT\Microsoft.ReactNative.Projection.* - - template: .ado/templates/component-governance.yml@self + - template: .ado/templates/esrp-codesign-binaries.yml@self + parameters: + displayName: 'CodeSign Microsoft.ReactNative Binaries' + 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: @@ -291,16 +275,18 @@ extends: artifactName: ReactWindows.${{ matrix.BuildPlatform }}.${{ matrix.BuildConfiguration }} targetPath: $(Build.StagingDirectory)/NuGet/ReactWindows/${{ matrix.BuildPlatform }}/${{ matrix.BuildConfiguration }} + # Create Nuget packages - job: RNWNuget + displayName: Pack NuGet dependsOn: - - RnwNpmPublish + - RnwNpmPack + - Linting - ${{ each matrix in parameters.desktopBuildMatrix }}: - RnwNativeBuildDesktop${{ matrix.Name }} - ${{ each matrix in parameters.universalBuildMatrix }}: - RnwNativeBuildUniversal${{ matrix.Name }} - displayName: Sign Binaries and Publish NuGet pool: ${{ parameters.AgentPool.Medium }} - timeoutInMinutes: 120 # Protect against the long CodeSign task + timeoutInMinutes: 60 # Protect against the long CodeSign task steps: - template: .ado/templates/checkout-shallow.yml@self @@ -309,7 +295,7 @@ extends: - 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) + # 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" @@ -321,8 +307,6 @@ extends: npmVersion: $(npmVersion) packMicrosoftReactNative: true packMicrosoftReactNativeCxx: true - ${{ if or(eq(variables['EnableCodesign'], 'true'), endsWith(variables['Build.SourceBranchName'], '-stable')) }}: # Sign if EnableCodeSign or on *-stable release builds - signMicrosoft: true slices: - platform: x64 configuration: Release @@ -337,8 +321,6 @@ extends: publishCommitId: $(publishCommitId) npmVersion: $(npmVersion) packDesktop: true - ${{ if or(eq(variables['EnableCodesign'], 'true'), endsWith(variables['Build.SourceBranchName'], '-stable')) }}: # Sign if EnableCodeSign or on *-stable release builds - signMicrosoft: true slices: - platform: x64 configuration: Release @@ -353,24 +335,11 @@ extends: - platform: ARM64EC configuration: Debug - # Symbol Publishing for Work Item 59264834 - MSRC Compliance - # continueOnError: Duplicate symbols are expected when the pipeline - # is re-run for the same version. The symbols already exist on the - # server, so it is safe to continue. - - task: PublishSymbols@2 - displayName: 'Publish Symbols to Microsoft Symbol Server' - continueOnError: true - inputs: - UseNetCoreClientTool: true - ConnectedServiceName: Office-React-Native-Windows-Bot - SymbolsFolder: '$(System.DefaultWorkingDirectory)\NugetRoot' - SearchPattern: '**/*.pdb' - SymbolServerType: 'TeamServices' - SymbolsProduct: 'ReactNativeWindows' - SymbolsVersion: '$(Build.BuildNumber)' - SymbolsArtifactName: 'ReactNativeWindows-Symbols-$(Build.BuildId)' - DetailedLog: true - TreatNotIndexedAsWarning: false + - template: .ado/templates/esrp-codesign-nuget.yml@self + parameters: + displayName: 'CodeSign all NuGet packages' + folderPath: $(System.DefaultWorkingDirectory)/NugetRootFinal + pattern: '**/*.nupkg' templateContext: sdl: diff --git a/.ado/release.yml b/.ado/release.yml index d8a20a99e4c..4bd8ffe7f58 100644 --- a/.ado/release.yml +++ b/.ado/release.yml @@ -3,7 +3,10 @@ # It releases npm packages to npmjs.com and NuGet packages to the public # ms/react-native and ms/react-native-public ADO feeds and to nuget.org. # -# The triggers are overridden by the ADO pipeline UI definition. +# 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 NuGet Release $(Date:yyyyMMdd).$(Rev:r) @@ -16,7 +19,15 @@ resources: - pipeline: 'Publish' project: 'ReactNative' source: 'Publish' - trigger: none + trigger: + branches: + include: + - main + - '0.74-stable' + - '0.81-stable' + - '0.82-stable' + - '0.83-stable' + - '0.84-stable' repositories: - repository: 1ESPipelineTemplates type: git @@ -30,14 +41,110 @@ extends: name: Azure-Pipelines-1ESPT-ExDShared image: windows-latest os: windows - customBuildTags: - - ES365AIMigrationTooling-Release 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 + + - 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) + displayName: Log all pipeline variables + + - powershell: | + $buildReason = $env:BUILD_REASON + # Use only the first line of the commit message + $sourceMessage = ($env:SOURCE_MESSAGE -split "`n")[0].Trim() + $publishRunName = $env:PUBLISH_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 NuGet 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 ($publishRunName) { + $buildNumber = "$publishRunName ($sourceBranch) - $dateStamp" + } else { + $buildNumber = "Release ($sourceBranch) - $dateStamp" + } + } + elseif ($sourceMessage.StartsWith("RELEASE:")) { + $shouldRelease = $true + $buildNumber = "$publishRunName ($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) + PUBLISH_RUN_NAME: $(resources.pipeline.Publish.runName) + SOURCE_BRANCH: $(resources.pipeline.Publish.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 - # Allow manual runs unconditionally; for build-completion triggers, - # only proceed if the commit message starts with 'RELEASE:'. - condition: or(eq(variables['Build.Reason'], 'Manual'), startsWith(variables['Build.SourceVersionMessage'], 'RELEASE:')) + dependsOn: Gate + condition: eq(dependencies.Gate.outputs['Evaluate.gate.shouldRelease'], 'True') jobs: - job: PushNpm displayName: npmjs.com - Publish npm packages @@ -73,7 +180,7 @@ extends: 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: 'SFP.release-tasks.custom-build-release-task.EsrpRelease@10' + - task: 'EsrpRelease@11' displayName: 'ESRP Release to npmjs.com' condition: and(succeeded(), ne(variables['NpmDistTag'], ''), eq(variables['HasPackagesToPublish'], 'true')) inputs: @@ -158,3 +265,62 @@ extends: - 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: 'Publish' + artifactName: 'ReactWindows-final-nuget' + targetPath: '$(Pipeline.Workspace)/ReactWindows-final-nuget' + steps: + - powershell: | + # 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 diff --git a/.ado/templates/checkout-shallow.yml b/.ado/templates/checkout-shallow.yml index 21460b9c88d..20c685f9395 100644 --- a/.ado/templates/checkout-shallow.yml +++ b/.ado/templates/checkout-shallow.yml @@ -2,7 +2,7 @@ # without full history. steps: - checkout: self - fetchDepth: 10 # Buffer to avoid race condition with AZP jobs started against merge branch + fetchDepth: 1 clean: false submodules: false lfs: false diff --git a/.ado/templates/esrp-codesign-binaries.yml b/.ado/templates/esrp-codesign-binaries.yml new file mode 100644 index 00000000000..9c8c03adcf5 --- /dev/null +++ b/.ado/templates/esrp-codesign-binaries.yml @@ -0,0 +1,45 @@ +parameters: + - name: displayName + type: string + - name: folderPath + type: string + - name: pattern + type: string + +steps: + - task: EsrpCodeSigning@6 + displayName: ${{ parameters.displayName }} + inputs: + ConnectedServiceName: 'ESRP-CodeSigning-OGX-JSHost-RNW' + AppRegistrationClientId: '0a35e01f-eadf-420a-a2bf-def002ba898d' + AppRegistrationTenantId: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' + AuthAKVName: 'OGX-JSHost-KV' + AuthCertName: 'OGX-JSHost-Auth4' + AuthSignCertName: 'OGX-JSHost-Sign3' + FolderPath: ${{ parameters.folderPath }} + Pattern: ${{ parameters.pattern }} + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode" : "CP-230012", + "OperationCode" : "SigntoolSign", + "Parameters" : { + "OpusName" : "Microsoft", + "OpusInfo" : "http://www.microsoft.com", + "FileDigest" : "/fd \"SHA256\"", + "PageHash" : "/PH", + "TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + }, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-230012", + "OperationCode" : "SigntoolVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] diff --git a/.ado/templates/esrp-codesign-nuget.yml b/.ado/templates/esrp-codesign-nuget.yml new file mode 100644 index 00000000000..3666061449f --- /dev/null +++ b/.ado/templates/esrp-codesign-nuget.yml @@ -0,0 +1,39 @@ +parameters: + - name: displayName + type: string + - name: folderPath + type: string + - name: pattern + type: string + +steps: + - task: EsrpCodeSigning@6 + displayName: ${{ parameters.displayName }} + inputs: + ConnectedServiceName: 'ESRP-CodeSigning-OGX-JSHost-RNW' + AppRegistrationClientId: '0a35e01f-eadf-420a-a2bf-def002ba898d' + AppRegistrationTenantId: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' + AuthAKVName: 'OGX-JSHost-KV' + AuthCertName: 'OGX-JSHost-Auth4' + AuthSignCertName: 'OGX-JSHost-Sign3' + FolderPath: ${{ parameters.folderPath }} + Pattern: ${{ parameters.pattern }} + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode" : "CP-401405", + "OperationCode" : "NuGetSign", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-401405", + "OperationCode" : "NuGetVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] diff --git a/.ado/templates/prep-and-pack-nuget.yml b/.ado/templates/prep-and-pack-nuget.yml index b3628fe82f5..6913307076e 100644 --- a/.ado/templates/prep-and-pack-nuget.yml +++ b/.ado/templates/prep-and-pack-nuget.yml @@ -29,9 +29,6 @@ parameters: type: boolean default: false - - name: signMicrosoft - type: boolean - default: false steps: - pwsh: | @@ -99,8 +96,6 @@ steps: outputPackage: Microsoft.ReactNative slices: $(releaseSlices) packageVersion: ${{parameters.npmVersion}} - codesignBinaries: ${{ parameters.signMicrosoft }} - codesignNuget: ${{ parameters.signMicrosoft }} buildProperties: CommitId=${{parameters.publishCommitId}};nugetroot=${{parameters.nugetroot}};baseconfiguration=Release;baseplatform=$(releaseBasePlatform) @@ -110,5 +105,4 @@ steps: outputPackage: Microsoft.ReactNative.Cxx packageVersion: ${{parameters.npmVersion}} buildProperties: CommitId=${{parameters.publishCommitId}};nugetroot=${{parameters.nugetroot}};baseconfiguration=$(baseConfiguration);baseplatform=$(basePlatform) - codesignNuget: ${{ parameters.signMicrosoft }} diff --git a/.ado/templates/prep-and-pack-single.yml b/.ado/templates/prep-and-pack-single.yml index e07757bdbfd..cdc7d7f4081 100644 --- a/.ado/templates/prep-and-pack-single.yml +++ b/.ado/templates/prep-and-pack-single.yml @@ -2,7 +2,7 @@ parameters: # Required: Name to publish the NuGet Package As - name: outputPackage type: string - + # Required: NPM-matching version - name: packageVersion type: string @@ -12,33 +12,17 @@ parameters: type: string default: '' - # Optional: Pattern of binaries within the artifact to sign as part of this - # NuGet package. Defaults to .dll, .winmd, .exe matching the nuspec name - - name: binariesToSign - type: string - default: '' - # Optional: Excludes platform-specific files from the NuSpec of they are not # included in slices - name: slices type: string default: '' - # Optional: Properties to pass to nuspec + # Optional: Properties to pass to nuspec - name: buildProperties type: string default: '' - # Optional: Whether to sign binaries - - name: codesignBinaries - type: boolean - default: false - - # Optional: Whether to sign the NuGet packag - - name: codesignNuget - type: boolean - default: false - steps: - powershell: gci $(System.DefaultWorkingDirectory)/NugetRoot @@ -54,50 +38,8 @@ steps: displayName: '${{ parameters.outputPackage }} - Strip slices from nuspec' workingDirectory: $(System.DefaultWorkingDirectory)/NugetRoot - - ${{ if eq(parameters.codesignBinaries, true) }}: - - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5 - displayName: '${{ parameters.outputPackage }} CodeSign Binaries' - inputs: - ConnectedServiceName: 'ESRP-CodeSigning-OGX-JSHost-RNW' - AppRegistrationClientId: '0a35e01f-eadf-420a-a2bf-def002ba898d' - AppRegistrationTenantId: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' - AuthAKVName: 'OGX-JSHost-KV' - AuthCertName: 'OGX-JSHost-Auth4' - AuthSignCertName: 'OGX-JSHost-Sign3' - FolderPath: $(System.DefaultWorkingDirectory)/NugetRoot - # Recursively finds files matching these patterns: - ${{ if ne(parameters.binariesToSign, '') }}: - Pattern: ${{ parameters.binariesToSign }} - ${{ else }}: - Pattern: | - **/${{ coalesce(parameters.nuspec, parameters.outputPackage) }}.dll - **/${{ coalesce(parameters.nuspec, parameters.outputPackage) }}.winmd - **/${{ coalesce(parameters.nuspec, parameters.outputPackage) }}.exe - UseMinimatch: true - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "KeyCode" : "CP-230012", - "OperationCode" : "SigntoolSign", - "Parameters" : { - "OpusName" : "Microsoft", - "OpusInfo" : "http://www.microsoft.com", - "FileDigest" : "/fd \"SHA256\"", - "PageHash" : "/PH", - "TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - }, - "ToolName" : "sign", - "ToolVersion" : "1.0" - }, - { - "KeyCode" : "CP-230012", - "OperationCode" : "SigntoolVerify", - "Parameters" : {}, - "ToolName" : "sign", - "ToolVersion" : "1.0" - } - ] + # Binary signing is done in build jobs (ESRP CodeSign before artifact upload) + # NuGet signing is done in batch in publish.yml (single ESRP call for all .nupkg) # NuGetCommand@2 workaround: https://developercommunity.visualstudio.com/content/problem/288534/vsts-yaml-build-failure-the-task-name-nugetcommand.html - task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 @@ -109,39 +51,6 @@ steps: packDestination: $(System.DefaultWorkingDirectory)/NugetRootFinal buildProperties: version=${{ parameters.packageVersion }};id=${{ parameters.outputPackage }};${{ parameters.buildProperties }} - - ${{ if eq(parameters.codesignNuget, true) }}: - - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5 - displayName: '${{ parameters.outputPackage }} CodeSign NuGet' - inputs: - ConnectedServiceName: 'ESRP-CodeSigning-OGX-JSHost-RNW' - AppRegistrationClientId: '0a35e01f-eadf-420a-a2bf-def002ba898d' - AppRegistrationTenantId: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' - AuthAKVName: 'OGX-JSHost-KV' - AuthCertName: 'OGX-JSHost-Auth4' - AuthSignCertName: 'OGX-JSHost-Sign3' - FolderPath: $(System.DefaultWorkingDirectory)/NugetRootFinal - Pattern: | - **/${{ parameters.outputPackage }}.${{ parameters.packageVersion }}.nupkg - UseMinimatch: true - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "KeyCode" : "CP-401405", - "OperationCode" : "NuGetSign", - "Parameters" : {}, - "ToolName" : "sign", - "ToolVersion" : "1.0" - }, - { - "KeyCode" : "CP-401405", - "OperationCode" : "NuGetVerify", - "Parameters" : {}, - "ToolName" : "sign", - "ToolVersion" : "1.0" - } - ] - - powershell: gci $(System.DefaultWorkingDirectory)/NugetRootFinal displayName: List files in NugetRootFinal diff --git a/.gitignore b/.gitignore index 94a413d154c..8724fe25a55 100644 --- a/.gitignore +++ b/.gitignore @@ -196,3 +196,4 @@ nul .store*/* /npm-pkgs +/.claude diff --git a/README.md b/README.md index fca6bff31ad..ba73b3047b8 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ React Native has [great documentation](https://reactnative.dev/docs/getting-star - Check the [samples repo](https://github.com/microsoft/react-native-windows-samples) for more standalone samples. - The [React Native Gallery](https://github.com/microsoft/react-native-gallery) app demonstrates various components in an interactive way. - Check out the [React Native Developer Blog](https://devblogs.microsoft.com/react-native/) to see examples from past conference talks, blog posts, and more. -- For more sample code browse the [RNTester folder](https://github.com/microsoft/react-native-windows/tree/main/packages/e2e-test-app-fabric/windows/RNTesterApp) in the GitHub web UI. +- For more sample code browse the [RNTester folder](https://github.com/microsoft/react-native-windows/tree/main/packages/e2e-test-app-fabric/windows/RNTesterApp-Fabric) in the GitHub web UI. ## 📢 Contributing See [Contributing guidelines](https://github.com/microsoft/react-native-windows/blob/main/CONTRIBUTING.md) for how to setup your fork of the repo and start a PR to contribute to React Native for Windows. diff --git a/change/react-native-windows-959c3f60-0f33-4ac8-a081-dc6452e2d455.json b/change/react-native-windows-959c3f60-0f33-4ac8-a081-dc6452e2d455.json new file mode 100644 index 00000000000..9b547c58d34 --- /dev/null +++ b/change/react-native-windows-959c3f60-0f33-4ac8-a081-dc6452e2d455.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Speed up the publish pipeline", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/docs/managedCodeGen.md b/docs/managedCodeGen.md index 2f33659fbc9..52023ba6611 100644 --- a/docs/managedCodeGen.md +++ b/docs/managedCodeGen.md @@ -27,7 +27,7 @@ When building the apps that are checked in to our repo for testing, we have to r ## Turning on/off Currently the feature is behind an MSBuild property `$(ReactNativeCodeGenEnabled)`. -The default at the moment is false, it is only turned on for a single project for now which is the [SampleLibraryCS.csproj](https://github.com/microsoft/react-native-windows/blob/main/packages/sample-apps/windows/SampleLibraryCS/SampleLibraryCS.csproj) project, to prove it is stable. We will slowly enable it for all projects in the repo and then make it the default. +The default at the moment is false, it is only turned on for a single project for now to prove it is stable. We will slowly enable it for all projects in the repo and then make it the default. ## MSBuild/NuGet Complications MSBuild and NuGet spent a long time fighting me in mixing a NetCoreApp3.1 executable and WinRT apps in the same solution and the same build. ProjectReferences cannot be used so I had to use the `` task directly in the targets and it was tricky making it build from both the customer apps as well as our main build solution and unittest (Microsoft.ReactNative.sln). In the end there are a few hacks in place to make this work. diff --git a/packages/@rnw-scripts/just-task/nuget-restore-task.js b/packages/@rnw-scripts/just-task/nuget-restore-task.js index 0273d7816b7..0e2e66546cb 100644 --- a/packages/@rnw-scripts/just-task/nuget-restore-task.js +++ b/packages/@rnw-scripts/just-task/nuget-restore-task.js @@ -26,6 +26,11 @@ function executeNuGetRestore(config) { return; } + if (process.env.TF_BUILD) { + console.log('Skipping NuGet restore in CI (MSBuild handles restore)'); + return; + } + if (!fs.existsSync(config.scriptPath)) { console.warn(`NuGet restore script not found: ${config.scriptPath}`); return; diff --git a/vnext/Microsoft.ReactNative.NewArch.Publish.slnf b/vnext/Microsoft.ReactNative.NewArch.Publish.slnf new file mode 100644 index 00000000000..39839fab846 --- /dev/null +++ b/vnext/Microsoft.ReactNative.NewArch.Publish.slnf @@ -0,0 +1,13 @@ +{ + "solution": { + "path": "Microsoft.ReactNative.NewArch.sln", + "projects": [ + "Common\\Common.vcxproj", + "Folly\\Folly.vcxproj", + "fmt\\fmt.vcxproj", + "Microsoft.ReactNative\\Microsoft.ReactNative.vcxproj", + "Microsoft.ReactNative.CsWinRT\\Microsoft.ReactNative.CsWinRT.csproj", + "ReactCommon\\ReactCommon.vcxproj" + ] + } +} diff --git a/vnext/PropertySheets/CIBuildOptimizations.props b/vnext/PropertySheets/CIBuildOptimizations.props new file mode 100644 index 00000000000..61d0244f890 --- /dev/null +++ b/vnext/PropertySheets/CIBuildOptimizations.props @@ -0,0 +1,29 @@ + + + + + false + false + false + + + + false + false + %(AdditionalOptions) /MP + + + diff --git a/vnext/ReactWindows-Desktop.Publish.slnf b/vnext/ReactWindows-Desktop.Publish.slnf new file mode 100644 index 00000000000..0261a90d017 --- /dev/null +++ b/vnext/ReactWindows-Desktop.Publish.slnf @@ -0,0 +1,14 @@ +{ + "solution": { + "path": "ReactWindows-Desktop.sln", + "projects": [ + "Common\\Common.vcxproj", + "Desktop\\React.Windows.Desktop.vcxproj", + "Desktop.DLL\\React.Windows.Desktop.DLL.vcxproj", + "Folly\\Folly.vcxproj", + "FollyWin32\\FollyWin32.vcxproj", + "ReactCommon\\ReactCommon.vcxproj", + "fmt\\fmt.vcxproj" + ] + } +} diff --git a/vnext/Scripts/OfficeReact.Win32.nuspec b/vnext/Scripts/OfficeReact.Win32.nuspec index a93e7d7f83c..4d53f228dbf 100644 --- a/vnext/Scripts/OfficeReact.Win32.nuspec +++ b/vnext/Scripts/OfficeReact.Win32.nuspec @@ -28,11 +28,6 @@ - - - - - @@ -59,12 +54,6 @@ - - - - - -