Skip to content

Commit 33db08e

Browse files
azure-sdkKonrad Jamrozik
andauthored
Sync eng/common directory with azure-sdk-tools for PR 6903 (Azure#36640)
* fixes * ongoing * ongoing * add top-level throw/catches showing exception info * fix handling of cases when there is 1 link and when there is no RetryAfter.Delta * handle lack of Exception.Headers property * handle gracefully obtaining status code from $_.Exception.InnerException.ErrorCode --------- Co-authored-by: Konrad Jamrozik <kojamroz@microsoft.com>
1 parent c775e1c commit 33db08e

File tree

1 file changed

+106
-54
lines changed

1 file changed

+106
-54
lines changed

eng/common/scripts/Verify-Links.ps1

Lines changed: 106 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
Specifies the file that contains a set of links to ignore when verifying.
1313
1414
.PARAMETER devOpsLogging
15-
Switch that will enable devops specific logging for warnings
15+
Switch that will enable devops specific logging for warnings.
1616
1717
.PARAMETER recursive
18-
Check the links recurisvely based on recursivePattern.
18+
Check the links recurisvely. Applies to links starting with 'baseUrl' parameter. Defaults to true.
1919
2020
.PARAMETER baseUrl
2121
Recursively check links for all links verified that begin with this baseUrl, defaults to the folder the url is contained in.
22+
If 'recursive' parameter is set to false, this parameter has no effect.
2223
2324
.PARAMETER rootUrl
2425
Path to the root of the site for resolving rooted relative links, defaults to host root for http and file directory for local files.
@@ -74,6 +75,8 @@ param (
7475
[string] $requestTimeoutSec = 15
7576
)
7677

78+
Set-StrictMode -Version 3.0
79+
7780
$ProgressPreference = "SilentlyContinue"; # Disable invoke-webrequest progress dialog
7881
# Regex of the locale keywords.
7982
$locale = "/en-us/"
@@ -184,11 +187,15 @@ function ParseLinks([string]$baseUri, [string]$htmlContent)
184187
#$hrefs | Foreach-Object { Write-Host $_ }
185188

186189
Write-Verbose "Found $($hrefs.Count) raw href's in page $baseUri";
187-
$links = $hrefs | ForEach-Object { ResolveUri $baseUri $_.Groups["href"].Value }
190+
[string[]] $links = $hrefs | ForEach-Object { ResolveUri $baseUri $_.Groups["href"].Value }
188191

189192
#$links | Foreach-Object { Write-Host $_ }
190193

191-
return $links
194+
if ($null -eq $links) {
195+
$links = @()
196+
}
197+
198+
return ,$links
192199
}
193200

