diff --git a/eng/common/pipelines/templates/steps/verify-codeowners.yml b/eng/common/pipelines/templates/steps/verify-codeowners.yml new file mode 100644 index 000000000000..b272329bb375 --- /dev/null +++ b/eng/common/pipelines/templates/steps/verify-codeowners.yml @@ -0,0 +1,32 @@ +parameters: + - name: ArtifactPath + type: string + default: $(Build.ArtifactStagingDirectory)/PackageInfo + - name: Repo + type: string + default: $(Build.Repository.Name) + - name: SdkTypes + type: object + default: + - client + - compat + - data + - functions + - datamovement + +steps: + - template: /eng/common/pipelines/templates/steps/install-azsdk-cli.yml + parameters: + Condition: and(succeeded(), ne(variables['Skip.VerifyCodeowners'], 'true')) + + - task: PowerShell@2 + displayName: Verify Codeowners + condition: and(succeeded(), ne(variables['Skip.VerifyCodeowners'], 'true')) + inputs: + pwsh: true + filePath: $(Build.SourcesDirectory)/eng/common/scripts/Test-CodeownersForArtifacts.ps1 + arguments: >- + -AzsdkPath '$(AZSDK)' + -PackageInfoDirectory '${{ parameters.ArtifactPath }}' + -SdkTypes ${{ join(',', parameters.SdkTypes) }} + -Repo '${{ parameters.Repo }}' diff --git a/eng/common/scripts/Test-CodeownersForArtifacts.ps1 b/eng/common/scripts/Test-CodeownersForArtifacts.ps1 new file mode 100644 index 000000000000..3c83173c21d2 --- /dev/null +++ b/eng/common/scripts/Test-CodeownersForArtifacts.ps1 @@ -0,0 +1,59 @@ +[CmdletBinding()] +param( + [string] $AzsdkPath, + [string] $PackageInfoDirectory, + [array] $SdkTypes, + [string] $Repo +) + +. "$PSScriptRoot/common.ps1" + +Set-StrictMode -Version 3 +$ErrorActionPreference = 'Stop' + +$failedPackages = @() + +foreach ($pkgPropertiesFile in Get-ChildItem -Path $PackageInfoDirectory -Filter '*.json' -File) { + $pkgProperties = Get-Content -Raw -Path $pkgPropertiesFile | ConvertFrom-Json + if ($SdkTypes -notcontains $pkgProperties.SdkType) { + Write-Host "Skipping package: $($pkgProperties.Name) $($pkgProperties.DirectoryPath) because its SdkType '$($pkgProperties.SdkType)' is not in the list of SdkTypes to validate." + continue + } + + Write-Host "Validating codeowners for package: $($pkgProperties.Name) $($pkgProperties.DirectoryPath)" + + if (!$pkgProperties.ReleaseStatus) { + LogError "Package $($pkgProperties.Name) at $($pkgProperties.DirectoryPath) is missing a ReleaseStatus property." + $failedPackages += $pkgProperties.DirectoryPath + continue + } + + # Validate packages with a release date (intended to release) + if ($pkgProperties.ReleaseStatus -ne "Unreleased") { + $output = & $AzsdkPath config codeowners check-package ` + --directory-path $pkgProperties.DirectoryPath ` + --repo $Repo ` + --output json 2>&1 + + if ($LASTEXITCODE) { + LogError "Codeowners validation failed for package: $($pkgProperties.DirectoryPath)" + $output | Write-Host + $failedPackages += $pkgProperties.DirectoryPath + } else { + Write-Host " Codeowners validation succeeded for package: $($pkgProperties.DirectoryPath)" + } + } else { + Write-Host " Skipping CODEOWNERS validation, package is not intended to release." + } +} + +if ($failedPackages.Count -gt 0) { + Write-Host "" + Write-Host "Failed Packages:" + foreach ($directoryPath in $failedPackages) { + LogError " - $directoryPath does not have sufficient code owners coverage" + } + LogError "Codeowners validation failed for one or more packages. See http://aka.ms/azsdk/codeowners for instructions to fix the issue." + exit 1 +} +exit 0