Skip to content
Open
43 changes: 30 additions & 13 deletions eng/common/scripts/Helpers/DevOps-WorkItem-Helpers.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ function Invoke-Query($fields, $wiql, $output = $true)
return $workItems
}

function BuildHashKeyNoNull()
function BuildHashKeyFromNonNullArgs()
{
$filterNulls = $args | Where-Object { $_ }
# if we had any nulls then return null
if (!$filterNulls -or $args.Count -ne $filterNulls.Count) {
# if we had any non-nulls then return it
if (!$filterNulls) {
return $null
}
return BuildHashKey $args
return BuildHashKey @filterNulls
}

function BuildHashKey()
Expand Down Expand Up @@ -215,16 +215,17 @@ function FindParentWorkItem($serviceName, $packageDisplayName, $outputCommand =
$packageWorkItems = @{}
$packageWorkItemWithoutKeyFields = @{}

function FindLatestPackageWorkItem($lang, $packageName, $outputCommand = $true, $ignoreReleasePlannerTests = $true, $tag = $null)
function FindLatestPackageWorkItem($lang, $packageName, $groupId = $null, $outputCommand = $true, $ignoreReleasePlannerTests = $true, $tag = $null)
{
# Cache all the versions of this package and language work items
$null = FindPackageWorkItem $lang $packageName -includeClosed $true -outputCommand $outputCommand -ignoreReleasePlannerTests $ignoreReleasePlannerTests -tag $tag
$null = FindPackageWorkItem $lang $packageName -includeClosed $true -outputCommand $outputCommand -ignoreReleasePlannerTests $ignoreReleasePlannerTests -tag $tag -groupId $groupId

$latestWI = $null
foreach ($wi in $packageWorkItems.Values)
{
if ($wi.fields["Custom.Language"] -ne $lang) { continue }
if ($wi.fields["Custom.Package"] -ne $packageName) { continue }
if ($groupId -and $wi.fields["Custom.GroupId"] -ne $groupId) { continue }

if (!$latestWI) {
$latestWI = $wi
Expand All @@ -238,9 +239,9 @@ function FindLatestPackageWorkItem($lang, $packageName, $outputCommand = $true,
return $latestWI
}

function FindPackageWorkItem($lang, $packageName, $version, $outputCommand = $true, $includeClosed = $false, $ignoreReleasePlannerTests = $true, $tag = $null)
function FindPackageWorkItem($lang, $packageName, $version, $groupId = $null, $outputCommand = $true, $includeClosed = $false, $ignoreReleasePlannerTests = $true, $tag = $null)
{
$key = BuildHashKeyNoNull $lang $packageName $version
$key = BuildHashKeyFromNonNullArgs $lang $packageName $version $groupId
if ($key -and $packageWorkItems.ContainsKey($key)) {
return $packageWorkItems[$key]
}
Expand All @@ -253,6 +254,7 @@ function FindPackageWorkItem($lang, $packageName, $version, $outputCommand = $tr
$fields += "System.Tags"
$fields += "Custom.Language"
$fields += "Custom.Package"
$fields += "Custom.GroupId"
$fields += "Custom.PackageDisplayName"
$fields += "System.Title"
$fields += "Custom.PackageType"
Expand Down Expand Up @@ -282,6 +284,9 @@ function FindPackageWorkItem($lang, $packageName, $version, $outputCommand = $tr
if ($packageName) {
$query += " AND [Package] = '${packageName}'"
}
if ($groupId) {
$query += " AND [GroupId] = '${groupId}'"
}
if ($version) {
$query += " AND [PackageVersionMajorMinor] = '${version}'"
}
Expand All @@ -295,7 +300,7 @@ function FindPackageWorkItem($lang, $packageName, $version, $outputCommand = $tr

foreach ($wi in $workItems)
{
$localKey = BuildHashKeyNoNull $wi.fields["Custom.Language"] $wi.fields["Custom.Package"] $wi.fields["Custom.PackageVersionMajorMinor"]
$localKey = BuildHashKeyFromNonNullArgs $wi.fields["Custom.Language"] $wi.fields["Custom.Package"] $wi.fields["Custom.PackageVersionMajorMinor"] $wi.fields["Custom.GroupId"]
if (!$localKey) {
$packageWorkItemWithoutKeyFields[$wi.id] = $wi
Write-Host "Skipping package [$($wi.id)]$($wi.fields['System.Title']) which is missing required fields language, package, or version."
Expand Down Expand Up @@ -461,10 +466,10 @@ function UpdatePackageWorkItemReleaseState($id, $state, $releaseType, $outputCom

function FindOrCreateClonePackageWorkItem($lang, $pkg, $verMajorMinor, $allowPrompt = $false, $outputCommand = $false, $relatedId = $null, $tag= $null, $ignoreReleasePlannerTests = $true)
{
$workItem = FindPackageWorkItem -lang $lang -packageName $pkg.Package -version $verMajorMinor -includeClosed $true -outputCommand $outputCommand -tag $tag -ignoreReleasePlannerTests $ignoreReleasePlannerTests
$workItem = FindPackageWorkItem -lang $lang -packageName $pkg.Package -version $verMajorMinor -includeClosed $true -outputCommand $outputCommand -tag $tag -ignoreReleasePlannerTests $ignoreReleasePlannerTests -groupId $pkg.GroupId

if (!$workItem) {
$latestVersionItem = FindLatestPackageWorkItem -lang $lang -packageName $pkg.Package -outputCommand $outputCommand -tag $tag -ignoreReleasePlannerTests $ignoreReleasePlannerTests
$latestVersionItem = FindLatestPackageWorkItem -lang $lang -packageName $pkg.Package -outputCommand $outputCommand -tag $tag -ignoreReleasePlannerTests $ignoreReleasePlannerTests -groupId $pkg.GroupId
$assignedTo = "me"
$extraFields = @()
if ($latestVersionItem) {
Expand Down Expand Up @@ -512,6 +517,13 @@ function CreateOrUpdatePackageWorkItem($lang, $pkg, $verMajorMinor, $existingIte
Write-Host "Cannot create or update because one of lang, pkg or verMajorMinor aren't set. [$lang|$($pkg.Package)|$verMajorMinor]"
return
}

# PackageProp object uses Group, while other places use GroupId, such as in work item fields and package csv files.
$pkgGroupId = if ($pkg.PSObject.Properties.Name -contains "GroupId") {
$pkg.GroupId
} else {
$null
}
$pkgName = $pkg.Package
$pkgDisplayName = $pkg.DisplayName
$pkgType = $pkg.Type
Expand All @@ -523,6 +535,7 @@ function CreateOrUpdatePackageWorkItem($lang, $pkg, $verMajorMinor, $existingIte
$fields = @()
$fields += "`"Language=${lang}`""
$fields += "`"Package=${pkgName}`""
$fields += "`"GroupId=${pkgGroupId}`""
Copy link
Member

Choose a reason for hiding this comment

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

Should we only include this clause if groupId isn't null?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd rather keeping it updated to the input value even if it's null.

$fields += "`"PackageDisplayName=${pkgDisplayName}`""
$fields += "`"PackageType=${pkgType}`""
$fields += "`"PackageTypeNewLibrary=${pkgNewLibrary}`""
Expand All @@ -540,6 +553,7 @@ function CreateOrUpdatePackageWorkItem($lang, $pkg, $verMajorMinor, $existingIte

if ($lang -ne $existingItem.fields["Custom.Language"]) { $changedField = "Custom.Language" }
if ($pkgName -ne $existingItem.fields["Custom.Package"]) { $changedField = "Custom.Package" }
if ($pkgGroupId -ne $existingItem.fields["Custom.GroupId"]) { $changedField = "Custom.GroupId" }
if ($verMajorMinor -ne $existingItem.fields["Custom.PackageVersionMajorMinor"]) { $changedField = "Custom.PackageVersionMajorMinor" }
if ($pkgDisplayName -ne $existingItem.fields["Custom.PackageDisplayName"]) { $changedField = "Custom.PackageDisplayName" }
if ($pkgType -ne [string]$existingItem.fields["Custom.PackageType"]) { $changedField = "Custom.PackageType" }
Expand Down Expand Up @@ -1029,15 +1043,16 @@ function UpdatePackageVersions($pkgWorkItem, $plannedVersions, $shippedVersions)
function UpdateValidationStatus($pkgvalidationDetails, $BuildDefinition, $PipelineUrl)
{
$pkgName = $pkgValidationDetails.Name
$groupId = $pkgValidationDetails.GroupId
$versionString = $pkgValidationDetails.Version

$parsedNewVersion = [AzureEngSemanticVersion]::new($versionString)
$versionMajorMinor = "" + $parsedNewVersion.Major + "." + $parsedNewVersion.Minor
$workItem = FindPackageWorkItem -lang $LanguageDisplayName -packageName $pkgName -version $versionMajorMinor -includeClosed $true -outputCommand $false
$workItem = FindPackageWorkItem -lang $LanguageDisplayName -packageName $pkgName -groupId $groupId -version $versionMajorMinor -includeClosed $true -outputCommand $false

if (!$workItem)
{
Write-Host"No work item found for package [$pkgName]."
Write-Host "No work item found for package [$pkgName] with groupId [$groupId]."
return $false
}

Expand Down Expand Up @@ -1250,6 +1265,7 @@ function Update-DevOpsReleaseWorkItem {
[Parameter(Mandatory=$true)]
[string]$version,
[string]$plannedDate,
[string]$groupId = $null,
[string]$serviceName = $null,
[string]$packageDisplayName = $null,
[string]$packageRepoPath = "NA",
Expand Down Expand Up @@ -1277,6 +1293,7 @@ function Update-DevOpsReleaseWorkItem {

$packageInfo = [PSCustomObject][ordered]@{
Package = $packageName
GroupId = $groupId
DisplayName = $packageDisplayName
ServiceName = $serviceName
RepoPath = $packageRepoPath
Expand Down
47 changes: 44 additions & 3 deletions eng/common/scripts/Package-Properties.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,30 @@ class PackageProps {
# Returns important properties of the package relative to the language repo
# Returns a PS Object with properties @ { pkgName, pkgVersion, pkgDirectoryPath, pkgReadMePath, pkgChangeLogPath }
# Note: python is required for parsing python package properties.
# GroupId is optional and is used to filter packages for languages that support group identifiers (e.g., Java).
# When GroupId is provided, the function will match both the package name and the group ID.
function Get-PkgProperties {
Param
(
[Parameter(Mandatory = $true)]
[string]$PackageName,
[string]$ServiceDirectory
[string]$ServiceDirectory,
[string]$GroupId
)

Write-Host "Get-PkgProperties called with PackageName: [$PackageName], ServiceDirectory: [$ServiceDirectory], GroupId: [$GroupId]"

$allPkgProps = Get-AllPkgProperties -ServiceDirectory $ServiceDirectory
$pkgProps = $allPkgProps.Where({ $_.Name -eq $PackageName -or $_.ArtifactName -eq $PackageName });

if ([string]::IsNullOrEmpty($GroupId)) {
$pkgProps = $allPkgProps.Where({ $_.Name -eq $PackageName -or $_.ArtifactName -eq $PackageName });
}
else {
$pkgProps = $allPkgProps.Where({
($_.Name -eq $PackageName -or $_.ArtifactName -eq $PackageName) -and
($_.PSObject.Properties.Name -contains "Group" -and $_.Group -eq $GroupId)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
($_.PSObject.Properties.Name -contains "Group" -and $_.Group -eq $GroupId)
($_.PSObject.Properties.Name -contains "GroupId" -and $_.GroupId -eq $GroupId)

Copy link
Member

Choose a reason for hiding this comment

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

Nevermind this looks to be a packageprops/info so I guess it would still be Group.

Copy link
Member Author

Choose a reason for hiding this comment

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

The input object comes from the PackageProps type and we have to access it by Group.

});
}

if ($pkgProps.Count -ge 1) {
if ($pkgProps.Count -gt 1) {
Expand All @@ -248,7 +262,12 @@ function Get-PkgProperties {
return $pkgProps[0]
}

LogError "Failed to retrieve Properties for [$PackageName]"
if ([string]::IsNullOrEmpty($GroupId)) {
LogError "Failed to retrieve Properties for [$PackageName]"
}
else {
LogError "Failed to retrieve Properties for [$PackageName] with GroupId [$GroupId]. Ensure the package has a Group property matching the specified GroupId."
}
return $null
}

Expand Down Expand Up @@ -568,3 +587,25 @@ function Get-PkgPropsForEntireService ($serviceDirectoryPath) {

return $projectProps
}

# Get the full package name based on packageInfo properties
# Returns Group+ArtifactName if Group exists and has a value, otherwise returns Name
# If UseColonSeparator switch is enabled, returns Group:ArtifactName format (colon separator)
function Get-FullPackageName {
param (
[Parameter(Mandatory=$true)]
[PSCustomObject]$PackageInfo,
[switch]$UseColonSeparator
)

if ($PackageInfo.PSObject.Members.Name -contains "Group") {
$groupId = $PackageInfo.Group
if ($groupId) {
if ($UseColonSeparator) {
return "${groupId}:$($PackageInfo.Name)"
}
return "${groupId}+$($PackageInfo.Name)"
}
}
return $PackageInfo.Name
}
28 changes: 23 additions & 5 deletions eng/common/scripts/Prepare-Release.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ If one isn't provided, then it will compute the next ship date or today's date i
.PARAMETER ReleaseTrackingOnly
Optional: If this switch is passed then the script will only update the release work items and not update the versions in the local repo or validate the changelog.

.PARAMETER GroupId
Optional: The group ID for the package. For Java packages, if not provided, the script will prompt for input with 'com.azure' as the default.

.EXAMPLE
PS> ./eng/common/scripts/Prepare-Release.ps1 <PackageName>

Expand All @@ -49,14 +52,27 @@ param(
[string]$PackageName,
[string]$ServiceDirectory,
[string]$ReleaseDate, # Pass Date in the form MM/dd/yyyy"
[switch]$ReleaseTrackingOnly = $false
[switch]$ReleaseTrackingOnly = $false,
[string]$GroupId
)
Set-StrictMode -Version 3

. ${PSScriptRoot}\common.ps1
. ${PSScriptRoot}\Helpers\ApiView-Helpers.ps1
. ${PSScriptRoot}\Helpers\DevOps-WorkItem-Helpers.ps1

# Prompt for GroupId if language is Java and GroupId is not provided
if ($Language -eq 'java' -and [string]::IsNullOrEmpty($GroupId)) {
$userInput = Read-Host "Input the group id, or press Enter to use 'com.azure' as the group id"
if ([string]::IsNullOrWhiteSpace($userInput)) {
$GroupId = "com.azure"
}
else {
$GroupId = $userInput.Trim()
}
Write-Host "Using GroupId: $GroupId" -ForegroundColor Green
}

function Get-ReleaseDay($baseDate)
{
# Find first friday
Expand All @@ -74,7 +90,7 @@ function Get-ReleaseDay($baseDate)
$ErrorPreference = 'Stop'

$packageProperties = $null
$packageProperties = Get-PkgProperties -PackageName $PackageName -ServiceDirectory $ServiceDirectory
$packageProperties = Get-PkgProperties -PackageName $PackageName -ServiceDirectory $ServiceDirectory -GroupId $GroupId

if (!$packageProperties)
{
Expand Down Expand Up @@ -128,7 +144,7 @@ if (Test-Path "Function:GetExistingPackageVersions")
}

$currentProjectVersion = $packageProperties.Version
$newVersion = Read-Host -Prompt "Input the new version, or press Enter to use use current project version '$currentProjectVersion'"
$newVersion = Read-Host -Prompt "Input the new version, or press Enter to use current project version '$currentProjectVersion'"

if (!$newVersion)
{
Expand All @@ -144,6 +160,7 @@ if ($null -eq $newVersionParsed)

$result = Update-DevOpsReleaseWorkItem -language $LanguageDisplayName `
-packageName $packageProperties.Name `
-groupId $packageProperties.Group `
-version $newVersion `
-plannedDate $releaseDateString `
-packageRepoPath $packageProperties.serviceDirectory `
Expand All @@ -166,7 +183,8 @@ try
}
$url = az keyvault secret show --name "APIURL" --vault-name "AzureSDKPrepRelease-KV" --query "value" --output "tsv"
$apiKey = az keyvault secret show --name "APIKEY" --vault-name "AzureSDKPrepRelease-KV" --query "value" --output "tsv"
Check-ApiReviewStatus -PackageName $packageProperties.Name -packageVersion $newVersion -Language $LanguageDisplayName -url $url -apiKey $apiKey
$fullPackageNameInApiView = Get-FullPackageName -PackageInfo $packageProperties -UseColonSeparator
Check-ApiReviewStatus -PackageName $fullPackageNameInApiView -packageVersion $newVersion -Language $LanguageDisplayName -url $url -apiKey $apiKey
}
catch
{
Expand Down Expand Up @@ -194,7 +212,7 @@ if (Test-Path "Function:SetPackageVersion")
}
SetPackageVersion -PackageName $packageProperties.Name -Version $newVersion `
-ServiceDirectory $packageProperties.ServiceDirectory -ReleaseDate $releaseDateString `
-PackageProperties $packageProperties -ReplaceLatestEntryTitle $replaceLatestEntryTitle
-PackageProperties $packageProperties -ReplaceLatestEntryTitle $replaceLatestEntryTitle -GroupId $packageProperties.Group
}
else
{
Expand Down
6 changes: 4 additions & 2 deletions eng/common/scripts/Update-ChangeLog.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# Version : Version to add or replace in change log
# Unreleased: Default is true. If it is set to false, then today's date will be set in verion title. If it is True then title will show "Unreleased"
# ReplaceLatestEntryTitle: Replaces the latest changelog entry title.
# GroupId: Optional. The group ID for the package. Used for filtering packages in languages that support group identifiers (e.g., Java).

[CmdletBinding()]
param (
Expand All @@ -14,7 +15,8 @@ param (
[Boolean]$Unreleased = $true,
[Boolean]$ReplaceLatestEntryTitle = $false,
[String]$ChangelogPath,
[String]$ReleaseDate
[String]$ReleaseDate,
[String]$GroupId
)
Set-StrictMode -Version 3

Expand Down Expand Up @@ -59,7 +61,7 @@ if ($null -eq [AzureEngSemanticVersion]::ParseVersionString($Version))

if ([string]::IsNullOrEmpty($ChangelogPath))
{
$pkgProperties = Get-PkgProperties -PackageName $PackageName -ServiceDirectory $ServiceDirectory
$pkgProperties = Get-PkgProperties -PackageName $PackageName -ServiceDirectory $ServiceDirectory -GroupId $GroupId
$ChangelogPath = $pkgProperties.ChangeLogPath
}

Expand Down
Loading