194201
function CheckLink ([System.Uri]$linkUri, $allowRetry=$true)
@@ -239,11 +246,27 @@ function CheckLink ([System.Uri]$linkUri, $allowRetry=$true)
239246
}
240247
}
241248
catch {
242-
$statusCode = $_.Exception.Response.StatusCode.value__
249+
250+
$responsePresent = $_.Exception.psobject.Properties.name -contains "Response"
251+
if ($responsePresent) {
252+
$statusCode = $_.Exception.Response.StatusCode.value__
253+
} else {
254+
$statusCode = $null
255+
}
243256

244-
if(!$statusCode) {
257+
if (!$statusCode) {
245258
# Try to pull the error code from any inner SocketException we might hit
246-
$statusCode = $_.Exception.InnerException.ErrorCode
259+
260+
$innerExceptionPresent = $_.Exception.psobject.Properties.name -contains "InnerException"
261+
262+
$errorCodePresent = $false
263+
if ($innerExceptionPresent) {
264+
$errorCodePresent = $_.Exception.InnerException.psobject.Properties.name -contains "ErrorCode"
265+
}
266+
267+
if ($errorCodePresent) {
268+
$statusCode = $_.Exception.InnerException.ErrorCode
269+
}
247270
}
248271

249272
if ($statusCode -in $errorStatusCodes) {
@@ -257,13 +280,30 @@ function CheckLink ([System.Uri]$linkUri, $allowRetry=$true)
257280
$linkValid = $false
258281
}
259282
else {
283+
260284
if ($null -ne $statusCode) {
285+
261286
# For 429 rate-limiting try to pause if possible
262-
if ($allowRetry -and $_.Exception.Response -and $statusCode -eq 429) {
263-
$retryAfter = $_.Exception.Response.Headers.RetryAfter.Delta.TotalSeconds
287+
if ($allowRetry -and $responsePresent -and $statusCode -eq 429) {
288+
289+
$headersPresent = $_.Exception.psobject.Properties.name -contains "Headers"
290+
291+
$retryAfterPresent = $false
292+
if ($headersPresent) {
293+
$retryAfterPresent = $_.Exception.Headers.psobject.Properties.name -contains "RetryAfter"
294+
}
295+
296+
$retryAfterDeltaPresent = $false
297+
if ($retryAfterPresent) {
298+
$retryAfterDeltaPresent = $_.Exception.Headers.RetryAfter.psobject.Properties.name -contains "Delta"
299+
}
300+
301+
if ($retryAfterDeltaPresent) {
302+
$retryAfter = $_.Exception.Response.Headers.RetryAfter.Delta.TotalSeconds
303+
}
264304

265305
# Default retry after 60 (arbitrary) seconds if no header given
266-
if (!$retryAfter -or $retryAfter -gt 60) { $retryAfter = 60 }
306+
if (!$retryAfterDeltaPresent -or $retryAfter -gt 60) { $retryAfter = 60 }
267307
Write-Host "Rate-Limited for $retryAfter seconds while requesting $linkUri"
268308

269309
Start-Sleep -Seconds $retryAfter
@@ -366,9 +406,9 @@ function GetLinks([System.Uri]$pageUri)
366406
LogError "Don't know how to process uri $pageUri"
367407
}
368408

369-
$links = ParseLinks $pageUri $content
409+
[string[]] $links = ParseLinks $pageUri $content
370410

371-
return $links;
411+
return ,$links;
372412
}
373413

374414
if ($urls) {
@@ -433,59 +473,71 @@ if ($devOpsLogging) {
433473
while ($pageUrisToCheck.Count -ne 0)
434474
{
435475
$pageUri = $pageUrisToCheck.Dequeue();
436-
if ($checkedPages.ContainsKey($pageUri)) { continue }
437-
$checkedPages[$pageUri] = $true;
438-
439-
$linkUris = GetLinks $pageUri
440-
Write-Host "Checking $($linkUris.Count) links found on page $pageUri";
441-
$badLinksPerPage = @();
442-
foreach ($linkUri in $linkUris) {
443-
$isLinkValid = CheckLink $linkUri
444-
if (!$isLinkValid -and !$badLinksPerPage.Contains($linkUri)) {
445-
if (!$linkUri.ToString().Trim()) {
446-
$linkUri = $emptyLinkMessage
476+
Write-Verbose "Processing pageUri $pageUri"
477+
try {
478+
if ($checkedPages.ContainsKey($pageUri)) { continue }
479+
$checkedPages[$pageUri] = $true;
480+
481+
[string[]] $linkUris = GetLinks $pageUri
482+
Write-Host "Checking $($linkUris.Count) links found on page $pageUri";
483+
$badLinksPerPage = @();
484+
foreach ($linkUri in $linkUris) {
485+
$isLinkValid = CheckLink $linkUri
486+
if (!$isLinkValid -and !$badLinksPerPage.Contains($linkUri)) {
487+
if (!$linkUri.ToString().Trim()) {
488+
$linkUri = $emptyLinkMessage
489+
}
490+
$badLinksPerPage += $linkUri
447491
}
448-
$badLinksPerPage += $linkUri
449-
}
450-
if ($recursive -and $isLinkValid) {
451-
if ($linkUri.ToString().StartsWith($baseUrl) -and !$checkedPages.ContainsKey($linkUri)) {
452-
$pageUrisToCheck.Enqueue($linkUri);
492+
if ($recursive -and $isLinkValid) {
493+
if ($linkUri.ToString().StartsWith($baseUrl) -and !$checkedPages.ContainsKey($linkUri)) {
494+
$pageUrisToCheck.Enqueue($linkUri);
495+
}
453496
}
454497
}
498+
if ($badLinksPerPage.Count -gt 0) {
499+
$badLinks[$pageUri] = $badLinksPerPage
500+
}
501+
} catch {
502+
Write-Host "Exception encountered while processing pageUri $pageUri : $($_.Exception)"
503+
throw
455504
}
456-
if ($badLinksPerPage.Count -gt 0) {
457-
$badLinks[$pageUri] = $badLinksPerPage
458-
}
459-
}
460-
if ($devOpsLogging) {
461-
Write-Host "##[endgroup]"
462505
}
463506

464-
if ($badLinks.Count -gt 0) {
465-
Write-Host "Summary of broken links:"
466-
}
467-
foreach ($pageLink in $badLinks.Keys) {
468-
Write-Host "'$pageLink' has $($badLinks[$pageLink].Count) broken link(s):"
469-
foreach ($brokenLink in $badLinks[$pageLink]) {
470-
Write-Host " $brokenLink"
507+
try {
508+
if ($devOpsLogging) {
509+
Write-Host "##[endgroup]"
471510
}
472-
}
473511

474-
$linksChecked = $checkedLinks.Count - $cachedLinksCount
512+
if ($badLinks.Count -gt 0) {
513+
Write-Host "Summary of broken links:"
514+
}
515+
foreach ($pageLink in $badLinks.Keys) {
516+
Write-Host "'$pageLink' has $($badLinks[$pageLink].Count) broken link(s):"
517+
foreach ($brokenLink in $badLinks[$pageLink]) {
518+
Write-Host " $brokenLink"
519+
}
520+
}
475521

476-
if ($badLinks.Count -gt 0) {
477-
Write-Host "Checked $linksChecked links with $($badLinks.Count) broken link(s) found."
478-
}
479-
else {
480-
Write-Host "Checked $linksChecked links. No broken links found."
481-
}
522+
$linksChecked = $checkedLinks.Count - $cachedLinksCount
482523

483-
if ($outputCacheFile)
484-
{
485-
$goodLinks = $checkedLinks.Keys.Where({ "True" -eq $checkedLinks[$_].ToString() }) | Sort-Object
524+
if ($badLinks.Count -gt 0) {
525+
Write-Host "Checked $linksChecked links with $($badLinks.Count) broken link(s) found."
526+
}
527+
else {
528+
Write-Host "Checked $linksChecked links. No broken links found."
529+
}
530+
531+
if ($outputCacheFile)
532+
{
533+
$goodLinks = $checkedLinks.Keys.Where({ "True" -eq $checkedLinks[$_].ToString() }) | Sort-Object
486534

487-
Write-Host "Writing the list of validated links to $outputCacheFile"
488-
$goodLinks | Set-Content $outputCacheFile
535+
Write-Host "Writing the list of validated links to $outputCacheFile"
536+
$goodLinks | Set-Content $outputCacheFile
537+
}
538+
} catch {
539+
Write-Host "Exception encountered after all pageUris have been processed : $($_.Exception)"
540+
throw
489541
}
490542

491543
exit $badLinks.Count

0 commit comments

Comments
 (0)