File: Validate-Package.ps1

package info (click to toggle)
python-azure 20250603%2Bgit-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 851,724 kB
  • sloc: python: 7,362,925; ansic: 804; javascript: 287; makefile: 195; sh: 145; xml: 109
file content (253 lines) | stat: -rw-r--r-- 9,077 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#This script is responsible for release preparedness check that's run as part of build pipeline.

[CmdletBinding()]
param (
  [Parameter(Mandatory = $true)]
  [string] $PackageName,
  [Parameter(Mandatory = $true)]
  [string] $ArtifactPath,
  [Parameter(Mandatory=$True)]
  [string] $RepoRoot,
  [Parameter(Mandatory=$True)]
  [string] $APIKey,
  [Parameter(Mandatory=$True)]
  [string] $ConfigFileDir,
  [string] $BuildDefinition,
  [string] $PipelineUrl,
  [string] $APIViewUri,
  [bool] $IsReleaseBuild = $false
)
Set-StrictMode -Version 3

. (Join-Path $PSScriptRoot common.ps1)
. ${PSScriptRoot}\Helpers\ApiView-Helpers.ps1
. ${PSScriptRoot}\Helpers\DevOps-WorkItem-Helpers.ps1

az account show *> $null
if (!$?) {
  Write-Host 'Running az login...'
  az login *> $null
}

az extension show -n azure-devops *> $null
if (!$?){
  az extension add --name azure-devops
} else {
  # Force update the extension to the latest version if it was already installed
  # this is needed to ensure we have the authentication issue fixed from earlier versions
  az extension update -n azure-devops *> $null
}

CheckDevOpsAccess

# Function to validate change log
function ValidateChangeLog($changeLogPath, $versionString, $validationStatus)
{
    try
    {
        $ChangeLogStatus = [PSCustomObject]@{
            IsValid = $false
            Message = ""
        }
        $changeLogFullPath = Join-Path $RepoRoot $changeLogPath
        Write-Host "Path to change log: [$changeLogFullPath]"
        if (Test-Path $changeLogFullPath)
        {
            Confirm-ChangeLogEntry -ChangeLogLocation $changeLogFullPath -VersionString $versionString -ForRelease $true -ChangeLogStatus $ChangeLogStatus -SuppressErrors $true
            $validationStatus.Status = if ($ChangeLogStatus.IsValid) { "Success" } else { "Failed" }
            $validationStatus.Message = $ChangeLogStatus.Message
        }
        else {
            $validationStatus.Status = "Failed"
            $validationStatus.Message = "Change log is not found in [$changeLogPath]. Change log file must be present in package root directory."
        }
    }
    catch
    {
        Write-Host "Current directory: $(Get-Location)"
        $validationStatus.Status = "Failed"
        $validationStatus.Message = $_.Exception.Message
    }
}

# Function to verify API review status
function VerifyAPIReview($packageName, $packageVersion, $language)
{
    $APIReviewValidation = [PSCustomObject]@{
        Name = "API Review Approval"
        Status = "Pending"
        Message = ""
    }
    $PackageNameValidation = [PSCustomObject]@{
        Name = "Package Name Approval"
        Status = "Pending"
        Message = ""
    }

    try
    {
        $apiStatus = [PSCustomObject]@{
            IsApproved = $false
            Details = ""
        }
        $packageNameStatus = [PSCustomObject]@{
            IsApproved = $false
            Details = ""
        }
        Write-Host "Checking API review status for package $packageName with version $packageVersion. language [$language]."
        Check-ApiReviewStatus $packageName $packageVersion $language $APIViewUri $APIKey $apiStatus $packageNameStatus

        Write-Host "API review approval details: $($apiStatus.Details)"
        Write-Host "Package name approval details: $($packageNameStatus.Details)"
        #API review approval status
        $APIReviewValidation.Message = $apiStatus.Details
        $APIReviewValidation.Status = if ($apiStatus.IsApproved) { "Approved" } else { "Pending" }

        # Package name approval status
        $PackageNameValidation.Status = if ($packageNameStatus.IsApproved) { "Approved" } else { "Pending" }
        $PackageNameValidation.Message = $packageNameStatus.Details
    }
    catch
    {
        Write-Warning "Failed to get API review status. Error: $_"
        $PackageNameValidation.Status = "Failed"
        $PackageNameValidation.Message = $_.Exception.Message
        $APIReviewValidation.Status = "Failed"
        $APIReviewValidation.Message = $_.Exception.Message
    }

    return [PSCustomObject]@{
        ApiviewApproval = $APIReviewValidation
        PackageNameApproval = $PackageNameValidation
    }
}


