diff --git a/.github/DEVELOPMENT.md b/.github/DEVELOPMENT.md index ad114e16d37c..d4f2a618f03a 100644 --- a/.github/DEVELOPMENT.md +++ b/.github/DEVELOPMENT.md @@ -59,9 +59,13 @@ Before opening the solution in Visual Studio / VS Code you **MUST** build the bu *NOTE*: IntelliSense takes a decent amount of time to fully process your solution. It will eventually work through all the necessary tasks. If you are having IntelliSense issues, usually unloading/reloading the `maui.core` and `maui.controls` projects will resolve. ## What branch should I use? -- main -Always use main no matter what you are working on or where you are hoping your change will get applied. We make sure that main always works against the current stable releases of Visual Studio and the .NET MAUI SDK. Even if you are working on features that will only be released with a future version of .NET. `main` is the only relevant branch for current development. +As a general rule: +- [main](https://github.com/dotnet/maui/tree/main) + +Use ‘main’ for bug fixes that don’t require API changes. For new features and changes to public APIs, you must use the branch of the next .NET version. + +- [net9.0](https://github.com/dotnet/maui/tree/net9.0) ## Repository projects @@ -116,8 +120,10 @@ These are tests used for exercising the UI through accessibility layers to simul ``` ├── Controls +│ ├── samples +│ │ ├── Controls.Sample.UITests │ ├── tests -│ │ ├── UITests +│ │ ├── Controls.AppiumTests ``` ### Unit Test Projects @@ -146,6 +152,8 @@ These tests can be ran using the test explorer in VS, or from command line with dotnet test src/TestUtils/src/Microsoft.Maui.IntegrationTests --logger "console;verbosity=diagnostic" --filter "Name=Build\(%22maui%22,%22net7.0%22,%22Debug%22,False\)" ``` +You can find detailed information about testing in the [Wiki](https://github.com/dotnet/maui/wiki/Testing). + ### Additional Cake Commands #### Clean diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 172a757d1d3c..4ac562325168 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -45,6 +45,7 @@ body: description: In what version do you see this issue? Run `dotnet workload list` to find your version. options: - + - 9.0.0-preview.1.9973 - 8.0.7 SR2 - 8.0.6 SR1 - 8.0.3 GA @@ -79,7 +80,7 @@ body: id: version-that-worked attributes: label: Last version that worked well - description: If you answered yes, there a version on which this _did_ work, which one? If no or unknown, please select `Unknown/Other`. Run `dotnet workload list` to find your version. + description: If you answered yes, is there a version on which this _did_ work, which one? If no or unknown, please select `Unknown/Other`. Run `dotnet workload list` to find your version. options: - - Unknown/Other @@ -107,6 +108,7 @@ body: - 8.0.3 GA - 8.0.6 SR1 - 8.0.7 SR2 + - 9.0.0-preview.1.9973 validations: required: true - type: dropdown diff --git a/eng/Versions.targets b/eng/Versions.targets index 2419b505db60..b6fbc83806b7 100644 --- a/eng/Versions.targets +++ b/eng/Versions.targets @@ -57,12 +57,12 @@ -$(GitSemVerLabel) - + - + diff --git a/eng/automation/guardian/CredScanSuppressions.json b/eng/automation/guardian/CredScanSuppressions.json deleted file mode 100644 index 3d66276257ba..000000000000 --- a/eng/automation/guardian/CredScanSuppressions.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "tool": "Credential Scanner", - "suppressions": [ - { - "file": "\\Xamarin.Forms.ControlGallery.WindowsUniversal\\Xamarin.Forms.ControlGallery.WindowsUniversal_TemporaryKey.pfx", - "_justification": "Dummy pfx file used for testing." - }, - { - "file": "\\debug.keystore", - "_justification": "Dummy debug store file used for testing." - } - ] -} \ No newline at end of file diff --git a/eng/automation/guardian/PoliCheck.Exclusions.xml b/eng/automation/guardian/PoliCheck.Exclusions.xml deleted file mode 100644 index dd494420606a..000000000000 --- a/eng/automation/guardian/PoliCheck.Exclusions.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - SAMPLES|CONTROLGALLERY|PUBLICAPI - - - - - - - \ No newline at end of file diff --git a/eng/automation/guardian/source.gdnsuppress b/eng/automation/guardian/source.gdnsuppress index 7506141a6d67..f062f2b243b5 100644 --- a/eng/automation/guardian/source.gdnsuppress +++ b/eng/automation/guardian/source.gdnsuppress @@ -152,6 +152,14 @@ "default" ], "createdDate": "2023-12-19 01:00:51Z" + }, + "db932a43593049dd3d581d65ef9043ce4a5cc9f6970942c61f7ff29a8395ab5a": { + "signature": "db932a43593049dd3d581d65ef9043ce4a5cc9f6970942c61f7ff29a8395ab5a", + "alternativeSignatures": [], + "memberOf": [ + "default" + ], + "createdDate": "2024-02-27 23:34:18Z" } } } \ No newline at end of file diff --git a/eng/common/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1 index 6db6baac5c09..6a05966d57ce 100644 --- a/eng/common/SetupNugetSources.ps1 +++ b/eng/common/SetupNugetSources.ps1 @@ -25,7 +25,7 @@ [CmdletBinding()] param ( [Parameter(Mandatory = $true)][string]$ConfigFile, - [Parameter(Mandatory = $true)][string]$Password + [Parameter(Mandatory = $true)][SecureString]$Password ) $ErrorActionPreference = "Stop" @@ -35,7 +35,7 @@ Set-StrictMode -Version 2.0 . $PSScriptRoot\tools.ps1 # Add source entry to PackageSources -function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Username, $Password) { +function AddPackageSource($sources, $SourceName, $SourceEndPoint, [SecureString] $creds, $Username, [SecureString] $Password) { $packageSource = $sources.SelectSingleNode("add[@key='$SourceName']") if ($packageSource -eq $null) @@ -53,7 +53,7 @@ function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Usern } # Add a credential node for the specified source -function AddCredential($creds, $source, $username, $password) { +function AddCredential([SecureString] $creds, $source, $username, [SecureString] $password) { # Looks for credential configuration for the given SourceName. Create it if none is found. $sourceElement = $creds.SelectSingleNode($Source) if ($sourceElement -eq $null) @@ -85,7 +85,7 @@ function AddCredential($creds, $source, $username, $password) { $passwordElement.SetAttribute("value", $Password) } -function InsertMaestroPrivateFeedCredentials($Sources, $Creds, $Username, $Password) { +function InsertMaestroPrivateFeedCredentials($Sources, [SecureString] $Creds, $Username, [SecureString] $Password) { $maestroPrivateSources = $Sources.SelectNodes("add[contains(@key,'darc-int')]") Write-Host "Inserting credentials for $($maestroPrivateSources.Count) Maestro's private feeds." @@ -164,4 +164,4 @@ foreach ($dotnetVersion in $dotnetVersions) { } } -$doc.Save($filename) \ No newline at end of file +$doc.Save($filename) diff --git a/eng/common/pipeline-logging-functions.sh b/eng/common/pipeline-logging-functions.sh old mode 100644 new mode 100755 diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index aa74ab4a81e7..269fdb9420da 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -65,6 +65,9 @@ $ErrorActionPreference = 'Stop' # Base-64 encoded SAS token that has permission to storage container described by $runtimeSourceFeed [string]$runtimeSourceFeedKey = if (Test-Path variable:runtimeSourceFeedKey) { $runtimeSourceFeedKey } else { $null } +# True if the build is a product build +[bool]$productBuild = if (Test-Path variable:productBuild) { $productBuild } else { $false } + function Create-Directory ([string[]] $path) { New-Item -Path $path -Force -ItemType 'Directory' | Out-Null } @@ -158,18 +161,13 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { $env:DOTNET_MULTILEVEL_LOOKUP=0 # Disable first run since we do not need all ASP.NET packages restored. - $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 + $env:DOTNET_NOLOGO=1 # Disable telemetry on CI. if ($ci) { $env:DOTNET_CLI_TELEMETRY_OPTOUT=1 } - # Source Build uses DotNetCoreSdkDir variable - if ($env:DotNetCoreSdkDir -ne $null) { - $env:DOTNET_INSTALL_DIR = $env:DotNetCoreSdkDir - } - # Find the first path on %PATH% that contains the dotnet.exe if ($useInstalledDotNetCli -and (-not $globalJsonHasRuntimes) -and ($env:DOTNET_INSTALL_DIR -eq $null)) { $dotnetExecutable = GetExecutableFileName 'dotnet' @@ -228,7 +226,7 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { Write-PipelinePrependPath -Path $dotnetRoot Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0' - Write-PipelineSetVariable -Name 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' -Value '1' + Write-PipelineSetVariable -Name 'DOTNET_NOLOGO' -Value '1' return $global:_DotNetInstallDir = $dotnetRoot } @@ -379,13 +377,13 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = } # Minimum VS version to require. - $vsMinVersionReqdStr = '17.6' + $vsMinVersionReqdStr = '17.7' $vsMinVersionReqd = [Version]::new($vsMinVersionReqdStr) # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/RoslynTools.MSBuild/versions/17.6.0-2 - $defaultXCopyMSBuildVersion = '17.6.0-2' + # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/Microsoft.DotNet.Arcade.MSBuild.Xcopy/versions/17.8.5 + $defaultXCopyMSBuildVersion = '17.8.5' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { @@ -450,7 +448,7 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = if ($xcopyMSBuildVersion.Trim() -ine "none") { $vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install if ($vsInstallDir -eq $null) { - throw "Could not xcopy msbuild. Please check that package 'RoslynTools.MSBuild @ $xcopyMSBuildVersion' exists on feed 'dotnet-eng'." + throw "Could not xcopy msbuild. Please check that package 'Microsoft.DotNet.Arcade.MSBuild.Xcopy @ $xcopyMSBuildVersion' exists on feed 'dotnet-eng'." } } if ($vsInstallDir -eq $null) { @@ -487,7 +485,7 @@ function InstallXCopyMSBuild([string]$packageVersion) { } function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { - $packageName = 'RoslynTools.MSBuild' + $packageName = 'Microsoft.DotNet.Arcade.MSBuild.Xcopy' $packageDir = Join-Path $ToolsDir "msbuild\$packageVersion" $packagePath = Join-Path $packageDir "$packageName.$packageVersion.nupkg" @@ -601,7 +599,15 @@ function InitializeBuildTool() { ExitWithExitCode 1 } $dotnetPath = Join-Path $dotnetRoot (GetExecutableFileName 'dotnet') - $buildTool = @{ Path = $dotnetPath; Command = 'msbuild'; Tool = 'dotnet'; Framework = 'net8.0' } + + # Use override if it exists - commonly set by source-build + if ($null -eq $env:_OverrideArcadeInitializeBuildToolFramework) { + $initializeBuildToolFramework="net9.0" + } else { + $initializeBuildToolFramework=$env:_OverrideArcadeInitializeBuildToolFramework + } + + $buildTool = @{ Path = $dotnetPath; Command = 'msbuild'; Tool = 'dotnet'; Framework = $initializeBuildToolFramework } } elseif ($msbuildEngine -eq "vs") { try { $msbuildPath = InitializeVisualStudioMSBuild -install:$restore @@ -676,8 +682,14 @@ function Read-ArcadeSdkVersion() { } function InitializeToolset() { - if (Test-Path variable:global:_ToolsetBuildProj) { - return $global:_ToolsetBuildProj + # For Unified Build/Source-build support, check whether the environment variable is + # set. If it is, then use this as the toolset build project. + if ($env:_InitializeToolset -ne $null) { + return $global:_InitializeToolset = $env:_InitializeToolset + } + + if (Test-Path variable:global:_InitializeToolset) { + return $global:_InitializeToolset } $nugetCache = GetNuGetPackageCachePath @@ -688,7 +700,7 @@ function InitializeToolset() { if (Test-Path $toolsetLocationFile) { $path = Get-Content $toolsetLocationFile -TotalCount 1 if (Test-Path $path) { - return $global:_ToolsetBuildProj = $path + return $global:_InitializeToolset = $path } } @@ -711,7 +723,7 @@ function InitializeToolset() { throw "Invalid toolset path: $path" } - return $global:_ToolsetBuildProj = $path + return $global:_InitializeToolset = $path } function ExitWithExitCode([int] $exitCode) { @@ -763,12 +775,10 @@ function MSBuild() { # new scripts need to work with old packages, so we need to look for the old names/versions (Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.ArcadeLogging.dll')), (Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.Arcade.Sdk.dll')), - (Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.ArcadeLogging.dll')), - (Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.Arcade.Sdk.dll')) - (Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.ArcadeLogging.dll')), - (Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.Arcade.Sdk.dll')) (Join-Path $basePath (Join-Path net7.0 'Microsoft.DotNet.ArcadeLogging.dll')), - (Join-Path $basePath (Join-Path net7.0 'Microsoft.DotNet.Arcade.Sdk.dll')) + (Join-Path $basePath (Join-Path net7.0 'Microsoft.DotNet.Arcade.Sdk.dll')), + (Join-Path $basePath (Join-Path net8.0 'Microsoft.DotNet.ArcadeLogging.dll')), + (Join-Path $basePath (Join-Path net8.0 'Microsoft.DotNet.Arcade.Sdk.dll')) ) $selectedPath = $null foreach ($path in $possiblePaths) { @@ -827,7 +837,8 @@ function MSBuild-Core() { } } - $env:ARCADE_BUILD_TOOL_COMMAND = "$($buildTool.Path) $cmdArgs" + # Be sure quote the path in case there are spaces in the dotnet installation location. + $env:ARCADE_BUILD_TOOL_COMMAND = "`"$($buildTool.Path)`" $cmdArgs" $exitCode = Exec-Process $buildTool.Path $cmdArgs @@ -842,7 +853,8 @@ function MSBuild-Core() { } # When running on Azure Pipelines, override the returned exit code to avoid double logging. - if ($ci -and $env:SYSTEM_TEAMPROJECT -ne $null) { + # Skip this when the build is a child of the VMR orchestrator build. + if ($ci -and $env:SYSTEM_TEAMPROJECT -ne $null -and !$productBuild -and $properties -notlike "*DotNetBuildRepo=true*") { Write-PipelineSetResult -Result "Failed" -Message "msbuild execution failed." # Exiting with an exit code causes the azure pipelines task to log yet another "noise" error # The above Write-PipelineSetResult will cause the task to be marked as failure without adding yet another error diff --git a/eng/common/tools.sh b/eng/common/tools.sh old mode 100644 new mode 100755 index e8d478943341..6f0141e7d513 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -68,6 +68,9 @@ fi runtime_source_feed=${runtime_source_feed:-''} runtime_source_feed_key=${runtime_source_feed_key:-''} +# True if the build is a product build +product_build=${product_build:-false} + # Resolve any symlinks in the given path. function ResolvePath { local path=$1 @@ -112,7 +115,7 @@ function InitializeDotNetCli { export DOTNET_MULTILEVEL_LOOKUP=0 # Disable first run since we want to control all package sources - export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 + export DOTNET_NOLOGO=1 # Disable telemetry on CI if [[ $ci == true ]]; then @@ -123,11 +126,6 @@ function InitializeDotNetCli { # so it doesn't output warnings to the console. export LTTNG_HOME="$HOME" - # Source Build uses DotNetCoreSdkDir variable - if [[ -n "${DotNetCoreSdkDir:-}" ]]; then - export DOTNET_INSTALL_DIR="$DotNetCoreSdkDir" - fi - # Find the first path on $PATH that contains the dotnet.exe if [[ "$use_installed_dotnet_cli" == true && $global_json_has_runtimes == false && -z "${DOTNET_INSTALL_DIR:-}" ]]; then local dotnet_path=`command -v dotnet` @@ -146,7 +144,7 @@ function InitializeDotNetCli { if [[ $global_json_has_runtimes == false && -n "${DOTNET_INSTALL_DIR:-}" && -d "$DOTNET_INSTALL_DIR/sdk/$dotnet_sdk_version" ]]; then dotnet_root="$DOTNET_INSTALL_DIR" else - dotnet_root="$repo_root/.dotnet" + dotnet_root="${repo_root}.dotnet" export DOTNET_INSTALL_DIR="$dotnet_root" @@ -165,7 +163,7 @@ function InitializeDotNetCli { Write-PipelinePrependPath -path "$dotnet_root" Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0" - Write-PipelineSetVariable -name "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" -value "1" + Write-PipelineSetVariable -name "DOTNET_NOLOGO" -value "1" # return value _InitializeDotNetCli="$dotnet_root" @@ -310,7 +308,7 @@ function GetDotNetInstallScript { curl "$install_script_url" -sSL --retry 10 --create-dirs -o "$install_script" || { if command -v openssl &> /dev/null; then echo "Curl failed; dumping some information about dotnet.microsoft.com for later investigation" - echo | openssl s_client -showcerts -servername dotnet.microsoft.com -connect dotnet.microsoft.com:443 + echo | openssl s_client -showcerts -servername dotnet.microsoft.com -connect dotnet.microsoft.com:443 || true fi echo "Will now retry the same URL with verbose logging." with_retries curl "$install_script_url" -sSL --verbose --retry 10 --create-dirs -o "$install_script" || { @@ -341,7 +339,12 @@ function InitializeBuildTool { # return values _InitializeBuildTool="$_InitializeDotNetCli/dotnet" _InitializeBuildToolCommand="msbuild" - _InitializeBuildToolFramework="net8.0" + # use override if it exists - commonly set by source-build + if [[ "${_OverrideArcadeInitializeBuildToolFramework:-x}" == "x" ]]; then + _InitializeBuildToolFramework="net9.0" + else + _InitializeBuildToolFramework="${_OverrideArcadeInitializeBuildToolFramework}" + fi } # Set RestoreNoCache as a workaround for https://github.com/NuGet/Home/issues/3116 @@ -453,12 +456,10 @@ function MSBuild { local possiblePaths=() possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.ArcadeLogging.dll" ) possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.Arcade.Sdk.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.ArcadeLogging.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.Arcade.Sdk.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.ArcadeLogging.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.Arcade.Sdk.dll" ) possiblePaths+=( "$toolset_dir/net7.0/Microsoft.DotNet.ArcadeLogging.dll" ) possiblePaths+=( "$toolset_dir/net7.0/Microsoft.DotNet.Arcade.Sdk.dll" ) + possiblePaths+=( "$toolset_dir/net8.0/Microsoft.DotNet.ArcadeLogging.dll" ) + possiblePaths+=( "$toolset_dir/net8.0/Microsoft.DotNet.Arcade.Sdk.dll" ) for path in "${possiblePaths[@]}"; do if [[ -f $path ]]; then selectedPath=$path @@ -505,7 +506,8 @@ function MSBuild-Core { echo "Build failed with exit code $exit_code. Check errors above." # When running on Azure Pipelines, override the returned exit code to avoid double logging. - if [[ "$ci" == "true" && -n ${SYSTEM_TEAMPROJECT:-} ]]; then + # Skip this when the build is a child of the VMR orchestrator build. + if [[ "$ci" == true && -n ${SYSTEM_TEAMPROJECT:-} && "$product_build" != true && $properties != *"DotNetBuildRepo=true"* ]]; then Write-PipelineSetResult -result "Failed" -message "msbuild execution failed." # Exiting with an exit code causes the azure pipelines task to log yet another "noise" error # The above Write-PipelineSetResult will cause the task to be marked as failure without adding yet another error diff --git a/eng/pipelines/common/apiscan.yml b/eng/pipelines/common/apiscan.yml new file mode 100644 index 000000000000..996c12c1c53d --- /dev/null +++ b/eng/pipelines/common/apiscan.yml @@ -0,0 +1,23 @@ +parameters: + poolName: VSEngSS-MicroBuild2022-1ES + vmImage: '' + os: windows + softwareName: 'MAUI' + softwareVersion: 8.0 + dependsOn: [] + scanArtifacts: [] + stageName: 'api_scan' + displayName: 'ApiScan' + +stages: + - template: security/apiscan/v0.yml@yaml-templates + parameters: + windowsPoolName: ${{ parameters.poolName }} + windowsImageOverride: ${{ parameters.vmImage }} + stageDependsOn: ${{ parameters.dependsOn }} + timeoutInMinutes: 600 + scanArtifacts: ${{ parameters.scanArtifacts }} + sourceGdnSuppressionFile: '$(System.DefaultWorkingDirectory)\eng\automation\guardian\source.gdnsuppress' + tsaConfigFile: '$(System.DefaultWorkingDirectory)\eng\automation\guardian\tsaoptions-v2.json' + apiScanSoftwareName: ${{ parameters.softwareName }} + apiScanSoftwareVersionNum: ${{ parameters.softwareVersion }} \ No newline at end of file diff --git a/eng/pipelines/common/insertion.yml b/eng/pipelines/common/insertion.yml index f51397c389e0..bbd556645c02 100644 --- a/eng/pipelines/common/insertion.yml +++ b/eng/pipelines/common/insertion.yml @@ -1,29 +1,22 @@ parameters: poolName: VSEngSS-MicroBuild2022-1ES vmImage: '' + os: windows + dependsOn: [] + stageName: 'sdk_insertion' + displayName: 'SDK Insertion' pushMauiPackagesToMaestro: false stages: - - stage: sdk_insertion - displayName: 'SDK Insertion' - dependsOn: nuget_signing + - stage: ${{ parameters.stageName }} + displayName: ${{ parameters.displayName }} + dependsOn: ${{ parameters.dependsOn }} condition: and(succeeded(), eq(variables.signingCondition, true)) jobs: - - template: sdk-insertion.yml + - template: /eng/pipelines/common/sdk-insertion.yml@self parameters: poolName: ${{ parameters.poolName }} vmImage: ${{ parameters.vmImage }} + os: ${{ parameters.os }} pushMauiPackagesToMaestro: ${{ parameters.pushMauiPackagesToMaestro }} - - stage: sbom - displayName: 'Software Bill of Materials' - dependsOn: nuget_signing - condition: and(succeeded(), eq(variables.signingCondition, true)) - jobs: - - template: compliance/sbom/job.v1.yml@yaml-templates - parameters: - artifactNames: [ nuget, vs-msi-nugets, vsdrop-signed ] - artifactMap: [ nuget/signed ] # Use artifacts that match the filter from the signed directory and not the top-level directory for the nuget artifact - packageName: 'Microsoft Maui' - packageFilter: '*.msi;*.nupkg' - condition: and(succeeded(), eq(variables.signingCondition, true)) diff --git a/eng/pipelines/common/pack.yml b/eng/pipelines/common/pack.yml index 0144fc0b286c..bed2ca312849 100644 --- a/eng/pipelines/common/pack.yml +++ b/eng/pipelines/common/pack.yml @@ -3,10 +3,6 @@ parameters: type: string default: '' -- name: poolName - type: string - default: '' - - name: provisionatorChannel type: string default: 'latest' @@ -19,15 +15,22 @@ parameters: type: string default: 'pack-binaries' +- name: artifactsPath + type: string + default: (Build.ArtifactStagingDirectory) + - name: nugetFolder type: string default: 'artifacts' - - name: prepareSteps type: stepList default: [] +- name: postSteps + type: stepList + default: [] + - name: gitHubToken type: string default: $(github--pat--vs-mobiletools-engineering-service2) @@ -36,16 +39,15 @@ parameters: type: string default: $(System.DefaultWorkingDirectory) -steps: +- name: additionalArtifacts + type: object + default: [] - - ${{ if ne(variables['Build.DefinitionName'], 'dotnet-maui') }}: - - template: provision.yml - parameters: - checkoutDirectory: ${{ parameters.checkoutDirectory }} - poolName: ${{ parameters.poolName }} - provisionatorChannel: ${{ parameters.provisionatorChannel }} - gitHubToken: ${{ parameters.gitHubToken }} - skipAndroidImages: true +- name: publishArtifacts + type: boolean + default: true + +steps: - ${{ each step in parameters.prepareSteps }}: - ${{ each pair in step }}: @@ -116,6 +118,16 @@ steps: displayName: 'Diff .NET Maui artifacts with NuGet' workingDirectory: ${{ parameters.checkoutDirectory }} + # binaries for compliance scanning + - task: CopyFiles@2 + displayName: 'Copy Binaries Files' + condition: succeeded() + inputs: + Contents: | + ${{ parameters.checkoutDirectory }}/src/Controls/src/Nuget/bin/Release/**/*.dll + TargetFolder: ${{ parameters.checkoutDirectory }}/artifacts/binaries + flattenFolders: false + # artifacts - task: CopyFiles@2 condition: always() @@ -128,7 +140,8 @@ steps: ${{ parameters.checkoutDirectory }}/eng/automation/SignList.xml ${{ parameters.checkoutDirectory }}/eng/automation/SignVerifyIgnore.txt !${{ parameters.checkoutDirectory}}/artifacts/docs-packs/** - TargetFolder: $(build.artifactstagingdirectory) + !${{ parameters.checkoutDirectory}}/artifacts/binaries/** + TargetFolder: ${{ parameters.artifactsPath }} flattenFolders: true - task: CopyFiles@2 @@ -139,7 +152,7 @@ steps: Contents: | metadata/** api-diff/** - TargetFolder: $(build.artifactstagingdirectory) + TargetFolder: ${{ parameters.artifactsPath }} - task: CopyFiles@2 displayName: 'Copy Log Files' @@ -147,37 +160,33 @@ steps: inputs: Contents: | ${{ parameters.checkoutDirectory }}/artifacts/logs/** - TargetFolder: $(build.artifactstagingdirectory)/logs + TargetFolder: ${{ parameters.artifactsPath }}/logs flattenFolders: true - - - task: PublishBuildArtifacts@1 - condition: always() - displayName: publish artifacts - inputs: - ArtifactName: ${{ parameters.artifact }} - # xml-docs - - ${{ if eq(parameters.platform, 'Windows') }}: + + - ${{ if eq(parameters.publishArtifacts, 'true') }}: - task: PublishBuildArtifacts@1 condition: always() - displayName: publish docs artifacts - inputs: - PathToPublish: ${{ parameters.checkoutDirectory }}/artifacts/docs-packs - ArtifactName: xml-docs - - # binaries for compliance scanning - - task: CopyFiles@2 - displayName: 'Copy Binaries Files' - condition: succeeded() + displayName: publish artifacts inputs: - Contents: | - ${{ parameters.checkoutDirectory }}/src/Controls/src/Nuget/bin/Release/**/*.dll - TargetFolder: ${{ parameters.checkoutDirectory }}/binaries - flattenFolders: false - - - task: PublishBuildArtifacts@1 - condition: succeeded() - displayName: publish binaries artifacts - inputs: - PathToPublish: ${{ parameters.checkoutDirectory }}/binaries - ArtifactName: ${{ parameters.artifactBinaries }} - + ArtifactName: ${{ parameters.artifact }} + PathToPublish: ${{ parameters.artifactsPath }} + + # xml-docs + - ${{ if eq(parameters.platform, 'Windows') }}: + - task: PublishBuildArtifacts@1 + condition: always() + displayName: publish docs artifacts + inputs: + PathToPublish: ${{ parameters.checkoutDirectory }}/artifacts/docs-packs + ArtifactName: xml-docs + + - task: PublishBuildArtifacts@1 + condition: succeeded() + displayName: publish binaries artifacts + inputs: + PathToPublish: ${{ parameters.checkoutDirectory }}/artifacts/binaries + ArtifactName: ${{ parameters.artifactBinaries }} + + - ${{ each step in parameters.postSteps }}: + - ${{ each pair in step }}: + ${{ pair.key }}: ${{ pair.value }} \ No newline at end of file diff --git a/eng/pipelines/common/sdk-insertion.yml b/eng/pipelines/common/sdk-insertion.yml index 4225a29989bc..d10760fed1a2 100644 --- a/eng/pipelines/common/sdk-insertion.yml +++ b/eng/pipelines/common/sdk-insertion.yml @@ -1,7 +1,10 @@ parameters: poolName: VSEngSS-MicroBuild2022-1ES vmImage: '' + os: windows pushMauiPackagesToMaestro: false + nugetArtifactName: nuget-signed + nugetArtifactPath: $(Build.StagingDirectory)\nuget-signed jobs: - job: create_artifact_statuses @@ -9,30 +12,31 @@ jobs: timeoutInMinutes: 60 pool: name: ${{ parameters.poolName }} - vmImage: ${{ parameters.vmImage }} + image: ${{ parameters.vmImage }} + os: ${{ parameters.os }} variables: - group: Publish-Build-Assets steps: - checkout: self - task: DownloadPipelineArtifact@2 inputs: - artifactName: nuget - downloadPath: $(Build.StagingDirectory)\nuget + artifactName: ${{ parameters.nugetArtifactName }} + downloadPath: ${{ parameters.nugetArtifactPath }} patterns: | - **/signed/*.nupkg + *.nupkg **/*.snupkg **/additional-assets.zip - task: DownloadPipelineArtifact@2 inputs: artifactName: vs-msi-nugets - downloadPath: $(Build.StagingDirectory)\nuget + downloadPath: ${{ parameters.nugetArtifactPath }} - template: templates\common\upload-vs-insertion-artifacts.yml@sdk-insertions parameters: githubToken: $(github--pat--vs-mobiletools-engineering-service2) githubContext: $(NupkgCommitStatusName) blobName: $(NupkgCommitStatusName) packagePrefix: maui - artifactsPath: $(Build.StagingDirectory)\nuget + artifactsPath: ${{ parameters.nugetArtifactPath }} yamlResourceName: yaml-templates - template: templates\common\upload-vs-insertion-artifacts.yml@sdk-insertions parameters: @@ -67,7 +71,7 @@ jobs: arguments: >- -t:PushManifestToBuildAssetRegistry -p:BuildAssetRegistryToken=$(MaestroAccessToken) - -p:OutputPath=$(Build.StagingDirectory)\nuget\ + -p:OutputPath=$(Build.StagingDirectory)\nuget-signed\ -v:n -bl:$(Build.StagingDirectory)\binlogs\push-bar-manifest.binlog condition: and(succeeded(), eq('${{ parameters.pushMauiPackagesToMaestro }}', 'true')) - powershell: | diff --git a/eng/pipelines/common/sign.yml b/eng/pipelines/common/sign.yml index eded95eca34a..cb8fbab9d1cd 100644 --- a/eng/pipelines/common/sign.yml +++ b/eng/pipelines/common/sign.yml @@ -1,28 +1,34 @@ +parameters: + poolName: Azure Pipelines + vmImage: windows-latest + os: windows + teamName: $(TeamName) + signType: 'Real' + dependsOn: [] + stageName: 'nuget_signing' + displayName: 'Sign Nuget' + + stages: - - stage: nuget_signing - dependsOn: pack_net - displayName: Sign Nuget + - stage: ${{ parameters.stageName }} + dependsOn: ${{ parameters.dependsOn }} + displayName: ${{ parameters.displayName }} jobs: - template: sign-artifacts/jobs/v2.yml@yaml-templates parameters: - signType: Real - teamName: $(TeamName) - usePipelineArtifactTasks: false - targetFolder: $(Build.ArtifactStagingDirectory)/nuget/signed - signedArtifactName: nuget - signedArtifactPath: signed - displayName: Sign Phase - condition: and(succeeded(), eq(variables.signingCondition, true)) - + signType: ${{ parameters.signType }} + teamName: ${{ parameters.teamName }} + condition: eq(variables.signingCondition, true) + use1ESTemplate: true + usePipelineArtifactTasks: true + - template: nuget-msi-convert/job/v3.yml@yaml-templates parameters: yamlResourceName: yaml-templates - artifactName: nuget - artifactPatterns: | - **/signed/*.nupkg - artifactPath: signed - propsArtifactName: nuget - signType: Real + artifactName: nuget-signed + propsArtifactName: nuget + signType: ${{ parameters.signType }} + use1ESTemplate: true postConvertSteps: - task: DownloadPipelineArtifact@2 inputs: diff --git a/eng/pipelines/common/variables.yml b/eng/pipelines/common/variables.yml index b113de6661af..53556c9d981a 100644 --- a/eng/pipelines/common/variables.yml +++ b/eng/pipelines/common/variables.yml @@ -24,11 +24,11 @@ variables: - name: isPullRequest value: $[eq(variables['Build.Reason'], 'PullRequest')] - name: isLocHandoffBranch - value: $[in(variables['Build.SourceBranch'], 'refs/heads/net9.0', 'refs/heads/net7.0', 'refs/heads/net8.0', 'refs/heads/main')] + value: $[in(variables['Build.SourceBranch'], 'refs/heads/net9.0', 'refs/heads/net8.0', 'refs/heads/net7.0', 'refs/heads/main')] - name: signingCondition value: $[or( eq(variables['Sign'], 'true'), - in(variables['Build.SourceBranch'], 'refs/heads/net9.0', 'refs/heads/net7.0', 'refs/heads/net8.0', 'refs/heads/main'), + in(variables['Build.SourceBranch'], 'refs/heads/net9.0', 'refs/heads/net8.0', 'refs/heads/net7.0', 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/tags/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/') )] diff --git a/eng/pipelines/handlers.yml b/eng/pipelines/handlers.yml index 4a628624d718..7a13a1dbf9cc 100644 --- a/eng/pipelines/handlers.yml +++ b/eng/pipelines/handlers.yml @@ -67,28 +67,22 @@ parameters: type: boolean default: false - - name: RunCompliance - type: boolean - default: false - - name: BuildConfigurations type: object default: - Debug - Release + - name: BuildPlatforms type: object default: - name: Windows poolName: $(windowsNet6VmPool) vmImage: $(windowsNet6VmImage) - bootsAndroid: $(Android.Msi) artifact: build-windows - name: macOS poolName: $(macOSXNet6VmPool) vmImage: $(macOSXNet6VmImage) - bootsAndroid: $(Android.Pkg) - bootsMacCatalyst: $(MacCatalyst.Pkg) artifact: build-macos - name: PackPlatforms @@ -97,13 +91,10 @@ parameters: - name: Windows poolName: $(windowsNet6VmPool) vmImage: $(windowsNet6VmImage) - bootsAndroid: $(Android.Msi) artifact: nuget - name: macOS poolName: $(macOSXNet6VmPool) vmImage: $(macOSXNet6VmImage) - bootsAndroid: $(Android.Pkg) - bootsMacCatalyst: $(MacCatalyst.Pkg) artifact: nuget-macos - name: RunTemplatePlatforms @@ -214,11 +205,18 @@ stages: - template: common/pack.yml parameters: platform: ${{ PackPlatform.name }} - poolName: ${{ PackPlatform.poolName }} provisionatorChannel: ${{ parameters.provisionatorChannel }} artifact: ${{ PackPlatform.artifact }} + artifactsPath: '(Build.ArtifactStagingDirectory)' artifactBinaries: 'pack-binaries' gitHubToken: $(github--pat--vs-mobiletools-engineering-service2) + prepareSteps: + - template: common/provision.yml + parameters: + checkoutDirectory: '$(System.DefaultWorkingDirectory)' + provisionatorChannel: ${{ parameters.provisionatorChannel }} + gitHubToken: $(github--pat--vs-mobiletools-engineering-service2) + skipAndroidImages: true - stage: samples_net displayName: Test .NET MAUI Samples @@ -285,23 +283,3 @@ stages: - template: common/localization-handoff.yml # Process outgoing strings [Localization Handoff] - template: common/localization-handback.yml # Process incoming translations and Create PR to main [Localization Handback] - template: common/merge-translations-update.yml # Validating incoming translations strings and merge PR [Localization Handback] - - ${{ if or(eq(variables['Build.Reason'], 'Schedule'), parameters.RunCompliance) }}: - - template: security/full/v1.yml@yaml-templates - parameters: - stageDependsOn: 'pack_net' - complianceEnabled: true - complianceTimeoutInMinutes: 480 - scanArtifacts: ['pack-binaries'] - antiMalwareEnabled: true - binSkimEnabled: true - #binSkimTargetGlob: '$(Build.ArtifactStagingDirectory)\binaries-to-scan\pack-binaries\src\Controls\src\Nuget\bin\Release\net8.0\*.dll' - sourceGdnSuppressionFile: $(Build.SourcesDirectory)\eng\automation\guardian\source.gdnsuppress - tsaConfigFile: '$(Build.SourcesDirectory)\eng\automation\guardian\tsaoptions-v2.json' - policheckExclusionFile: '$(System.DefaultWorkingDirectory)\eng\automation\guardian\PoliCheck.Exclusions.xml' - policheckGdnSuppressionFilesFolder: '$(System.DefaultWorkingDirectory)\eng\automation\guardian' - credScanEnabled: true - credScanSuppressionFile: '$(System.DefaultWorkingDirectory)\eng\automation\guardian\CredScanSuppressions.json' - enableCodeInspector: true - apiScanEnabled: true - apiScanSoftwareName: 'MAUI' - apiScanSoftwareVersionNum: 8.0 diff --git a/eng/pipelines/maui-release-internal.yml b/eng/pipelines/maui-release-internal.yml index 193ccce5347f..6d6679b87222 100644 --- a/eng/pipelines/maui-release-internal.yml +++ b/eng/pipelines/maui-release-internal.yml @@ -22,65 +22,83 @@ trigger: variables: - - template: /eng/pipelines/common/variables.yml - + - template: /eng/pipelines/common/variables.yml@self + parameters: - name: provisionatorChannel displayName: 'Provisionator channel' type: string default: 'latest' # Support for launching a build against a Provisionator PR (e.g., pr/[github-account-name]/[pr-number]) as a means to test in-progress Provisionator changes - - name: PackPlatforms + - name: VM_IMAGE_HOST + type: object + default: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + os: windows + + - name: PackPlatform type: object default: - - name: Windows - poolName: $(windowsNet6VmPool) - vmImage: $(windowsNet6VmImage) - artifact: nuget + name: Windows + artifact: nuget -# resources: -# repositories: -# - repository: yaml-templates -# type: github -# name: xamarin/yaml-templates -# endpoint: xamarin -# ref: refs/heads/main -# - repository: sdk-insertions -# type: github -# name: xamarin/sdk-insertions -# ref: refs/heads/main -# endpoint: xamarin + - name: Skip1ESComplianceTasks + default: false -stages: +resources: + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release - - stage: pack_net - displayName: Pack .NET MAUI - dependsOn: [] - jobs: - - ${{ each PackPlatform in parameters.PackPlatforms }}: - - job: pack_net_${{ PackPlatform.name }} - workspace: - clean: all - displayName: ${{ PackPlatform.name }} - timeoutInMinutes: 240 - pool: - name: ${{ PackPlatform.poolName }} - vmImage: ${{ PackPlatform.vmImage }} - ${{ if startsWith(PackPlatform.poolName, 'VSEng-VSMac-Xamarin-Shared') }}: - demands: - - macOS.Name -equals Ventura - - macOS.Architecture -equals x64 - steps: - - template: common/pack.yml - parameters: - platform: ${{ PackPlatform.name }} - poolName: ${{ PackPlatform.poolName }} - provisionatorChannel: ${{ parameters.provisionatorChannel }} - artifact: ${{ PackPlatform.artifact }} +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + parameters: + pool: ${{ parameters.VM_IMAGE_HOST }} + sdl: + ${{ if eq('${{ parameters.Skip1ESComplianceTasks }}', 'true') }}: + enableAllTools: false + binskim: + scanOutputDirectoryOnly: true + codeql: + runSourceLanguagesInSourceAnalysis: true + policheck: + enabled: false + justification: Built in task does not support multi-language scanning + spotBugs: + enabled: false + justification: 'Failing with "Could not successfully find the java tool launcher"' + sourceRepositoriesToScan: + exclude: + - repository: yaml-templates + suppression: + suppressionFile: $(Build.SourcesDirectory)\eng\automation\guardian\source.gdnsuppress + stages: + - stage: pack_net + displayName: Pack .NET MAUI + dependsOn: [] + jobs: + - job: pack_net_${{ parameters.PackPlatform.name }} + workspace: + clean: all + displayName: ${{ parameters.PackPlatform.name }} + timeoutInMinutes: 240 + + pool: ${{ parameters.VM_IMAGE_HOST }} + + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish the ${{ parameters.PackPlatform.artifact }} artifacts' + artifactName: ${{ parameters.PackPlatform.artifact }} + targetPath: '(Build.ArtifactStagingDirectory)' - - ${{ if or(eq(variables['System.TeamProject'], 'DevDiv'), eq(variables['Build.DefinitionName'], 'dotnet-maui')) }}: - - template: common/sign.yml # Sign only using the private server - # - template: common/insertion.yml # Insert on VS and SDK - # parameters: - # poolName: $(windowsNet6VmPool) - # vmImage: $(windowsNet6VmImage) + steps: + - template: /eng/pipelines/common/pack.yml@self + parameters: + platform: ${{ parameters.PackPlatform.name }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + artifact: ${{ parameters.PackPlatform.artifact }} + artifactsPath: '(Build.ArtifactStagingDirectory)' \ No newline at end of file diff --git a/eng/pipelines/maui-release.yml b/eng/pipelines/maui-release.yml index 6b7bf2d6f2fc..9428e1d8c1bc 100644 --- a/eng/pipelines/maui-release.yml +++ b/eng/pipelines/maui-release.yml @@ -22,7 +22,7 @@ trigger: variables: - - template: /eng/pipelines/common/variables.yml + - template: /eng/pipelines/common/variables.yml@self - template: templates/common/vs-release-vars.yml@sdk-insertions parameters: @@ -34,13 +34,23 @@ parameters: type: string default: 'latest' # Support for launching a build against a Provisionator PR (e.g., pr/[github-account-name]/[pr-number]) as a means to test in-progress Provisionator changes - - name: PackPlatforms + - name: VM_IMAGE_HOST type: object default: - - name: Windows - poolName: $(windowsNet6VmPool) - vmImage: $(windowsNet6VmImage) - artifact: nuget + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + os: windows + + - name: PackPlatform + type: object + default: + name: Windows + artifact: nuget + binariesArtifact: pack-binaries + docsArtifact: xml-docs + + - name: Skip1ESComplianceTasks + default: false resources: repositories: @@ -54,36 +64,103 @@ resources: name: xamarin/sdk-insertions ref: refs/heads/main endpoint: xamarin + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + parameters: + pool: ${{ parameters.VM_IMAGE_HOST }} + sdl: + ${{ if eq('${{ parameters.Skip1ESComplianceTasks }}', 'true') }}: + enableAllTools: false + binskim: + scanOutputDirectoryOnly: true + codeql: + runSourceLanguagesInSourceAnalysis: true + policheck: + enabled: true + spotBugs: + enabled: false + justification: 'Failing with "Could not successfully find the java tool launcher"' + sourceRepositoriesToScan: + exclude: + - repository: yaml-templates + suppression: + suppressionFile: $(Build.SourcesDirectory)\eng\automation\guardian\source.gdnsuppress + stages: + - stage: pack_net + displayName: Pack .NET MAUI + dependsOn: [] + jobs: + - job: pack_net_${{ parameters.PackPlatform.name }} + workspace: + clean: all + displayName: ${{ parameters.PackPlatform.name }} + timeoutInMinutes: 240 + + pool: ${{ parameters.VM_IMAGE_HOST }} + + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish the ${{ parameters.PackPlatform.artifact }} artifacts' + artifactName: ${{ parameters.PackPlatform.artifact }} + targetPath: '(Build.ArtifactStagingDirectory)' + + - output: pipelineArtifact + displayName: 'Publish the ${{ parameters.PackPlatform.binariesArtifact }} artifacts' + artifactName: ${{ parameters.PackPlatform.binariesArtifact }} + targetPath: '$(System.DefaultWorkingDirectory)/artifacts/binaries' + + - output: pipelineArtifact + displayName: 'Publish the ${{ parameters.PackPlatform.docsArtifact }} artifacts' + artifactName: ${{ parameters.PackPlatform.docsArtifact }} + targetPath: '$(System.DefaultWorkingDirectory)/artifacts/docs-packs' + + steps: + - template: /eng/pipelines/common/pack.yml@self + parameters: + publishArtifacts: false + platform: ${{ parameters.PackPlatform.name }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + artifact: ${{ parameters.PackPlatform.artifact }} + artifactBinaries: ${{ parameters.PackPlatform.binariesArtifact }} + artifactsPath: '(Build.ArtifactStagingDirectory)' + prepareSteps: + - template: /eng/pipelines/common/provision.yml@self + parameters: + checkoutDirectory: '$(System.DefaultWorkingDirectory)' + provisionatorChannel: ${{ parameters.provisionatorChannel }} + gitHubToken: $(github--pat--vs-mobiletools-engineering-service2) + skipAndroidImages: true -stages: + - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: # Sign only using the private server + - template: /eng/pipelines/common/sign.yml@self + parameters: + dependsOn: ['pack_net'] + stageName: 'nuget_signing' + poolName: ${{ parameters.VM_IMAGE_HOST.name }} + vmImage: ${{ parameters.VM_IMAGE_HOST.image }} + os: ${{ parameters.VM_IMAGE_HOST.os }} + + - template: /eng/pipelines/common/insertion.yml@self # Insert on VS and SDK + parameters: + dependsOn: ['nuget_signing'] + stageName: 'sdk_insertion' + poolName: ${{ parameters.VM_IMAGE_HOST.name }} + vmImage: ${{ parameters.VM_IMAGE_HOST.image }} + os: ${{ parameters.VM_IMAGE_HOST.os }} + pushMauiPackagesToMaestro: ${{ parameters.pushMauiPackagesToMaestro }} - - stage: pack_net - displayName: Pack .NET MAUI - dependsOn: [] - jobs: - - ${{ each PackPlatform in parameters.PackPlatforms }}: - - job: pack_net_${{ PackPlatform.name }} - workspace: - clean: all - displayName: ${{ PackPlatform.name }} - timeoutInMinutes: 240 - pool: - name: ${{ PackPlatform.poolName }} - vmImage: ${{ PackPlatform.vmImage }} - ${{ if startsWith(PackPlatform.poolName, 'VSEng-VSMac-Xamarin-Shared') }}: - demands: - - macOS.Name -equals Ventura - - macOS.Architecture -equals x64 - steps: - - template: common/pack.yml - parameters: - platform: ${{ PackPlatform.name }} - poolName: ${{ PackPlatform.poolName }} - provisionatorChannel: ${{ parameters.provisionatorChannel }} - artifact: ${{ PackPlatform.artifact }} + - template: /eng/pipelines/common/apiscan.yml@self # ApiScan + parameters: + dependsOn: ['pack_net'] + poolName: ${{ parameters.VM_IMAGE_HOST.name }} + vmImage: ${{ parameters.VM_IMAGE_HOST.image }} + os: ${{ parameters.VM_IMAGE_HOST.os }} + scanArtifacts: ['${{ parameters.PackPlatform.binariesArtifact }}'] - - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: - - template: common/sign.yml # Sign only using the private server - - template: common/insertion.yml # Insert on VS and SDK - parameters: - pushMauiPackagesToMaestro: ${{ parameters.pushMauiPackagesToMaestro }} + diff --git a/src/Compatibility/ControlGallery/src/Issues.Shared/Issue10134.cs b/src/Compatibility/ControlGallery/src/Issues.Shared/Issue10134.cs index 33039cbf8ba6..4c29e18a20dd 100644 --- a/src/Compatibility/ControlGallery/src/Issues.Shared/Issue10134.cs +++ b/src/Compatibility/ControlGallery/src/Issues.Shared/Issue10134.cs @@ -44,6 +44,7 @@ protected override void Init() #if UITEST && __SHELL__ [Test] + [Compatibility.UITests.FailsOnMauiIOS] public void TopTabsDontScrollBackToStartWhenSelected() { var element1 = RunningApp.WaitForElement("Tab 1", "Shell hasn't loaded")[0].Rect; diff --git a/src/Compatibility/Core/src/Compatibility.csproj b/src/Compatibility/Core/src/Compatibility.csproj index c7fcc4d7bcd0..9c185620b649 100644 --- a/src/Compatibility/Core/src/Compatibility.csproj +++ b/src/Compatibility/Core/src/Compatibility.csproj @@ -67,7 +67,6 @@ - diff --git a/src/Controls/samples/Controls.Sample.UITests/Issues/Issue10947.xaml b/src/Controls/samples/Controls.Sample.UITests/Issues/Issue10947.xaml new file mode 100644 index 000000000000..54721464bfec --- /dev/null +++ b/src/Controls/samples/Controls.Sample.UITests/Issues/Issue10947.xaml @@ -0,0 +1,41 @@ + + + + + + First Item + Second Item + Third Item + Fourth Item + Fifth Item + Sixth Item + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Controls/samples/Controls.Sample.UITests/Issues/Issue10947.xaml.cs b/src/Controls/samples/Controls.Sample.UITests/Issues/Issue10947.xaml.cs new file mode 100644 index 000000000000..dda04562112e --- /dev/null +++ b/src/Controls/samples/Controls.Sample.UITests/Issues/Issue10947.xaml.cs @@ -0,0 +1,19 @@ +using Microsoft.Maui.Controls; +using Microsoft.Maui.Controls.Xaml; +using Microsoft.Maui.Platform; +using Microsoft.Maui.Controls.PlatformConfiguration; +using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; +using System; + +namespace Maui.Controls.Sample.Issues; + +[XamlCompilation(XamlCompilationOptions.Compile)] +[Issue(IssueTracker.Github, 10947, "CollectionView Header and Footer Scrolling", PlatformAffected.iOS)] + +public partial class Issue10947 : ContentPage +{ + public Issue10947() + { + InitializeComponent(); + } +} diff --git a/src/Controls/samples/Controls.Sample.UITests/Issues/Issue20903.xaml b/src/Controls/samples/Controls.Sample.UITests/Issues/Issue20903.xaml new file mode 100644 index 000000000000..1cd285463610 --- /dev/null +++ b/src/Controls/samples/Controls.Sample.UITests/Issues/Issue20903.xaml @@ -0,0 +1,27 @@ + + + +