diff --git a/_data/sidebars/releases_sidebar.yml b/_data/sidebars/releases_sidebar.yml
index 343483a8edde..bd8f8686aa75 100644
--- a/_data/sidebars/releases_sidebar.yml
+++ b/_data/sidebars/releases_sidebar.yml
@@ -57,158 +57,229 @@ entries:
url: /releases/2025-07/index.html
- title: June
url: /releases/2025-06/index.html
+ archived: true
- title: May
url: /releases/2025-05/index.html
+ archived: true
- title: April
url: /releases/2025-04/index.html
+ archived: true
- title: March
url: /releases/2025-03/index.html
+ archived: true
- title: February
url: /releases/2025-02/index.html
+ archived: true
- title: January
url: /releases/2025-01/index.html
+ archived: true
- title: 2024 Releases
folderitems:
- title: November
url: /releases/2024-11/index.html
+ archived: true
- title: October
url: /releases/2024-10/index.html
+ archived: true
- title: September
url: /releases/2024-09/index.html
+ archived: true
- title: August
url: /releases/2024-08/index.html
+ archived: true
- title: July
url: /releases/2024-07/index.html
+ archived: true
- title: June
url: /releases/2024-06/index.html
+ archived: true
- title: May
url: /releases/2024-05/index.html
+ archived: true
- title: April
url: /releases/2024-04/index.html
+ archived: true
- title: March
url: /releases/2024-03/index.html
+ archived: true
- title: February
url: /releases/2024-02/index.html
+ archived: true
- title: January
url: /releases/2024-01/index.html
+ archived: true
- title: 2023 Releases
folderitems:
- title: December
url: /releases/2023-12/index.html
+ archived: true
- title: November
url: /releases/2023-11/index.html
+ archived: true
- title: October
url: /releases/2023-10/index.html
+ archived: true
- title: September
url: /releases/2023-09/index.html
+ archived: true
- title: August
url: /releases/2023-08/index.html
+ archived: true
- title: July
url: /releases/2023-07/index.html
+ archived: true
- title: June
url: /releases/2023-06/index.html
+ archived: true
- title: May
url: /releases/2023-05/index.html
+ archived: true
- title: April
url: /releases/2023-04/index.html
+ archived: true
- title: March
url: /releases/2023-03/index.html
+ archived: true
- title: February
url: /releases/2023-02/index.html
+ archived: true
- title: January
url: /releases/2023-01/index.html
+ archived: true
- title: 2022 Releases
folderitems:
- title: December
url: /releases/2022-12/index.html
+ archived: true
- title: November
url: /releases/2022-11/index.html
+ archived: true
- title: October
url: /releases/2022-10/index.html
+ archived: true
- title: September
url: /releases/2022-09/index.html
+ archived: true
- title: August
url: /releases/2022-08/index.html
+ archived: true
- title: July
url: /releases/2022-07/index.html
+ archived: true
- title: June
url: /releases/2022-06/index.html
+ archived: true
- title: May
url: /releases/2022-05/index.html
+ archived: true
- title: April
url: /releases/2022-04/index.html
+ archived: true
- title: March
url: /releases/2022-03/index.html
+ archived: true
- title: February
url: /releases/2022-02/index.html
+ archived: true
- title: January
url: /releases/2022-01/index.html
+ archived: true
- title: 2021 Releases
folderitems:
- title: December
url: /releases/2021-12/index.html
+ archived: true
- title: November
url: /releases/2021-11/index.html
+ archived: true
- title: October
url: /releases/2021-10/index.html
+ archived: true
- title: September
url: /releases/2021-09/index.html
+ archived: true
- title: August
url: /releases/2021-08/index.html
+ archived: true
- title: July
url: /releases/2021-07/index.html
+ archived: true
- title: June
url: /releases/2021-06/index.html
+ archived: true
- title: May
url: /releases/2021-05/index.html
+ archived: true
- title: April
url: /releases/2021-04/index.html
+ archived: true
- title: March
url: /releases/2021-03/index.html
+ archived: true
- title: February
url: /releases/2021-02/index.html
+ archived: true
- title: January
url: /releases/2021-01/index.html
+ archived: true
- title: 2020 Releases
folderitems:
- title: December
url: /releases/2020-12/index.html
+ archived: true
- title: November
url: /releases/2020-11/index.html
+ archived: true
- title: October
url: /releases/2020-10/index.html
+ archived: true
- title: September
url: /releases/2020-09/index.html
+ archived: true
- title: August
url: /releases/2020-08/index.html
+ archived: true
- title: July
url: /releases/2020-07/index.html
+ archived: true
- title: June
url: /releases/2020-06/index.html
+ archived: true
- title: May
url: /releases/2020-05/index.html
+ archived: true
- title: April
url: /releases/2020-04/index.html
+ archived: true
- title: March
url: /releases/2020-03/index.html
+ archived: true
- title: February
url: /releases/2020-02/index.html
+ archived: true
- title: January
url: /releases/2020-01/index.html
+ archived: true
- title: 2019 Releases
folderitems:
- title: December
url: /releases/2019-12/index.html
+ archived: true
- title: November
url: /releases/2019-11/index.html
+ archived: true
- title: October
url: /releases/2019-10-11/index.html
+ archived: true
- title: September
url: /releases/2019-09-17/index.html
+ archived: true
- title: August
url: /releases/2019-08-06/index.html
+ archived: true
- title: July
url: /releases/2019-07-10/index.html
+ archived: true
- title: Deprecated
url: /releases/deprecated/index.html
folderitems:
diff --git a/_includes/sidebar.html b/_includes/sidebar.html
index c20a6fc7e27c..93851bba2dd9 100644
--- a/_includes/sidebar.html
+++ b/_includes/sidebar.html
@@ -29,14 +29,15 @@
{% endif %}
{% for folderitem in folder.folderitems %}
+ {% if folderitem.archived %}{% assign folderitem_title = folderitem.title | append: " (Archived)" %}{% else %}{% assign folderitem_title = folderitem.title %}{% endif %}
{% if folderitem.external_url %}
- - {{folderitem.title}}
+ - {{folderitem_title}}
{% elsif page.url == folderitem.url %}
- - {{folderitem.title}}
+ - {{folderitem_title}}
{% elsif folderitem.type == "empty" %}
- - {{folderitem.title}}
+ - {{folderitem_title}}
{% else %}
- - {{folderitem.title}}
+ - {{folderitem_title}}
{% endif %}
{% for subfolders in folderitem.subfolders %}
-
diff --git a/eng/ignore-links.txt b/eng/ignore-links.txt
index ca799822b3a7..5bc11625c7b2 100644
--- a/eng/ignore-links.txt
+++ b/eng/ignore-links.txt
@@ -2,4 +2,80 @@
https://github.com/Azure/azure-sdk-pr
https://github.com/azure/azure-rest-api-specs-pr
https://github.com/Azure/azure-sdk-pr/blob/main/onboarding/Core_Concepts.pdf
-https://github.com/Azure/azure-sdk-pr/blob/24384df0202021ab86ee37fcb14e9554182cd014/training/azure-sdk-apis/principles/approachable/README.md
\ No newline at end of file
+https://github.com/Azure/azure-sdk-pr/blob/24384df0202021ab86ee37fcb14e9554182cd014/training/azure-sdk-apis/principles/approachable/README.md
+
+# BEGIN auto-generated archived release notes (managed by eng/scripts/Generate-Release-Structure.ps1)
+# Release notes older than 12 months. They stay available on the site but
+# are excluded from link verification so outdated links in old notes don't fail CI.
+/azure-sdk/releases/2019-07-10/index.html
+/azure-sdk/releases/2019-08-06/index.html
+/azure-sdk/releases/2019-09-17/index.html
+/azure-sdk/releases/2019-10-11/index.html
+/azure-sdk/releases/2019-11/index.html
+/azure-sdk/releases/2019-12/index.html
+/azure-sdk/releases/2020-01/index.html
+/azure-sdk/releases/2020-02/index.html
+/azure-sdk/releases/2020-03/index.html
+/azure-sdk/releases/2020-04/index.html
+/azure-sdk/releases/2020-05/index.html
+/azure-sdk/releases/2020-06/index.html
+/azure-sdk/releases/2020-07/index.html
+/azure-sdk/releases/2020-08/index.html
+/azure-sdk/releases/2020-09/index.html
+/azure-sdk/releases/2020-10/index.html
+/azure-sdk/releases/2020-11/index.html
+/azure-sdk/releases/2020-12/index.html
+/azure-sdk/releases/2021-01/index.html
+/azure-sdk/releases/2021-02/index.html
+/azure-sdk/releases/2021-03/index.html
+/azure-sdk/releases/2021-04/index.html
+/azure-sdk/releases/2021-05/index.html
+/azure-sdk/releases/2021-06/index.html
+/azure-sdk/releases/2021-07/index.html
+/azure-sdk/releases/2021-08/index.html
+/azure-sdk/releases/2021-09/index.html
+/azure-sdk/releases/2021-10/index.html
+/azure-sdk/releases/2021-11/index.html
+/azure-sdk/releases/2021-12/index.html
+/azure-sdk/releases/2022-01/index.html
+/azure-sdk/releases/2022-02/index.html
+/azure-sdk/releases/2022-03/index.html
+/azure-sdk/releases/2022-04/index.html
+/azure-sdk/releases/2022-05/index.html
+/azure-sdk/releases/2022-06/index.html
+/azure-sdk/releases/2022-07/index.html
+/azure-sdk/releases/2022-08/index.html
+/azure-sdk/releases/2022-09/index.html
+/azure-sdk/releases/2022-10/index.html
+/azure-sdk/releases/2022-11/index.html
+/azure-sdk/releases/2022-12/index.html
+/azure-sdk/releases/2023-01/index.html
+/azure-sdk/releases/2023-02/index.html
+/azure-sdk/releases/2023-03/index.html
+/azure-sdk/releases/2023-04/index.html
+/azure-sdk/releases/2023-05/index.html
+/azure-sdk/releases/2023-06/index.html
+/azure-sdk/releases/2023-07/index.html
+/azure-sdk/releases/2023-08/index.html
+/azure-sdk/releases/2023-09/index.html
+/azure-sdk/releases/2023-10/index.html
+/azure-sdk/releases/2023-11/index.html
+/azure-sdk/releases/2023-12/index.html
+/azure-sdk/releases/2024-01/index.html
+/azure-sdk/releases/2024-02/index.html
+/azure-sdk/releases/2024-03/index.html
+/azure-sdk/releases/2024-04/index.html
+/azure-sdk/releases/2024-05/index.html
+/azure-sdk/releases/2024-06/index.html
+/azure-sdk/releases/2024-07/index.html
+/azure-sdk/releases/2024-08/index.html
+/azure-sdk/releases/2024-09/index.html
+/azure-sdk/releases/2024-10/index.html
+/azure-sdk/releases/2024-11/index.html
+/azure-sdk/releases/2025-01/index.html
+/azure-sdk/releases/2025-02/index.html
+/azure-sdk/releases/2025-03/index.html
+/azure-sdk/releases/2025-04/index.html
+/azure-sdk/releases/2025-05/index.html
+/azure-sdk/releases/2025-06/index.html
+# END auto-generated archived release notes
diff --git a/eng/scripts/Generate-Release-Structure.ps1 b/eng/scripts/Generate-Release-Structure.ps1
index 0f1e4d2e1ce6..956306787c80 100644
--- a/eng/scripts/Generate-Release-Structure.ps1
+++ b/eng/scripts/Generate-Release-Structure.ps1
@@ -7,6 +7,109 @@ param (
[string[]]$ExcludeFileNames = @()
)
+# Markers that delimit the auto-generated list of archived release note pages in
+# the ignore-links file. Everything between these markers is regenerated by
+# Update-ArchivedReleaseNotes so it can be kept in sync automatically.
+$script:ArchivedReleasesBeginMarker = "# BEGIN auto-generated archived release notes (managed by eng/scripts/Generate-Release-Structure.ps1)"
+$script:ArchivedReleasesEndMarker = "# END auto-generated archived release notes"
+
+# Parse the year/month a release note page represents from its sidebar url.
+# Returns the first-of-month DateTime, or $null if the url is not a monthly release page.
+function Get-ReleaseMonthFromReleaseUrl($url)
+{
+ if ($url -match "^/releases/(?\d{4})-(?\d{2})(?:-\d{2})?/index\.html$") {
+ return [DateTime]::new([int]$matches["year"], [int]$matches["month"], 1)
+ }
+ return $null
+}
+
+# Marks monthly release notes older than $monthsToKeep as archived in the sidebar and
+# regenerates the managed block of archived release note urls in the ignore-links file so
+# that link verification skips (and does not recurse into) release notes older than the
+# rolling window. Older notes remain reachable on the site; they are just not verified.
+# Operates purely on text so it works regardless of how the yaml file was formatted.
+function Update-ArchivedReleaseNotes
+{
+ param(
+ [Parameter(Mandatory = $true)][string]$sidebarPath,
+ [Parameter(Mandatory = $true)][string]$ignoreLinksPath,
+ [DateTime]$referenceDate = [DateTime]::Now,
+ [int]$monthsToKeep = 12,
+ [string]$siteBaseUrl = "/azure-sdk"
+ )
+
+ # Anything strictly older than the first day of the month, $monthsToKeep months ago, is archived.
+ $cutoff = [DateTime]::new($referenceDate.Year, $referenceDate.Month, 1).AddMonths(-$monthsToKeep)
+
+ $lines = @(Get-Content -LiteralPath $sidebarPath)
+ $newLines = new-object "System.Collections.Generic.List[string]"
+ $archivedUrls = new-object "System.Collections.Generic.List[string]"
+
+ for ($i = 0; $i -lt $lines.Count; $i++) {
+ $line = $lines[$i]
+ $newLines.Add($line)
+
+ if ($line -match "^(?\s*)url:\s*[""']?(?/releases/\S+?/index\.html)[""']?\s*$") {
+ $indent = $matches["indent"]
+ $url = $matches["url"]
+ $releaseMonth = Get-ReleaseMonthFromReleaseUrl $url
+
+ if ($releaseMonth) {
+ # Consume an existing archived marker (if any) so we can recompute it.
+ if (($i + 1) -lt $lines.Count -and $lines[$i + 1] -match "^\s*archived:\s*(true|false)\s*$") {
+ $i++
+ }
+
+ if ($releaseMonth -lt $cutoff) {
+ $newLines.Add("$($indent)archived: true")
+ $archivedUrls.Add("$siteBaseUrl$url")
+ }
+ }
+ }
+ }
+
+ Set-Content -LiteralPath $sidebarPath -Value $newLines -NoNewline:$false
+
+ $sortedArchivedUrls = $archivedUrls | Sort-Object -Unique
+
+ # Rebuild the ignore-links file keeping everything outside the managed block untouched.
+ $ignoreLines = @(Get-Content -LiteralPath $ignoreLinksPath)
+ $staticLines = new-object "System.Collections.Generic.List[string]"
+ $inManagedBlock = $false
+ foreach ($ignoreLine in $ignoreLines) {
+ if ($ignoreLine -eq $script:ArchivedReleasesBeginMarker) { $inManagedBlock = $true; continue }
+ if ($ignoreLine -eq $script:ArchivedReleasesEndMarker) { $inManagedBlock = $false; continue }
+ if (!$inManagedBlock) { $staticLines.Add($ignoreLine) }
+ }
+
+ # Trim trailing blank lines from the static portion so we control the spacing.
+ while ($staticLines.Count -gt 0 -and $staticLines[$staticLines.Count - 1].Trim() -eq "") {
+ $staticLines.RemoveAt($staticLines.Count - 1)
+ }
+
+ $outputLines = new-object "System.Collections.Generic.List[string]"
+ $outputLines.AddRange($staticLines)
+
+ if ($sortedArchivedUrls.Count -gt 0) {
+ $outputLines.Add("")
+ $outputLines.Add($script:ArchivedReleasesBeginMarker)
+ $outputLines.Add("# Release notes older than $monthsToKeep months. They stay available on the site but")
+ $outputLines.Add("# are excluded from link verification so outdated links in old notes don't fail CI.")
+ foreach ($archivedUrl in $sortedArchivedUrls) {
+ $outputLines.Add($archivedUrl)
+ }
+ $outputLines.Add($script:ArchivedReleasesEndMarker)
+ }
+
+ Set-Content -LiteralPath $ignoreLinksPath -Value $outputLines
+
+ Write-Host "Marked $($sortedArchivedUrls.Count) release note page(s) older than $monthsToKeep months as archived (cutoff $($cutoff.ToString('yyyy-MM')))."
+}
+
+# When dot-sourced (e.g. to reuse the functions above) stop here without running the
+# folder/sidebar generation below.
+if ($MyInvocation.InvocationName -eq '.') { return }
+
if ($releaseDateString -eq "") {
$releaseDate = [DateTime]::Now
}
@@ -45,7 +148,12 @@ if ($publishRelease) {
}
$yml | ConvertTo-Yaml -OutFile $releaseSidebar -Force
-
+
+ ### Archive release notes older than the rolling 12-month window so link
+ ### verification only checks recent notes (older notes stay on the site).
+ $ignoreLinksFile = Resolve-Path "$PSScriptRoot\ignore-links.txt"
+ Update-ArchivedReleaseNotes -sidebarPath $releaseSidebar -ignoreLinksPath $ignoreLinksFile -referenceDate $releaseDate
+
# If the release folder exists exit otherwise continue on and create the release folder
if (Test-Path $releaseFolder) {
exit 0