diff --git a/eng/versioning/pom_file_version_scanner.ps1 b/eng/versioning/pom_file_version_scanner.ps1 index abd51df74541..5586664d8d58 100644 --- a/eng/versioning/pom_file_version_scanner.ps1 +++ b/eng/versioning/pom_file_version_scanner.ps1 @@ -32,6 +32,13 @@ # Since we're skipping Management for the moment, only look for files with certain parents. These # limitations will vanish once Management track is updated. $ValidParents = ("azure-sdk-parent", "azure-client-sdk-parent", "azure-data-sdk-parent", "azure-cosmos-parent") + +# SpringSampleParents is necessary for the spring samples which have to build using the spring-boot-starter-parent BOM. +# The problem with this is, it's a BOM file and the spring dependencies are pulled in through that which means any +# dependencies may or may not have versions. Unfortunately, there are still version tags azure sdk client libraries +# which means these files have to be "sort of" scanned. +$SpringSampleParents = ("spring-boot-starter-parent") + $Path = Resolve-Path ($PSScriptRoot + "/../../") # Not all POM files have a parent entry @@ -248,6 +255,107 @@ function Confirm-Node-Is-Part-Of-Configuration { return $false } +# Spring samples will pull in most dependencies through use of the spring bom. Any dependency that is an +# an azure sdk client dependency needs to be verified and must have a groupId, artifactId, version and version tag. +# Similarly, any dependency with a version needs to have a version tag. Dependencies without a version tag are +# ignored as those are assumed to be coming from the BOM. +function Assert-Spring-Sample-Version-Tags { + param( + [hashtable]$libHash, + [hashtable]$extDepHash, + [xml]$xmlPomFile + ) + Write-Host "processing Spring Sample pomFile=$($pomFile)" + $xmlNsManagerSpring = New-Object -TypeName "Xml.XmlNamespaceManager" -ArgumentList $xmlPomFile.NameTable + $xmlNsManagerSpring.AddNamespace("ns", $xmlPomFile.DocumentElement.NamespaceURI) + + if (-not $xmlPomFile.project.parent.groupId) + { + $script:FoundError = $true + Write-Error-With-Color "Error: parent/groupId is missing." + } + + $versionNode = $xmlPomFile.SelectSingleNode("/ns:project/ns:parent/ns:version", $xmlNsManagerSpring) + if (-not $versionNode) + { + $script:FoundError = $true + Write-Error-With-Color "Error: parent/version is missing." + Write-Error-With-ColorWrite-Error-With-Color "Error: Missing project/version update tag. The tag should be " + } else { + $retVal = Test-Dependency-Tag-And-Version $libHash $extDepHash $versionNode.InnerText.Trim() $versionNode.NextSibling.Value + if ($retVal) + { + $script:FoundError = $true + Write-Error-With-Color "$($retVal)" + } + } + + # Loop through the dependencies. If any dependency is in the libHash (aka, the libraries we build) + # then it needs to have a version element and update tag. + foreach($dependencyNode in $xmlPomFile.GetElementsByTagName("dependency")) + { + $artifactId = $dependencyNode.artifactId + $groupId = $dependencyNode.groupId + # If the artifactId and groupId are both empty then check to see if this + # is part of a configuration entry. If so then just continue. + if (!$artifactId -and !$groupId) + { + $isPartOfConfig = Confirm-Node-Is-Part-Of-Configuration $dependencyNode + if (!$isPartOfConfig) + { + $script:FoundError = $true + # Because this particular case is harder to track down, print the OuterXML which is effectively the entire tag + Write-Error-With-Color "Error: dependency is missing version element and/or artifactId and groupId elements dependencyNode=$($dependencyNode.OuterXml)" + } + continue + } + $hashKey = "$($groupId):$($artifactId)" + $versionNode = $dependencyNode.GetElementsByTagName("version")[0] + # If this is something we build and release, it better have a version and a version tag + if ($libHash.ContainsKey($hashKey)) + { + if (-not $versionNode) + { + $script:FoundError = $true + Write-Error-With-Color "Error: dependency is missing version element and tag groupId=$($groupId), artifactId=$($artifactId) should be " + } else { + # verify the version tag and version are correct + if ($versionNode.NextSibling -and $versionNode.NextSibling.NodeType -eq "Comment") + { + $retVal = Test-Dependency-Tag-And-Version $libHash $extDepHash $versionNode.InnerText.Trim() $versionNode.NextSibling.Value + if ($retVal) + { + $script:FoundError = $true + Write-Error-With-Color "$($retVal)" + } + } else { + $script:FoundError = $true + Write-Error-With-Color "Error: dependency is missing version tag groupId=$($groupId), artifactId=$($artifactId) tag should be " + } + } + } else { + # else, if there's a version tag verify it, otherwise just skip it since the version should be coming + # from the bom + if ($versionNode) + { + if ($versionNode.NextSibling -and $versionNode.NextSibling.NodeType -eq "Comment") + { + $retVal = Test-Dependency-Tag-And-Version $libHash $extDepHash $versionNode.InnerText.Trim() $versionNode.NextSibling.Value + if ($retVal) + { + $script:FoundError = $true + Write-Error-With-Color "$($retVal)" + } + # If there's no version tag then error, if there's a version then it must be tagged + } else { + $script:FoundError = $true + Write-Error-With-Color "Error: dependency is missing version tag groupId=$($groupId), artifactId=$($artifactId) tag should be " + } + } + } + } +} + # Create one dependency hashtable for libraries we build (the groupIds will make the entries unique) and # one hash for external dependencies $libHash = @{} @@ -279,6 +387,10 @@ Get-ChildItem -Path $Path -Filter pom*.xml -Recurse -File | ForEach-Object { $xmlPomFile.Load($pomFile) if ($ValidParents -notcontains $xmlPomFile.project.parent.artifactId) { + if ($SpringSampleParents -contains $xmlPomFile.project.parent.artifactId) + { + Assert-Spring-Sample-Version-Tags $libHash $extDepHash $xmlPomFile + } # This may look odd but ForEach-Object is a cmdlet which means that "continue" # exits the loop altogether and "return" behaves like continue for a particular # loop @@ -613,4 +725,3 @@ if ($script:FoundError) Write-Error-With-Color "This script can be run locally from the root of the repo. .\eng\versioning\pom_file_version_scanner.ps1" exit(1) } -