eng/scripts/Generate-ReleaseNotes.ps1 (191 lines of code) (raw):

[CmdletBinding()] param ( [string]$releasePeriod, [DateTime]$releaseStartDate, [DateTime]$releaseEndDate, [string]$repoLanguage, [string]$commonScriptPath = (Resolve-Path "$PSScriptRoot/../common/scripts"), [string]$releaseDirectory = (Resolve-Path "$PSScriptRoot/../../_data\releases"), [string]$github_pat = $env:GITHUB_PAT ) . (Join-Path $commonScriptPath ChangeLog-Operations.ps1) . (Join-Path $PSScriptRoot PackageList-Helpers.ps1) function GetChangelogBlobLink($packageName, $packageVersion, $packageMetadata) { $sourceUrl = GetLinkTemplateValue $langLinkTemplates "source_url_template" $packageName $packageVersion $packageMetadata.RepoPath if (!$sourceUrl.EndsWith("/")) { $sourceUrl += "/" } $changelogBlobLink = "${sourceUrl}CHANGELOG.md" return $changelogBlobLink } function GetChangeLogContent($changelogBlobLink) { $changelogRawLink = $changelogBlobLink -replace "https://github.com/(.*)/(tree|blob)", "https://raw.githubusercontent.com/`$1" try { Write-Verbose "Pulling $changelogBlobLink" return Invoke-RestMethod -Method GET -Uri $changelogRawLink -MaximumRetryCount 2 } catch { # Skip if the changelog Url is invalid LogWarning "Failed to get content from ${changelogRawLink}" LogWarning "Changelog content will not be collected automatically for $packageName : $packageVersion." return $null } } function GetReleaseNoteEntryContent($packageName, $packageVersion, $changelogContent) { $changeLogEntries = Get-ChangeLogEntriesFromContent -changeLogContent $changelogContent $updatedVersionEntry = $changeLogEntries[$packageVersion] if (!$updatedVersionEntry) { # Skip if the changelog Url is invalid LogWarning "Failed to find matching change log entry from from ${changelogRawLink}" LogWarning "Changelog content will not be collected automatically for $packageName : $packageVersion." return "" } $releaseEntryContent = @() if ($updatedVersionEntry.Sections.Keys.Count -gt 0) { # Keeping both "Key Bugs Fixed" and "Bugs Fixed" for now to give people time to switch based on the recent guideline change $sectionsToPull = @("Features Added","Breaking Changes","Key Bugs Fixed","Bugs Fixed") foreach ($key in $updatedVersionEntry.Sections.Keys) { if ($key -in $sectionsToPull) { $releaseEntryContent += "#### ${key}" $releaseEntryContent += BumpUpMDHeaders -content $updatedVersionEntry.Sections[$key] } } } if (($releaseEntryContent.Count -eq 0) -and $updatedVersionEntry.ReleaseContent) { # Bumping all MD headers by one level to fit in with the release template structure. $releaseEntryContent += BumpUpMDHeaders -content $updatedVersionEntry.ReleaseContent } return $releaseEntryContent } function GetReleaseNotesData($packageName, $packageVersion, $packageMetadata) { $releaseEntryContent = "" $changelogBlobLink = GetChangelogBlobLink $packageName $packageVersion $packageMetadata $isSpring = ($packageMetadata.Type -eq "spring" -and $packageMetadata.RepoPath -eq "spring") $isMgmt = ($packageMetadata.Type -eq "mgmt") if ($isSpring) { # Spring libraries have a shared changelog so use that shared link $changelogBlobLink = $changelogBlobLink -replace "$packageName/CHANGELOG.md", "CHANGELOG.md" } $changelogRawContent = GetChangeLogContent $changelogBlobLink # If we cannot get the changelog content then we should not add this package to release notes if ($null -eq $changelogRawContent) { return $null } # Don't include the changelog content for mgmt or spring libraries as they are mostly autogenerated # and cause more noise then value in our release notes. People can simply use the changlog link. if (!$isMgmt -and !$isSpring) { $releaseEntryContent = GetReleaseNoteEntryContent $packageName $packageVersion $changelogRawContent } $packageSemVer = [AzureEngSemanticVersion]::ParseVersionString($packageVersion) $entry = [ordered]@{ Name = $packageName Version = $packageVersion DisplayName = $packageMetadata.DisplayName ServiceName = $packageMetadata.ServiceName VersionType = $packageSemVer.VersionType Hidden = $false ChangelogUrl = $changelogBlobLink ChangelogContent = ($releaseEntryContent | % { $_.Trim() } | Out-String).Trim() } if (!$entry.DisplayName) { $entry.DisplayName = $entry.Name } if ($packageMetadata.PSObject.Members.Name -contains "GroupId") { $entry.Add("GroupId", $packageMetadata.GroupId) } return $entry } function BumpUpMDHeaders($content) { $result = @() foreach ($line in $content) { if ($line.StartsWith("#")) { $line = "#${line}" } $result += $line } return $result } $pathToRelatedYaml = (Join-Path $ReleaseDirectory $releasePeriod "${repoLanguage}.yml") LogDebug "Related Yaml File Path [ $pathToRelatedYaml ]" if (Test-Path $pathToRelatedYaml) { $yamlContent = Get-Content $pathToRelatedYaml -Raw } else { $yamlContent = "entries:" } # Install Powershell Yaml $ProgressPreference = "SilentlyContinue" $ToolsFeed = "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-tools/nuget/v2" Register-PSRepository -Name azure-sdk-tools-feed -SourceLocation $ToolsFeed -PublishLocation $ToolsFeed -InstallationPolicy Trusted -ErrorAction SilentlyContinue Install-Module -Repository azure-sdk-tools-feed powershell-yaml $existingYamlContent = ConvertFrom-Yaml $yamlContent -Ordered if (!$existingYamlContent.entries) { $existingYamlContent.entries = New-Object "System.Collections.Generic.List[System.Collections.Specialized.OrderedDictionary]" } $langLinkTemplates = GetLinkTemplates $repoLanguage $updatedPackageSet = GetPackageVersions $repoLanguage $releaseStartDate $languageMetadata = Get-PackageLookupForLanguage $repoLanguage foreach ($packageName in $updatedPackageSet.Keys) { Write-Verbose "Checking release notes for $packageName" $pkgKey = $packageName $pkgMetadata = $languageMetadata[$pkgKey] if (!$pkgMetadata) { Write-Host "Skipped package '$pkgKey' because it doesn't contain metadata in the csv file." continue } if ($pkgMetadata.New -ne "true" -or $pkgMetadata.Hide -eq "true") { Write-Host "Skipped package '$pkgKey' because it is not new ($($pkgMetadata.Hide)) or it is marked as hidden ($($pkgMetadata.Hide))" continue } foreach ($packageVersion in $updatedPackageSet[$packageName].Versions) { if ($releaseEndDate -and $packageVersion.Date -gt $releaseEndDate) { Write-Host "Skipped package '$packageName' because it '$($packageVersion.Date)' > '$releaseEndDate'" continue } $presentKey = $existingYamlContent.entries.Where({ ($_.name -eq $packageName) -and ($_.version -eq $packageVersion.RawVersion) }) if ($presentKey.Count -eq 0) { $entry = GetReleaseNotesData $packageName $packageVersion.RawVersion $pkgMetadata if ($entry) { Write-Host "Added '$pkgKey' to the release note entries" $existingYamlContent.entries += $entry } } } } if ($existingYamlContent.entries.Count -gt 0) { Write-Host "Writing release notes for $repoLanguage to $pathToRelatedYaml" $yamlDirectory = Split-Path $pathToRelatedYaml -Parent if (!(Test-Path $yamlDirectory)) { New-Item -Type Directory $yamlDirectory > $null } Set-Content -Path $pathToRelatedYaml -Value (ConvertTo-Yaml $existingYamlContent) } else { Write-Host "No release notes for $repoLanguage so not writing $pathToRelatedYaml" }