function IsVersionShipped($packageName, $packageVersion)
{
    # This function will decide if a package version is already shipped or not
    Write-Host "Checking if a version is already shipped for package $packageName with version $packageVersion."
    $parsedNewVersion = [AzureEngSemanticVersion]::new($packageVersion)
    $versionMajorMinor = "" + $parsedNewVersion.Major + "." + $parsedNewVersion.Minor
    $workItem = FindPackageWorkItem -lang $LanguageDisplayName -packageName $packageName -version $versionMajorMinor -includeClosed $true -outputCommand $false
    if ($workItem)
    {
        # Check if the package version is already shipped
        $shippedVersionSet = ParseVersionSetFromMDField $workItem.fields["Custom.ShippedPackages"]
        if ($shippedVersionSet.ContainsKey($packageVersion)) {
            return $true
        }
    }
    else {
        Write-Host "No work item found for package [$packageName]. Creating new work item for package."
    }
    return $false
}

function CreateUpdatePackageWorkItem($pkgInfo)
{
    # This function will create or update package work item in Azure DevOps
    $versionString = $pkgInfo.Version
    $packageName = $pkgInfo.Name
    $plannedDate = $pkgInfo.ReleaseStatus
    $setReleaseState = $true
    if (!$plannedDate -or $plannedDate -eq "Unreleased")
    {
        $setReleaseState = $false
        $plannedDate = "unknown"
    }

    # Create or update package work item
    &$EngCommonScriptsDir/Update-DevOps-Release-WorkItem.ps1 `
        -language $LanguageDisplayName `
        -packageName $packageName `
        -version $versionString `
        -plannedDate $plannedDate `
        -packageRepoPath $pkgInfo.serviceDirectory `
        -packageType $pkgInfo.SDKType `
        -packageNewLibrary $pkgInfo.IsNewSDK `
        -serviceName "unknown" `
        -packageDisplayName "unknown" `
        -inRelease $IsReleaseBuild

    if ($LASTEXITCODE -ne 0)
    {
        Write-Host "Update of the Devops Release WorkItem failed."
        return $false
    }
    return $true
}

# Read package property file and identify all packages to process
Write-Host "Processing artifact: $PackageName"
Write-Host "Is Release Build: $IsReleaseBuild"
$packagePropertyFile = Join-Path $ConfigFileDir "$PackageName.json"
$pkgInfo = Get-Content $packagePropertyFile | ConvertFrom-Json
$pkgName = $pkgInfo.Name
$changeLogPath = $pkgInfo.ChangeLogPath
$versionString = $pkgInfo.Version
Write-Host "Checking if we need to create or update work item for package $pkgName with version $versionString."
$isShipped = IsVersionShipped $pkgName $versionString
if ($isShipped) {
    Write-Host "Package work item already exists for version [$versionString] that is marked as shipped. Skipping the update of package work item."
    exit 0
}

Write-Host "Validating package $pkgName with version $versionString."

# Change log validation
$changeLogStatus = [PSCustomObject]@{
    Name = "Change Log Validation"
    Status = "Success"
    Message = ""
}
ValidateChangeLog $changeLogPath $versionString $changeLogStatus

# API review and package name validation
$fulPackageName = $pkgName
$groupId = $null
if ($pkgInfo.PSObject.Members.Name -contains "Group") {
    $groupId = $pkgInfo.Group
}
if ($groupId){
    $fulPackageName = "${groupId}:${pkgName}"
}
Write-Host "Checking API review status for package $fulPackageName"
$apireviewDetails = VerifyAPIReview $fulPackageName $pkgInfo.Version $Language

$pkgValidationDetails= [PSCustomObject]@{
    Name = $pkgName
    Version = $pkgInfo.Version
    ChangeLogValidation = $changeLogStatus
    APIReviewValidation = $apireviewDetails.ApiviewApproval
    PackageNameValidation = $apireviewDetails.PackageNameApproval
}

$output = ConvertTo-Json $pkgValidationDetails
Write-Host "Output: $($output)"

# Create json token file in artifact path
$tokenFile = Join-Path $ArtifactPath "$PackageName-Validation.json"
$output | Out-File -FilePath $tokenFile -Encoding utf8

# Create DevOps work item
$updatedWi = CreateUpdatePackageWorkItem $pkgInfo

# Update validation status in package work item
if ($updatedWi) {
    Write-Host "Updating validation status in package work item."
    $updatedWi = UpdateValidationStatus $pkgValidationDetails $BuildDefinition $PipelineUrl
}

# Fail the build if any validation is not successful for a release build
Write-Host "Change log status:" $changelogStatus.Status
Write-Host "API Review status:" $apireviewDetails.ApiviewApproval.Status
Write-Host "Package Name status:" $apireviewDetails.PackageNameApproval.Status

if ($IsReleaseBuild)
{
    if (!$updatedWi -or $changelogStatus.Status -ne "Success" -or $apireviewDetails.ApiviewApproval.Status -ne "Approved" -or $apireviewDetails.PackageNameApproval.Status -ne "Approved") {
        Write-Error "At least one of the Validations above failed for package $pkgName with version $versionString."
        exit 1
    }
}