Skip to content

Commit e8e3e0c

Browse files
azure-sdkCopilotweshaggardCopilot
authored
Sync eng/common directory with azure-sdk-tools for PR 14400 (#48356)
* Allow relative links in configurable file paths via allowRelativeLinksFile parameter Co-authored-by: weshaggard <9010698+weshaggard@users.noreply.github.com> * Only lift relative-link restriction for matching pages, keep other guidance checks active Co-authored-by: weshaggard <9010698+weshaggard@users.noreply.github.com> * Remove instructions.md special case; add .github/** to allow-relative-links.txt Co-authored-by: weshaggard <9010698+weshaggard@users.noreply.github.com> * Move allow-relative-links.txt to eng/common/scripts/ so it syncs to all repos Co-authored-by: weshaggard <9010698+weshaggard@users.noreply.github.com> * Update allow-relative-links.txt * Change Write-Host to Write-Verbose for logging * Update eng/common/scripts/Verify-Links.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Address review feedback: trim comments, precompute regexes, Join-Path, remove eng/** Co-authored-by: weshaggard <9010698+weshaggard@users.noreply.github.com> * Restore eng/** to allow-relative-links.txt with updated comment Co-authored-by: weshaggard <9010698+weshaggard@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: weshaggard <9010698+weshaggard@users.noreply.github.com> Co-authored-by: Wes Haggard <weshaggard@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent d96ab2c commit e8e3e0c

File tree

3 files changed

+58
-13
lines changed

3 files changed

+58
-13
lines changed

eng/common/pipelines/templates/steps/verify-links.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ parameters:
99
BranchReplaceRegex: "^(${env:SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI}(?:\\.git)?/(?:blob|tree)/)$(DefaultBranch)(/.*)$"
1010
BranchReplacementName: "${env:SYSTEM_PULLREQUEST_SOURCECOMMITID}"
1111
Condition: succeeded() # If you want to run on failure for the link checker, set it to `Condition: succeededOrFailed()`.
12+
AllowRelativeLinksFile: '$(Build.SourcesDirectory)/eng/common/scripts/allow-relative-links.txt'
1213

1314
steps:
1415
- template: /eng/common/pipelines/templates/steps/set-default-branch.yml
@@ -32,3 +33,4 @@ steps:
3233
-localBuildRepoName "$env:BUILD_REPOSITORY_NAME"
3334
-localBuildRepoPath $(Build.SourcesDirectory)
3435
-inputCacheFile "https://azuresdkartifacts.blob.core.windows.net/verify-links-cache/verify-links-cache.txt"
36+
-allowRelativeLinksFile "${{ parameters.AllowRelativeLinksFile }}"

eng/common/scripts/Verify-Links.ps1

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
.PARAMETER requestTimeoutSec
5555
The number of seconds before we timeout when sending an individual web request. Default is 15 seconds.
5656
57+
.PARAMETER allowRelativeLinksFile
58+
Path to a file containing file path patterns (supporting wildcards) for which relative links are permitted even when
59+
checkLinkGuidance is true. Relative links in matching files are still verified for correctness. One pattern per line;
60+
lines beginning with '#' are treated as comments.
61+
5762
.EXAMPLE
5863
PS> .\Verify-Links.ps1 C:\README.md
5964
@@ -80,7 +85,8 @@ param (
8085
[string] $localGithubClonedRoot = "",
8186
[string] $localBuildRepoName = "",
8287
[string] $localBuildRepoPath = "",
83-
[string] $requestTimeoutSec = 15
88+
[string] $requestTimeoutSec = 15,
89+
[string] $allowRelativeLinksFile = (Join-Path $PSScriptRoot "allow-relative-links.txt")
8490
)
8591

8692
Set-StrictMode -Version 3.0
@@ -247,8 +253,9 @@ function ResolveUri ([System.Uri]$referralUri, [string]$link)
247253

248254
$linkUri = [System.Uri]$link;
249255
# Our link guidelines do not allow relative links so only resolve them when we are not
250-
# validating links against our link guidelines (i.e. !$checkLinkGuideance)
251-
if ($checkLinkGuidance -and !$linkUri.IsAbsoluteUri) {
256+
# validating links against our link guidelines (i.e. !$checkLinkGuidance) or when
257+
# relative links are explicitly allowed for the current page.
258+
if ($checkLinkGuidance -and !$allowRelativeLinksForCurrentPage -and !$linkUri.IsAbsoluteUri) {
252259
return $linkUri
253260
}
254261

@@ -428,7 +435,7 @@ function CheckLink ([System.Uri]$linkUri, $allowRetry=$true)
428435
$linkValid = $false
429436
}
430437
# Check if the url is relative links, suppress the archor link validation.
431-
if (!$linkUri.IsAbsoluteUri -and !$link.StartsWith("#")) {
438+
if (!$allowRelativeLinksForCurrentPage -and !$linkUri.IsAbsoluteUri -and !$link.StartsWith("#")) {
432439
LogWarning "DO NOT use relative link $linkUri. Please use absolute link instead. Check here for more information: https://aka.ms/azsdk/guideline/links"
433440
$linkValid = $false
434441
}
@@ -512,12 +519,41 @@ if ($PSVersionTable.PSVersion.Major -lt 6)
512519
}
513520
$ignoreLinks = @();
514521
if (Test-Path $ignoreLinksFile) {
515-
$ignoreLinks = (Get-Content $ignoreLinksFile).Where({ $_.Trim() -ne "" -and !$_.StartsWith("#") })
522+
$ignoreLinks = (Get-Content $ignoreLinksFile).Where({ $_.Trim() -ne "" -and !$_.Trim().StartsWith("#") })
523+
}
524+
525+
$allowRelativeLinkRegexes = @()
526+
if ($allowRelativeLinksFile -and (Test-Path $allowRelativeLinksFile)) {
527+
$allowRelativeLinkRegexes = (Get-Content $allowRelativeLinksFile).Where({ $_.Trim() -ne "" -and !$_.Trim().StartsWith("#") }) | ForEach-Object {
528+
$normalizedPattern = $_.Trim().Replace('\', '/')
529+
# Convert glob pattern to regex: ** matches anything including separators, * matches within a segment
530+
$regexStr = "^.*" + [regex]::Escape($normalizedPattern).Replace("\*\*", ".*").Replace("\*", "[^/]*") + ".*$"
531+
@{
532+
Pattern = $normalizedPattern
533+
Regex = [System.Text.RegularExpressions.Regex]::new($regexStr, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
534+
}
535+
}
536+
Write-Verbose "Loaded $($allowRelativeLinkRegexes.Count) allow-relative-links pattern(s) from '$allowRelativeLinksFile'."
537+
}
538+
539+
function Test-PageUriMatchesRelativeLinkPattern([System.Uri]$pageUri) {
540+
if ($allowRelativeLinkRegexes.Count -eq 0) { return $false }
541+
$pathToCheck = if ($pageUri.IsFile) { $pageUri.LocalPath } else { $pageUri.ToString() }
542+
# Normalize separators for consistent matching
543+
$pathToCheck = $pathToCheck.Replace('\', '/')
544+
foreach ($entry in $allowRelativeLinkRegexes) {
545+
if ($entry.Regex.IsMatch($pathToCheck)) {
546+
Write-Verbose "Page '$pathToCheck' matches allow-relative-links pattern '$($entry.Pattern)'."
547+
return $true
548+
}
549+
}
550+
return $false
516551
}
517552

518553
# Use default hashtable constructor instead of @{} because we need them to be case sensitive
519554
$checkedPages = New-Object Hashtable
520555
$checkedLinks = New-Object Hashtable
556+
$allowRelativeLinksForCurrentPage = $false
521557

522558
if ($inputCacheFile)
523559
{
@@ -535,7 +571,7 @@ if ($inputCacheFile)
535571
elseif (Test-Path $inputCacheFile) {
536572
$cacheContent = Get-Content $inputCacheFile -Raw
537573
}
538-
$goodLinks = $cacheContent.Split("`n").Where({ $_.Trim() -ne "" -and !$_.StartsWith("#") })
574+
$goodLinks = $cacheContent.Split("`n").Where({ $_.Trim() -ne "" -and !$_.Trim().StartsWith("#") })
539575

540576
foreach ($goodLink in $goodLinks) {
541577
$goodLink = $goodLink.Trim()
@@ -558,8 +594,6 @@ foreach ($url in $urls) {
558594

559595
LogGroupStart "Link checking details"
560596

561-
$originalcheckLinkGuidance = $checkLinkGuidance
562-
563597
while ($pageUrisToCheck.Count -ne 0)
564598
{
565599
$pageUri = $pageUrisToCheck.Dequeue();
@@ -568,10 +602,10 @@ while ($pageUrisToCheck.Count -ne 0)
568602
if ($checkedPages.ContainsKey($pageUri)) { continue }
569603
$checkedPages[$pageUri] = $true;
570604

571-
# copilot instructions require the use of relative links which is against our general guidance
572-
# but we mainly care about those guidelines for docs publishing and not copilot instructions
573-
# so we can disable the guidelines while validating copilot instruction files.
574-
if ($pageUri -match "instructions.md$") { $checkLinkGuidance = $false }
605+
# Allow relative links for pages matching patterns in the allow-relative-links configuration file.
606+
# The links themselves are still checked for correctness, only the relative-link restriction is lifted.
607+
# Other link guidance (e.g. http vs https, uppercase anchors, locale) continues to apply.
608+
if ($checkLinkGuidance -and (Test-PageUriMatchesRelativeLinkPattern $pageUri)) { $allowRelativeLinksForCurrentPage = $true }
575609

576610
[string[]] $linkUris = GetLinks $pageUri
577611
Write-Host "Checking $($linkUris.Count) links found on page $pageUri";
@@ -597,7 +631,7 @@ while ($pageUrisToCheck.Count -ne 0)
597631
Write-Host "Exception encountered while processing pageUri $pageUri : $($_.Exception)"
598632
throw
599633
} finally {
600-
$checkLinkGuidance = $originalcheckLinkGuidance
634+
$allowRelativeLinksForCurrentPage = $false
601635
}
602636
}
603637

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Files matching patterns listed here are permitted to use relative links even when checkLinkGuidance is enabled.
2+
# Relative links in matching files are still verified for correctness.
3+
# One glob pattern per line. Lines beginning with '#' are ignored.
4+
# Patterns support wildcards: * matches within a path segment, ** matches across segments.
5+
#
6+
# Allow relative links for all files under the .github folder (e.g. copilot instructions).
7+
.github/**
8+
# Allow relative links for all files under the eng folder (e.g. engineering system scripts and templates).
9+
eng/**

0 commit comments

Comments
 (0)