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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion eng/Directory.Build.Common.props
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@
<GenerateAPIListing Condition="'$(GenerateAPIListing)' == '' AND '$(IsShippingClientLibrary)' == 'true'">true</GenerateAPIListing>
<EnableSourceLink Condition="'$(EnableSourceLink)' == ''">true</EnableSourceLink>
<DefineConstants Condition="'$(BuildSnippets)' == 'true'">$(DefineConstants);SNIPPET</DefineConstants>
<AotCompatOptOut>false</AotCompatOptOut>
<AotCompatOptOut Condition="'$(IsShippingLibrary)' == 'true'">false</AotCompatOptOut>
<AotAnalyzersOptOut Condition="'$(IsShippingLibrary)' == 'true'">false</AotAnalyzersOptOut>
<ApiCompatBaselineTargetFramework Condition="'$(TargetFramework)' == '$(LtsTargetFramework)'">netstandard2.0</ApiCompatBaselineTargetFramework>
</PropertyGroup>

Expand Down
4 changes: 2 additions & 2 deletions eng/Directory.Build.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<PackageRootDirectory>$([MSBuild]::NormalizeDirectory($(MSBuildProjectDirectory)/../).TrimEnd("/").TrimEnd("\\"))</PackageRootDirectory>
</PropertyGroup>

<PropertyGroup Condition="'$(IsShippingLibrary)' == 'true' and '$(AotCompatOptOut)' == 'false'">
<PropertyGroup Condition="'$(IsShippingLibrary)' == 'true' and '$(AotCompatOptOut)' == 'false' and '$(AotAnalyzersOptOut)' == 'false'">
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">true</IsAotCompatible>
</PropertyGroup>

Expand Down Expand Up @@ -387,7 +387,7 @@
<ServiceDirectory><![CDATA[$([System.Text.RegularExpressions.Regex]::Replace($(PackageRootDirectory), '^.*[\\/]+sdk[\\/]+([^\\/]+).*$', '$1'))]]></ServiceDirectory>

<!-- Format package info line for output -->
<PackageInfoText Condition="'$(IsShippingLibrary)' == 'true'">'$(PackageRootDirectory)' '$(ServiceDirectory)' '$(PackageId)' '$(VersionForProperties)' '$(PackageSdkType)' '$(PackageIsNewSdk)' '$(BaseOutputPath)' '$(AotCompatOptOut)'</PackageInfoText>
<PackageInfoText Condition="'$(IsShippingLibrary)' == 'true'">'$(PackageRootDirectory)' '$(ServiceDirectory)' '$(PackageId)' '$(VersionForProperties)' '$(PackageSdkType)' '$(PackageIsNewSdk)' '$(BaseOutputPath)' </PackageInfoText>
</PropertyGroup>

<ItemGroup Condition="'$(IsShippingLibrary)' == 'true'">
Expand Down
1 change: 0 additions & 1 deletion eng/pipelines/pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ extends:
ServiceDirectory: template
${{ else }}:
ServiceDirectory: ${{ parameters.Service }}
CheckAOTCompat: true
BuildSnippets: true
ExcludePaths:
- eng/packages/http-client-csharp/
8 changes: 0 additions & 8 deletions eng/pipelines/templates/jobs/batched-build-analyze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ parameters:
- name: SDKType
type: string
default: all
- name: CheckAOTCompat
type: boolean
default: false
- name: AOTTestInputs
type: object
default: []
- name: BuildSnippets
type: boolean
default: true
Expand Down Expand Up @@ -66,8 +60,6 @@ jobs:
TestPipeline: ${{ parameters.TestPipeline }}
ServiceDirectory: ${{ parameters.ServiceDirectory }}
SDKType: ${{ parameters.SDKType }}
CheckAOTCompat: ${{ parameters.CheckAOTCompat }}
AOTTestInputs: ${{ parameters.AOTTestInputs }}

