-
Notifications
You must be signed in to change notification settings - Fork 159
[DevOps] Create broken link tests for markdown files across all documentation folders #1691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
Co-authored-by: flanakin <399533+flanakin@users.noreply.github.com>
.github/workflows/dev.yml
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create a separate workflow documentation tests and only run the broken link test there. Don't change the PowerShell code tests. Rename dev.yml to powershell.yml.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created separate documentation.yml
workflow for broken link tests and renamed dev.yml
to powershell.yml
. The PowerShell code tests remain unchanged. Commit bccd13f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the src/scripts/Test-PowerShell.ps1
script to add a -Markdown
option that runs this broken links test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added -Markdown
parameter to Test-PowerShell.ps1
that runs the broken links test. The script can now be called with src/scripts/Test-PowerShell.ps1 -Markdown
. Commit bccd13f
Co-authored-by: flanakin <399533+flanakin@users.noreply.github.com>
name: Broken Links | ||
runs-on: Windows-latest | ||
steps: | ||
- name: Install and cache PowerShell modules | ||
uses: potatoqualitee/psmodulecache@v6.2.1 | ||
with: | ||
modules-to-cache: Pester | ||
shell: pwsh | ||
- uses: actions/checkout@v3 | ||
- name: Run Broken Links Test | ||
shell: pwsh | ||
run: | | ||
src/scripts/Test-PowerShell.ps1 -Markdown |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium documentation
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 29 days ago
To fix the issue, we will add a permissions
block to the root of the workflow file. This block will specify the least privileges required for the workflow to function. Since the workflow only needs to read the repository contents to check for broken links, we will set contents: read
. This ensures that the workflow has no write access to the repository.
The permissions
block will be added at the root level, applying to all jobs in the workflow.
-
Copy modified lines R12-R14
@@ -11,2 +11,5 @@ | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds automated broken link validation for all markdown files, integrates it into the existing PowerShell test runner, and wires it up in GitHub Actions.
- Introduce a
-Markdown
switch inTest-PowerShell.ps1
to run only broken link tests - Add
BrokenLinks.Tests.ps1
with folder-specific link validation logic - Update the documentation CI workflow to trigger markdown broken link tests on PRs
Reviewed Changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.
File | Description |
---|---|
src/scripts/Test-PowerShell.ps1 | Added -Markdown parameter and special-case logic to run broken link tests |
src/powershell/Tests/Lint/BrokenLinks.Tests.ps1 | New comprehensive Pester tests that verify link formats and existence across docs, docs-mslearn, docs-wiki, and other markdown |
.github/workflows/documentation.yml | Workflow that runs the broken link tests on markdown changes in docs folders |
Comments suppressed due to low confidence (1)
.github/workflows/documentation.yml:9
- [nitpick] The file path filter '.md' only matches Markdown files in the repository root; consider using '**/.md' to cover Markdown files in subdirectories and ensure tests run for all documentation changes.
- '*.md'
if ($FOCUS) { $testsToRun += '*-FinOpsSchema*', 'FOCUS.Tests.ps1' } | ||
if ($Hubs) { $testsToRun += '*-FinOpsHub*', '*-Hub*', 'Hubs.Tests.ps1' } | ||
if ($Toolkit) { $testsToRun += 'Toolkit.Tests.ps1', '*-FinOpsToolkit*' } | ||
if ($Markdown) { $testsToRun += 'BrokenLinks.Tests.ps1' } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The test path for BrokenLinks.Tests.ps1 uses only the filename, which may not resolve correctly; consider using the full path or a consistent glob pattern to ensure Pester locates the test file.
Copilot uses AI. Check for mistakes.
} | ||
|
||
Describe 'Broken Links - docs folder [<_>]' -Tag 'BrokenLinks', 'Docs' -ForEach $docsFiles.FullName { | ||
BeforeAll { | ||
$rootPath = ((Get-Item -Path $PSScriptRoot).Parent.Parent.Parent.Parent).FullName | ||
$file = $_ | ||
|
||
function Get-MarkdownLinks { | ||
param([string]$FilePath) | ||
|
||
$content = Get-Content -Path $FilePath -Raw -ErrorAction SilentlyContinue | ||
if (-not $content) { return @() } | ||
|
||
# Find markdown links [text](url) and reference links [text]: url | ||
$linkPattern = '\[([^\]]*)\]\(([^)]+)\)' | ||
$refLinkPattern = '^\s*\[([^\]]+)\]:\s*(.+)$' | ||
|
||
$links = @() | ||
|
||
# Extract inline links | ||
[regex]::Matches($content, $linkPattern) | ForEach-Object { | ||
$links += @{ | ||
Text = $_.Groups[1].Value | ||
Url = $_.Groups[2].Value.Trim() | ||
} | ||
} | ||
|
||
# Extract reference links | ||
$content -split "`n" | ForEach-Object { | ||
if ($_ -match $refLinkPattern) { | ||
$links += @{ | ||
Text = $matches[1] | ||
Url = $matches[2].Trim() | ||
} | ||
} | ||
} | ||
|
||
return $links | ||
} | ||
|
||
function Test-LinkValidity { | ||
param( | ||
[string]$FilePath, | ||
[string]$LinkUrl, | ||
[string]$FolderType | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Helper functions Get-MarkdownLinks and Test-LinkValidity are duplicated across each Describe block; consider extracting them to BeforeDiscovery or a shared module to reduce duplication and improve maintainability.
} | |
Describe 'Broken Links - docs folder [<_>]' -Tag 'BrokenLinks', 'Docs' -ForEach $docsFiles.FullName { | |
BeforeAll { | |
$rootPath = ((Get-Item -Path $PSScriptRoot).Parent.Parent.Parent.Parent).FullName | |
$file = $_ | |
function Get-MarkdownLinks { | |
param([string]$FilePath) | |
$content = Get-Content -Path $FilePath -Raw -ErrorAction SilentlyContinue | |
if (-not $content) { return @() } | |
# Find markdown links [text](url) and reference links [text]: url | |
$linkPattern = '\[([^\]]*)\]\(([^)]+)\)' | |
$refLinkPattern = '^\s*\[([^\]]+)\]:\s*(.+)$' | |
$links = @() | |
# Extract inline links | |
[regex]::Matches($content, $linkPattern) | ForEach-Object { | |
$links += @{ | |
Text = $_.Groups[1].Value | |
Url = $_.Groups[2].Value.Trim() | |
} | |
} | |
# Extract reference links | |
$content -split "`n" | ForEach-Object { | |
if ($_ -match $refLinkPattern) { | |
$links += @{ | |
Text = $matches[1] | |
Url = $matches[2].Trim() | |
} | |
} | |
} | |
return $links | |
} | |
function Test-LinkValidity { | |
param( | |
[string]$FilePath, | |
[string]$LinkUrl, | |
[string]$FolderType | |
) | |
function Get-MarkdownLinks { | |
param([string]$FilePath) | |
$content = Get-Content -Path $FilePath -Raw -ErrorAction SilentlyContinue | |
if (-not $content) { return @() } | |
# Find markdown links [text](url) and reference links [text]: url | |
$linkPattern = '\[([^\]]*)\]\(([^)]+)\)' | |
$refLinkPattern = '^\s*\[([^\]]+)\]:\s*(.+)$' | |
$links = @() | |
# Extract inline links | |
[regex]::Matches($content, $linkPattern) | ForEach-Object { | |
$links += @{ | |
Text = $_.Groups[1].Value | |
Url = $_.Groups[2].Value.Trim() | |
} | |
} | |
# Extract reference links | |
$content -split "`n" | ForEach-Object { | |
if ($_ -match $refLinkPattern) { | |
$links += @{ | |
Text = $matches[1] | |
Url = $matches[2].Trim() | |
} | |
} | |
} | |
return $links | |
} | |
function Test-LinkValidity { | |
param( | |
[string]$FilePath, | |
[string]$LinkUrl, | |
[string]$FolderType | |
) | |
Describe 'Broken Links - docs folder [<_>]' -Tag 'BrokenLinks', 'Docs' -ForEach $docsFiles.FullName { | |
BeforeAll { | |
$rootPath = ((Get-Item -Path $PSScriptRoot).Parent.Parent.Parent.Parent).FullName | |
$file = $_ | |
# Functions moved to BeforeDiscovery | |
Copilot uses AI. Check for mistakes.
This PR implements comprehensive broken link testing for all markdown files in the repository, with folder-specific validation rules and automated GitHub workflow integration.
What's New
BrokenLinks.Tests.ps1
insrc/powershell/Tests/Lint
that validates links across all markdown filesdocs/
: Relative links for files within docs, root-relative for MS Learn content, fully qualified for external links, Jekyll template supportdocs-mslearn/
: Folder-relative for same folder files, root-relative for learn.microsoft.com content, fully qualified for external (prohibits explicit learn.microsoft.com URLs)docs-wiki/
: Relative links for files within docs-wiki, fully qualified for external linksDocs
,DocsMslearn
,DocsWiki
,Other
)dev.yml
to trigger broken link tests when markdown files change in any documentation folderTechnical Implementation
The tests automatically integrate with the existing lint test infrastructure and validate:
Test Results
Successfully identifies 70 broken links across the repository, demonstrating the tests are working correctly to catch real issues.
Fixes #1690.
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.