- job:
displayName: "Analyze"
Expand Down
10 changes: 0 additions & 10 deletions eng/pipelines/templates/jobs/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ parameters:
- name: BuildSnippets
type: boolean
default: true
- name: CheckAOTCompat
type: boolean
default: false
- name: AOTTestInputs
type: object
default: []
- name: TestSetupSteps
type: stepList
default: []
Expand Down Expand Up @@ -75,8 +69,6 @@ jobs:
TestPipeline: ${{ parameters.TestPipeline }}
ServiceDirectory: ${{ parameters.ServiceDirectory }}
SDKType: ${{ parameters.SDKType }}
CheckAOTCompat: ${{ parameters.CheckAOTCompat }}
AOTTestInputs: ${{ parameters.AOTTestInputs }}
BuildSnippets: ${{ parameters.BuildSnippets }}
PreGenerationSteps:
- template: /eng/pipelines/templates/steps/pr-matrix-presteps.yml
Expand Down Expand Up @@ -116,8 +108,6 @@ jobs:
TestPipeline: ${{ parameters.TestPipeline }}
ServiceDirectory: ${{ parameters.ServiceDirectory }}
SDKType: ${{ parameters.SDKType }}
CheckAOTCompat: ${{ parameters.CheckAOTCompat }}
AOTTestInputs: ${{ parameters.AOTTestInputs }}

- job: "Analyze"
timeoutInMinutes: ${{ parameters.TestTimeoutInMinutes }}
Expand Down
8 changes: 0 additions & 8 deletions eng/pipelines/templates/stages/archetype-sdk-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ parameters:
- name: BuildSnippets
type: boolean
default: true
- name: CheckAOTCompat
type: boolean
default: false
- name: AOTTestInputs
type: object
default: []
- name: TestSetupSteps
type: stepList
default: []
Expand Down Expand Up @@ -84,8 +78,6 @@ extends:
ArtifactName: packages
LimitForPullRequest: ${{ parameters.LimitForPullRequest }}
BuildSnippets: ${{ parameters.BuildSnippets }}
CheckAOTCompat: ${{ parameters.CheckAOTCompat }}
AOTTestInputs: ${{ parameters.AOTTestInputs }}
TestSetupSteps: ${{ parameters.TestSetupSteps }}
TestTimeoutInMinutes: ${{ parameters.TestTimeoutInMinutes }}
MatrixConfigs:
Expand Down
10 changes: 5 additions & 5 deletions eng/pipelines/templates/steps/aot-compatibility.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
parameters:
ServiceDirectory: ''
Artifacts: ''
PackageInfoFolder: ''
AOTTestInputs: []

steps:

Expand All @@ -16,14 +16,14 @@ steps:
-ProjectNames "$(ProjectNames)"
workingDirectory: $(Build.SourcesDirectory)/eng/scripts/compatibility
- ${{ else }}:
- ${{ each aotTestInput in parameters.AOTTestInputs }}:
- ${{ each artifact in parameters.Artifacts }}:
- task: Powershell@2
displayName: Check for AOT compatibility regressions in ${{ aotTestInput.ArtifactName }}
displayName: Check for AOT compatibility regressions in ${{ artifact.name }}
inputs:
targetType: filepath
filePath: $(Build.SourcesDirectory)/eng/scripts/compatibility/Check-AOT-Compatibility.ps1
arguments: >-
-ServiceDirectory ${{ parameters.ServiceDirectory }}
-PackageName ${{ aotTestInput.ArtifactName }}
-ExpectedWarningsFilePath ${{ aotTestInput.ExpectedWarningsFilePath }}
-PackageName ${{ artifact.name }}
-DirectoryName ${{ artifact.directoryName }}
workingDirectory: $(Build.SourcesDirectory)/eng/scripts/compatibility
17 changes: 5 additions & 12 deletions eng/pipelines/templates/steps/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ parameters:
- name: SDKType
type: string
default: all
- name: CheckAOTCompat
type: boolean
default: false
- name: AOTTestInputs
type: object
default: []
- name: BuildSnippets
type: boolean
default: true
Expand Down Expand Up @@ -153,12 +147,11 @@ steps:
LibType: 'client'
PackageInfoFolder: '$(Build.ArtifactStagingDirectory)/PackageInfo'

- ${{ if eq(parameters.CheckAOTCompat, 'true') }}:
- template: /eng/pipelines/templates/steps/aot-compatibility.yml
parameters:
ServiceDirectory: ${{ parameters.ServiceDirectory }}
AOTTestInputs: ${{ parameters.AOTTestInputs }}
PackageInfoFolder: '$(Build.ArtifactStagingDirectory)/PackageInfo'
- template: /eng/pipelines/templates/steps/aot-compatibility.yml
parameters:
ServiceDirectory: ${{ parameters.ServiceDirectory }}
Artifacts: ${{ parameters.Artifacts }}
PackageInfoFolder: '$(Build.ArtifactStagingDirectory)/PackageInfo'

- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: "Component Detection"
Expand Down
50 changes: 2 additions & 48 deletions eng/scripts/Language-Settings.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function Get-AllPackageInfoFromRepo($serviceDirectory)
continue
}

$pkgPath, $serviceDirectory, $pkgName, $pkgVersion, $sdkType, $isNewSdk, $dllFolder, $AotCompatOptOut = $projectOutput.Split("' '", [System.StringSplitOptions]::RemoveEmptyEntries).Trim("' ")
$pkgPath, $serviceDirectory, $pkgName, $pkgVersion, $sdkType, $isNewSdk, $dllFolder = $projectOutput.Split("' '", [System.StringSplitOptions]::RemoveEmptyEntries).Trim("' ")
if(!(Test-Path $pkgPath)) {
Write-Host "Parsed package path `$pkgPath` does not exist so skipping the package line '$projectOutput'."
continue
Expand All @@ -67,49 +67,6 @@ function Get-AllPackageInfoFromRepo($serviceDirectory)
$ciProps = $pkgProp.GetCIYmlForArtifact()

if ($ciProps) {
# First, check if this artifact has baselined warnings in AOTTestInputs
$aotArtifacts = GetValueSafelyFrom-Yaml $ciProps.ParsedYml @("extends", "parameters", "AOTTestInputs")
$hasBaselinedWarnings = $false
if ($aotArtifacts) {
$matchingAotArtifact = $aotArtifacts | Where-Object { $_.ArtifactName -eq $pkgProp.ArtifactName }
if ($matchingAotArtifact -and $matchingAotArtifact.ExpectedWarningsFilepath) {
$hasBaselinedWarnings = $true
}
}

# CheckAOTCompat logic: if set in CI.yml, respect that value;
# if artifact has baselined warnings, run AOT checks;
# otherwise use AotCompatOptOut from project settings
$shouldAot = GetValueSafelyFrom-Yaml $ciProps.ParsedYml @("extends", "parameters", "CheckAOTCompat")
if ($null -ne $shouldAot) {
$parsedBool = $null
if ([bool]::TryParse($shouldAot, [ref]$parsedBool)) {
$pkgProp.CIParameters["CheckAOTCompat"] = $parsedBool
}
}
elseif ($hasBaselinedWarnings) {
# If artifact has baselined warnings, enable AOT checks
$pkgProp.CIParameters["CheckAOTCompat"] = $true
}
else {
# If not explicitly opted out of AOT compat, run the check
$pkgProp.CIParameters["CheckAOTCompat"] = $AotCompatOptOut -ne 'true'
}

# If CheckAOTCompat is true, look for additional AOTTestInputs parameter
if ($pkgProp.CIParameters["CheckAOTCompat"]) {
if ($aotArtifacts) {
$aotArtifacts = $aotArtifacts | Where-Object { $_.ArtifactName -eq $pkgProp.ArtifactName }
$pkgProp.CIParameters["AOTTestInputs"] = $aotArtifacts
}
else {
$pkgProp.CIParameters["AOTTestInputs"] = @()
}
}
else {
$pkgProp.CIParameters["AOTTestInputs"] = @()
}

# BuildSnippets is opt _out_, so we should default to true if not specified
$shouldSnippet = GetValueSafelyFrom-Yaml $ciProps.ParsedYml @("extends", "parameters", "BuildSnippets")
if ($null -ne $shouldSnippet) {
Expand All @@ -123,11 +80,8 @@ function Get-AllPackageInfoFromRepo($serviceDirectory)
}
}
# if the package isn't associated with a CI.yml, we still want to set the defaults values for these parameters
# so that when we are checking the package set for which need to "Build Snippets" or "Check AOT" we won't crash due to the property being null
# so that when we are checking the package set for which need to "Build Snippets"
else {
# No CI.yml found, use IsAotCompatible from csproj for CheckAOTCompat
$pkgProp.CIParameters["CheckAOTCompat"] = $AotCompatOptOut -eq 'false'
$pkgProp.CIParameters["AOTTestInputs"] = @()
$pkgProp.CIParameters["BuildSnippets"] = $true
}

Expand Down
28 changes: 11 additions & 17 deletions eng/scripts/compatibility/Check-AOT-Compatibility-For-PR.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,17 @@ $filteredPackages = Get-ChildItem -Path $PackageInfoFolder -Filter "*.json" -Fil

$failedAotChecks = $false
foreach ($package in $filteredPackages) {
if ($package.CIParameters.CheckAOTCompat) {
Write-Host "Running Check-AOT-Compatibility.ps1 for Package: $($package.ArtifactName) Service $($package.ServiceDirectory)"

# Check if AOTTestInputs exists and has ExpectedWarningsFilePath, otherwise use "None"
$expectedWarningsFilePath = "None"
if ($package.CIParameters.AOTTestInputs -and $package.CIParameters.AOTTestInputs.ExpectedWarningsFilePath) {
$expectedWarningsFilePath = $package.CIParameters.AOTTestInputs.ExpectedWarningsFilePath
}

& $PSScriptRoot/Check-AOT-Compatibility.ps1 `
-PackageName $package.ArtifactName `
-ServiceDirectory $package.ServiceDirectory `
-ExpectedWarningsFilePath $expectedWarningsFilePath

if ($LASTEXITCODE -ne 0) {
$failedAotChecks = $true
}
Write-Host "Running Check-AOT-Compatibility.ps1 for Package: $($package.ArtifactName) Service $($package.ServiceDirectory)"

$scriptPath = Join-Path $PSScriptRoot "Check-AOT-Compatibility.ps1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a place we should consider switching to call the azsdk cli command instead of calling the script directly.

Write-Host "Calling: $scriptPath -ServiceDirectory $($package.ServiceDirectory) -PackageName $($package.ArtifactName)"

& $scriptPath `
-ServiceDirectory $package.ServiceDirectory `
-PackageName $package.ArtifactName

if ($LASTEXITCODE -ne 0) {
$failedAotChecks = $true
}
}

Expand Down
52 changes: 33 additions & 19 deletions eng/scripts/compatibility/Check-AOT-Compatibility.ps1
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
param(
[string]$ServiceDirectory,
[string]$PackageName,
[string]$ExpectedWarningsFilePath,
[string]$DirectoryName = "")
# Path to the csproj file for the package relative to the repository root
[string]$PackagePath)

### Check if AOT compatibility is opted out ###

$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot .. .. ..)
$ProjectPath = Join-Path $RepoRoot $PackagePath
$PackageName = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath)

# Get the property directly from the project file - replicating what the target does
$output = dotnet msbuild -getProperty:AotCompatOptOut "$ProjectPath"

$aotOptOut = $output.Trim() -eq "true"

if ($aotOptOut) {
Write-Host "AOT compatibility is opted out for $PackageName. Skipping AOT compatibility check."
exit 0
}

### Creating a test app ###

Write-Host "Creating a test app to publish."

$expectedWarningsFullPath = Join-Path -Path "..\..\..\..\sdk\$ServiceDirectory\" -ChildPath $ExpectedWarningsFilePath

# Set the project reference path based on whether DirectoryName was provided
if ([string]::IsNullOrEmpty($DirectoryName)) {
$projectRefFullPath = "..\..\..\..\sdk\$ServiceDirectory\$PackageName\src\$PackageName.csproj"
$projectRefFullPath = "..\..\..\..\$PackagePath"
} else {
$projectRefFullPath = "..\..\..\..\sdk\$ServiceDirectory\$DirectoryName\src\$PackageName.csproj"
$projectRefFullPath = "..\..\..\..\$PackagePath"
}

$folderPath = "\TempAotCompatFiles"
Expand Down Expand Up @@ -97,25 +109,24 @@ foreach ($line in $($publishOutput -split "`r`n"))
}
}

Write-Host "There were $actualWarningCount warnings reported."
### Compare to baselined warnings ###

### Reading the contents of the text file path ###
# Baselining warnings is only allowed for two of the Azure.Core.* packages, hard code the file path to the expected
# warnings as a backdoor for those packages.

Write-Host "Reading the list of patterns that represent the list of expected warnings."
$expectedWarningsPath = "..\..\..\..\sdk\core\$PackageName\tests\compatibility\ExpectedAotWarnings.txt"

if (Test-Path $expectedWarningsFullPath -PathType Leaf) {
if (Test-Path $expectedWarningsPath -PathType Leaf) {
# Read the contents of the file and store each line in an array
$expectedWarnings = Get-Content -Path $expectedWarningsFullPath
$expectedWarnings = Get-Content -Path $expectedWarningsPath
} else {
# If no correct expected warnings were provided, check that there are no warnings reported.

Write-Host "The specified file does not exist. Assuming no warnings are expected."

$warnings = $publishOutput -split "`n" | select-string -pattern 'IL\d+' | select-string -pattern '##' -notmatch
$numWarnings = $warnings.Count

if ($numWarnings -gt 0) {
Write-Host "Found $numWarnings additional warnings that were not expected:" -ForegroundColor Red
Write-Host "Found $numWarnings AOT warnings:" -ForegroundColor Red
foreach ($warning in $warnings) {
Write-Host $warning -ForegroundColor Yellow
}
Expand All @@ -127,15 +138,16 @@ if (Test-Path $expectedWarningsFullPath -PathType Leaf) {
Remove-Item -Path "./$folderPath" -Recurse -Force

Write-Host "`nFor help with this check, please see https://github.com/Azure/azure-sdk-for-net/tree/main/doc/dev/AotCompatibility.md"
Write-Host "To see this output locally, run 'eng/scripts/compatibility/Check-AOT-Compatibility.ps1 $PackagePath'"

exit $warnings.Count
}

### Comparing expected warnings to the publish output ###
Write-Host "There were $actualWarningCount warnings reported from the publish."

$numExpectedWarnings = $expectedWarnings.Count

Write-Host "Checking against the list of expected warnings. There are $numExpectedWarnings warnings expected."
Write-Host "There are $numExpectedWarnings warnings expected."

$warnings = $publishOutput -split "`n" | select-string -pattern 'IL\d+' | select-string -pattern '##' -notmatch | select-string -pattern $expectedWarnings -notmatch
$numWarnings = $warnings.Count
Expand All @@ -156,8 +168,10 @@ Remove-Item -Path "./$folderPath" -Recurse -Force
if ($numExpectedWarnings -ne $actualWarningCount) {
Write-Host "The number of expected warnings ($numExpectedWarnings) was different than the actual warning count ($actualWarningCount)."
Write-Host "`nFor help with this check, please see https://github.com/Azure/azure-sdk-for-net/tree/main/doc/dev/AotCompatibility.md"
Write-Host "To run locally, run eng/scripts/compatibility/Check-AOT-Compatibility.ps1 $PackagePath"
exit 2
}

Write-Host "`nFor help with this check, please see https://github.com/Azure/azure-sdk-for-net/tree/main/doc/dev/AotCompatibility.md"
Write-Host "To see this output locally, run 'eng/scripts/compatibility/Check-AOT-Compatibility.ps1 $PackagePath'"
exit $warnings.Count
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<TargetFrameworks>$(RequiredTargetFrameworks)</TargetFrameworks>
<EnableClientSdkAnalyzers>true</EnableClientSdkAnalyzers>
<EnableBannedApiAnalyzers>false</EnableBannedApiAnalyzers>
<AotCompatOptOut>true</AotCompatOptOut>
<AotAnalyzersOptOut>true</AotAnalyzersOptOut>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading
Loading