From 5d04e10444947b5f3d8b9c74315238ebb4ae07ff Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:07:53 +0200 Subject: [PATCH 01/19] Enhance module catalog generation pipeline Add enriched module catalog generation with Process-PSModule reference tracking, per-repo catalog page generation, and a weekly docs refresh schedule. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/update-index/src/Helper.psm1 | 486 +++++++++++++++++-- .github/actions/update-index/src/main.ps1 | 4 +- .github/workflows/Docs.yml | 2 + 3 files changed, 452 insertions(+), 40 deletions(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index dbba6f8..d486212 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -39,24 +39,34 @@ function Show-RepoList { } LogGroup "Get repositories for organization [$Owner]" { - $rawRepos = Get-GitHubRepository -Organization $Owner -AdditionalProperty 'description' + $rawRepos = Get-GitHubRepository -Organization $Owner -AdditionalProperty @( + 'description', + 'default_branch', + 'stargazers_count', + 'open_issues_count', + 'html_url' + ) Write-Output "Found $($rawRepos.Count) repositories" $repos = $rawRepos | ForEach-Object { $rawRepo = $_ $rawRepo.CustomProperties | Where-Object { $_.Name -eq 'Type' } | ForEach-Object { $type = $_.Value [pscustomobject]@{ - Name = $rawRepo.Name - Owner = $Owner - Type = $type - Description = $rawRepo.Description + Name = $rawRepo.Name + Owner = $Owner + Type = $type + Description = $rawRepo.Description + DefaultBranch = $rawRepo.DefaultBranch + Stars = $rawRepo.StargazersCount + OpenIssuesCount = $rawRepo.OpenIssuesCount + HtmlUrl = $rawRepo.HtmlUrl } } } | Sort-Object Type, Name $repos | Format-Table -AutoSize } - $repos | Group-Object -Property Type + $repos } function Update-MDSection { @@ -117,6 +127,352 @@ function Update-MDSection { } } +function Get-PropertyValue { + [OutputType([object])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [object] $InputObject, + + [Parameter(Mandatory)] + [string[]] $Names, + + [Parameter()] + [object] $Default = $null + ) + + foreach ($name in $Names) { + $property = $InputObject.PSObject.Properties[$name] + if ($null -eq $property) { + continue + } + if ($null -eq $property.Value) { + continue + } + $value = [string]$property.Value + if ([string]::IsNullOrWhiteSpace($value)) { + continue + } + return $property.Value + } + + return $Default +} + +function Get-GitHubAccessToken { + [OutputType([string])] + [CmdletBinding()] + param() + + $context = Get-GitHubContext + if ($null -eq $context) { + return $null + } + + foreach ($propertyName in @('AccessToken', 'Token', 'token')) { + $property = $context.PSObject.Properties[$propertyName] + if ($null -eq $property) { + continue + } + + $token = $property.Value + if ($token -is [securestring]) { + $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($token) + try { + return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) + } + finally { + [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) + } + } + + if (-not [string]::IsNullOrWhiteSpace([string]$token)) { + return [string]$token + } + } + + return $null +} + +function Invoke-GitHubApi { + [OutputType([object])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Uri + ) + + $headers = @{ + Accept = 'application/vnd.github+json' + 'User-Agent' = 'PSModule-Docs-UpdateIndex' + } + + $accessToken = Get-GitHubAccessToken + if (-not [string]::IsNullOrWhiteSpace($accessToken)) { + $headers.Authorization = "Bearer $accessToken" + } + + try { + Invoke-RestMethod -Method Get -Uri $Uri -Headers $headers + } + catch { + $statusCode = $null + if ($_.Exception.Response) { + $statusCode = $_.Exception.Response.StatusCode.value__ + } + if ($statusCode -eq 404) { + return $null + } + + Write-Warning "GitHub API call failed for [$Uri]: $($_.Exception.Message)" + return $null + } +} + +function Get-RepositoryReadmeContent { + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Owner, + [Parameter(Mandatory)] + [string] $Name + ) + + $uri = "https://api.github.com/repos/$Owner/$Name/readme" + $response = Invoke-GitHubApi -Uri $uri + if ($null -eq $response) { + return '' + } + + $encodedContent = Get-PropertyValue -InputObject $response -Names @('content') + if ([string]::IsNullOrWhiteSpace([string]$encodedContent)) { + return '' + } + + $cleanContent = ([string]$encodedContent).Replace("`n", '').Replace("`r", '') + [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($cleanContent)) +} + +function Get-MarkdownSummary { + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter()] + [string] $Markdown + ) + + if ([string]::IsNullOrWhiteSpace($Markdown)) { + return '' + } + + $text = $Markdown + $text = [regex]::Replace($text, '(?s)```.*?```', ' ') + $text = [regex]::Replace($text, '(?m)^!\[[^\]]*\]\([^\)]*\)\s*$', '') + $text = [regex]::Replace($text, '(?m)^#+\s+', '') + $text = [regex]::Replace($text, '\[([^\]]+)\]\([^\)]+\)', '$1') + $text = [regex]::Replace($text, '(?m)^\s*>+\s*', '') + $text = [regex]::Replace($text, '[*_`~]', '') + $text = [regex]::Replace($text, '\r?\n', "`n") + + foreach ($paragraph in ($text -split "`n`n")) { + $candidate = [regex]::Replace($paragraph, '\s+', ' ').Trim() + if (-not [string]::IsNullOrWhiteSpace($candidate)) { + return $candidate + } + } + + '' +} + +function ConvertTo-HtmlAttributeValue { + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter()] + [string] $Value, + [Parameter()] + [int] $MaxLength = 160 + ) + + if ([string]::IsNullOrWhiteSpace($Value)) { + return '' + } + + $singleLine = [regex]::Replace($Value, '\s+', ' ').Trim() + if ($singleLine.Length -gt $MaxLength) { + $singleLine = $singleLine.Substring(0, $MaxLength - 1).TrimEnd() + '...' + } + + $singleLine = $singleLine.Replace('&', '&') + $singleLine = $singleLine.Replace('"', '"') + $singleLine = $singleLine.Replace('<', '<') + $singleLine = $singleLine.Replace('>', '>') + $singleLine +} + +function Get-OpenItemCount { + [OutputType([int])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Owner, + [Parameter(Mandatory)] + [string] $Name, + [Parameter(Mandatory)] + [ValidateSet('issue', 'pr')] + [string] $Type + ) + + $query = [uri]::EscapeDataString("repo:$Owner/$Name type:$Type state:open") + $uri = "https://api.github.com/search/issues?q=$query&per_page=1" + $response = Invoke-GitHubApi -Uri $uri + if ($null -eq $response) { + return 0 + } + + [int](Get-PropertyValue -InputObject $response -Names @('total_count') -Default 0) +} + +function Get-RepositoryVersion { + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Owner, + [Parameter(Mandatory)] + [string] $Name + ) + + $latestReleaseUri = "https://api.github.com/repos/$Owner/$Name/releases/latest" + $latestRelease = Invoke-GitHubApi -Uri $latestReleaseUri + if ($null -ne $latestRelease) { + $releaseName = Get-PropertyValue -InputObject $latestRelease -Names @('tag_name', 'name') + if (-not [string]::IsNullOrWhiteSpace([string]$releaseName)) { + return [string]$releaseName + } + } + + $latestTagUri = "https://api.github.com/repos/$Owner/$Name/tags?per_page=1" + $latestTags = Invoke-GitHubApi -Uri $latestTagUri + if ($null -eq $latestTags -or $latestTags.Count -eq 0) { + return 'N/A' + } + + [string](Get-PropertyValue -InputObject $latestTags[0] -Names @('name') -Default 'N/A') +} + +function Get-WorkflowReference { + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Owner, + [Parameter(Mandatory)] + [string] $Name, + [Parameter(Mandatory)] + [string] $DefaultBranch + ) + + foreach ($workflowPath in @('.github/workflows/workflow.yml', '.github/workflows/workflow.yaml')) { + $encodedRef = [uri]::EscapeDataString($DefaultBranch) + $uri = "https://api.github.com/repos/$Owner/$Name/contents/$workflowPath?ref=$encodedRef" + $response = Invoke-GitHubApi -Uri $uri + if ($null -eq $response) { + continue + } + + $content = Get-PropertyValue -InputObject $response -Names @('content') + if ([string]::IsNullOrWhiteSpace([string]$content)) { + continue + } + + $decoded = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String(([string]$content).Replace("`n", '').Replace("`r", ''))) + $match = [regex]::Match($decoded, '(?m)uses:\s*PSModule/Process-PSModule/.+?@(?[^\s#]+)') + if ($match.Success) { + return $match.Groups['ref'].Value + } + } + + 'N/A' +} + +function Get-ProcessReferenceStatus { + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter()] + [string] $Reference, + [Parameter()] + [string] $LatestVersion + ) + + if ([string]::IsNullOrWhiteSpace($Reference) -or $Reference -eq 'N/A') { + return 'not-configured' + } + + if ($Reference -match '^[0-9a-f]{7,40}$') { + return 'sha-pinned' + } + + if ([string]::IsNullOrWhiteSpace($LatestVersion) -or $LatestVersion -eq 'N/A') { + return 'unknown' + } + + $referenceNormalized = $Reference.TrimStart('v') + $latestNormalized = $LatestVersion.TrimStart('v') + if ($referenceNormalized -eq $latestNormalized) { + return 'up-to-date' + } + + $referenceVersion = $null + $latestVersionParsed = $null + $hasReferenceVersion = [version]::TryParse(($referenceNormalized -replace '-.*$'), [ref]$referenceVersion) + $hasLatestVersion = [version]::TryParse(($latestNormalized -replace '-.*$'), [ref]$latestVersionParsed) + if ($hasReferenceVersion -and $hasLatestVersion) { + if ($referenceVersion -lt $latestVersionParsed) { + return 'behind' + } + return 'ahead' + } + + 'behind' +} + +function New-ModuleCatalogPage { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Path, + [Parameter(Mandatory)] + [pscustomobject] $ModuleData + ) + + $content = @" +# $($ModuleData.Name) + +> This page is generated from repository metadata by the docs index pipeline. + +- Repository: [$($ModuleData.Owner)/$($ModuleData.Name)](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)) +- Description: $($ModuleData.Description) +- Version: `$($ModuleData.Version)` +- Process-PSModule: `$($ModuleData.ProcessReference)` (`$($ModuleData.ProcessStatus)`) +- Open issues: [$($ModuleData.Issues)](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)/issues) +- Open PRs: [$($ModuleData.PullRequests)](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)/pulls) +- Stars: [$($ModuleData.Stars)](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)/stargazers) + +## About + +$($ModuleData.About) + +## README + +[View source README](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)#readme) +"@ + + Set-Content -Path $Path -Value $content +} + function Update-ActionList { <# .SYNOPSIS @@ -182,48 +538,102 @@ function Update-ModuleList { Updates the PowerShell modules list section in the documentation. .DESCRIPTION - Generates an HTML table of all PowerShell module repositories from the module's repo list, - including GitHub and PowerShell Gallery badges, and updates the MODULE_LIST section in - the PowerShell Modules index markdown file. - - .EXAMPLE - Update-ModuleList - - Regenerates the module table and writes it to docs\PowerShell\Modules\index.md. + Generates an enriched HTML table for PSModule module repositories and writes + repository-specific catalog pages that summarize README and module metadata. #> [CmdletBinding(SupportsShouldProcess)] - param() + param( + [Parameter()] + [object[]] $Repos = @() + ) + + if ($Repos.Count -eq 0) { + $Repos = Show-RepoList + } + + $moduleRepos = $Repos | Where-Object { + $_.Type -eq 'Module' -and $_.Owner -eq 'PSModule' + } | Sort-Object Name + + $catalogFolderPath = Join-Path 'src\docs\Modules\Catalog' 'Repositories' + if (-not (Test-Path $catalogFolderPath)) { + New-Item -Path $catalogFolderPath -ItemType Directory | Out-Null + } - $moduleTableRowTemplate = @' + $processLatestVersion = Get-RepositoryVersion -Owner 'PSModule' -Name 'Process-PSModule' + $moduleTableRows = '' + + foreach ($repo in $moduleRepos) { + $owner = [string](Get-PropertyValue -InputObject $repo -Names @('Owner') -Default 'PSModule') + $name = [string](Get-PropertyValue -InputObject $repo -Names @('Name') -Default '') + if ([string]::IsNullOrWhiteSpace($name)) { + continue + } + + $description = [string](Get-PropertyValue -InputObject $repo -Names @('Description') -Default 'No description available.') + if ([string]::IsNullOrWhiteSpace($description)) { + $description = 'No description available.' + } + + $defaultBranch = [string](Get-PropertyValue -InputObject $repo -Names @('DefaultBranch', 'default_branch') -Default 'main') + if ([string]::IsNullOrWhiteSpace($defaultBranch)) { + $defaultBranch = 'main' + } + + $readmeContent = Get-RepositoryReadmeContent -Owner $owner -Name $name + $aboutSummary = Get-MarkdownSummary -Markdown $readmeContent + if ([string]::IsNullOrWhiteSpace($aboutSummary)) { + $aboutSummary = $description + } + + $titleSummary = ConvertTo-HtmlAttributeValue -Value $aboutSummary + $version = Get-RepositoryVersion -Owner $owner -Name $name + $processReference = Get-WorkflowReference -Owner $owner -Name $name -DefaultBranch $defaultBranch + $processStatus = Get-ProcessReferenceStatus -Reference $processReference -LatestVersion $processLatestVersion + $issues = Get-OpenItemCount -Owner $owner -Name $name -Type issue + $pullRequests = Get-OpenItemCount -Owner $owner -Name $name -Type pr + $stars = [int](Get-PropertyValue -InputObject $repo -Names @('Stars', 'stargazers_count', 'StargazersCount') -Default 0) + + $modulePageFileName = "$name.md" + $modulePagePath = Join-Path $catalogFolderPath $modulePageFileName + $modulePageRelativeLink = "./Repositories/$modulePageFileName" + + $moduleData = [pscustomobject]@{ + Owner = $owner + Name = $name + Description = $description + Version = $version + ProcessReference = $processReference + ProcessStatus = $processStatus + Issues = $issues + PullRequests = $pullRequests + Stars = $stars + About = $aboutSummary + } + New-ModuleCatalogPage -Path $modulePagePath -ModuleData $moduleData + + $moduleTableRows += @" - {{ NAME }} - {{ DESCRIPTION }} -
- GitHub Issues - GitHub Pull Requests - GitHub Stars - GitHub Watchers - GitHub Forks - PowerShell Gallery Downloads - - - GitHub release (with filter) - PowerShell Gallery Version - + $name + $version + $processReference
$processStatus + $issues + $pullRequests + $stars -'@ - $moduleTableRows = '' - $repos | Where-Object { $_.Type -eq 'Module' } | ForEach-Object { - $moduleTableRows += $moduleTableRowTemplate.replace('{{ OWNER }}', $_.Owner).replace('{{ NAME }}', $_.Name).replace('{{ DESCRIPTION }}', $_.Description).TrimEnd() - $moduleTableRows += [Environment]::NewLine +"@ } + $moduleTable = @" - - - + + + + + + $moduleTableRows
NameDescriptionVersionNameVersionProcessVersionIssuesPRsStars
diff --git a/.github/actions/update-index/src/main.ps1 b/.github/actions/update-index/src/main.ps1 index c2d68fb..81fc345 100644 --- a/.github/actions/update-index/src/main.ps1 +++ b/.github/actions/update-index/src/main.ps1 @@ -1,6 +1,6 @@ Import-Module -Name (Join-Path $PSScriptRoot 'Helper.psm1') -Show-RepoList +$repos = Show-RepoList # Update-ActionList # Update-FunctionAppList -Update-ModuleList +Update-ModuleList -Repos $repos diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml index bdccaf0..f129fb6 100644 --- a/.github/workflows/Docs.yml +++ b/.github/workflows/Docs.yml @@ -2,6 +2,8 @@ name: Docs on: workflow_dispatch: + schedule: + - cron: '0 4 * * 1' push: branches: - main From 460a3345a24fc65eeb85ee4c1b6bbe32eafc901f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:07:56 +0200 Subject: [PATCH 02/19] Document generated module catalog behavior Clarify that catalog table and linked module pages are generated from repository metadata and README summaries. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/docs/Modules/Catalog/index.md | 2 +- src/docs/Modules/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/docs/Modules/Catalog/index.md b/src/docs/Modules/Catalog/index.md index f43062d..5db88f7 100644 --- a/src/docs/Modules/Catalog/index.md +++ b/src/docs/Modules/Catalog/index.md @@ -14,7 +14,7 @@ Each module page should capture: ## Catalog generation -The module list is intended to be generated from repository metadata and refreshed automatically. +The module list and linked module pages are generated from PSModule repository metadata and README content, then refreshed automatically. diff --git a/src/docs/Modules/index.md b/src/docs/Modules/index.md index 2989ec8..e1e1bbb 100644 --- a/src/docs/Modules/index.md +++ b/src/docs/Modules/index.md @@ -16,6 +16,6 @@ This section is the local source of truth for: - [Module types](Module-Types.md) - [Test Specification](Test-Specification.md) - [Versioning](Versioning.md) -- [Catalog](Catalog/index.md) +- [Catalog](Catalog/index.md) (auto-generated from PSModule repo metadata, release data, and README summaries) - [Process-PSModule](Process-PSModule/index.md) - [Dashboard Extension](Dashboard-Extension/index.md) From 4ec9d958a2cac0f19be93a3a2e7e3cb30de07e5d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:17:20 +0200 Subject: [PATCH 03/19] Align index script with GitHub module APIs Use supported GitHub module calls discovered locally: Get-GitHubRepository -Owner and Invoke-GitHubAPI for REST lookups. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/update-index/src/Helper.psm1 | 49 +------------------- 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index d486212..9a8dd44 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -39,7 +39,7 @@ function Show-RepoList { } LogGroup "Get repositories for organization [$Owner]" { - $rawRepos = Get-GitHubRepository -Organization $Owner -AdditionalProperty @( + $rawRepos = Get-GitHubRepository -Owner $Owner -AdditionalProperty @( 'description', 'default_branch', 'stargazers_count', @@ -159,41 +159,6 @@ function Get-PropertyValue { return $Default } -function Get-GitHubAccessToken { - [OutputType([string])] - [CmdletBinding()] - param() - - $context = Get-GitHubContext - if ($null -eq $context) { - return $null - } - - foreach ($propertyName in @('AccessToken', 'Token', 'token')) { - $property = $context.PSObject.Properties[$propertyName] - if ($null -eq $property) { - continue - } - - $token = $property.Value - if ($token -is [securestring]) { - $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($token) - try { - return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) - } - finally { - [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) - } - } - - if (-not [string]::IsNullOrWhiteSpace([string]$token)) { - return [string]$token - } - } - - return $null -} - function Invoke-GitHubApi { [OutputType([object])] [CmdletBinding()] @@ -202,18 +167,8 @@ function Invoke-GitHubApi { [string] $Uri ) - $headers = @{ - Accept = 'application/vnd.github+json' - 'User-Agent' = 'PSModule-Docs-UpdateIndex' - } - - $accessToken = Get-GitHubAccessToken - if (-not [string]::IsNullOrWhiteSpace($accessToken)) { - $headers.Authorization = "Bearer $accessToken" - } - try { - Invoke-RestMethod -Method Get -Uri $Uri -Headers $headers + Invoke-GitHubAPI -Method GET -Uri $Uri -ErrorAction Stop } catch { $statusCode = $null From 07138a2910fd84006da6854e8c82534e8e4a5f6a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:20:56 +0200 Subject: [PATCH 04/19] Harden GitHub API helper for local/module execution Fix module-qualified API invocation, unwrap GitHub module response envelopes, correct workflow URI interpolation, and fall back to anonymous mode when no context exists. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/update-index/src/Helper.psm1 | 52 ++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index 9a8dd44..85d9179 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -168,14 +168,60 @@ function Invoke-GitHubApi { ) try { - Invoke-GitHubAPI -Method GET -Uri $Uri -ErrorAction Stop + $apiParameters = @{ + Method = 'GET' + Uri = $Uri + ErrorAction = 'Stop' + } + + $availableContexts = Get-GitHubContext -ListAvailable -ErrorAction SilentlyContinue + if ($null -eq $availableContexts -or $availableContexts.Count -eq 0) { + $apiParameters.Anonymous = $true + } + + $rawResponse = GitHub\Invoke-GitHubAPI @apiParameters + if ($null -eq $rawResponse) { + return $null + } + + if ($rawResponse -is [array] -and $rawResponse.Count -gt 0 -and $rawResponse[0].PSObject.Properties['Response']) { + $payloadItems = @() + foreach ($item in $rawResponse) { + if ($null -eq $item.Response) { + continue + } + + if ($item.Response -is [array]) { + $payloadItems += $item.Response + } + else { + $payloadItems += , $item.Response + } + } + + if ($payloadItems.Count -eq 0) { + return $null + } + if ($payloadItems.Count -eq 1) { + return $payloadItems[0] + } + + return $payloadItems + } + + if ($rawResponse.PSObject.Properties['Response']) { + return $rawResponse.Response + } + + return $rawResponse } catch { $statusCode = $null if ($_.Exception.Response) { $statusCode = $_.Exception.Response.StatusCode.value__ } - if ($statusCode -eq 404) { + $errorText = $_ | Out-String + if ($statusCode -eq 404 -or $errorText -match 'StatusCode\s*:\s*404' -or $errorText -match '\(404\)') { return $null } @@ -331,7 +377,7 @@ function Get-WorkflowReference { foreach ($workflowPath in @('.github/workflows/workflow.yml', '.github/workflows/workflow.yaml')) { $encodedRef = [uri]::EscapeDataString($DefaultBranch) - $uri = "https://api.github.com/repos/$Owner/$Name/contents/$workflowPath?ref=$encodedRef" + $uri = "https://api.github.com/repos/$Owner/$Name/contents/${workflowPath}?ref=$encodedRef" $response = Invoke-GitHubApi -Uri $uri if ($null -eq $response) { continue From a69dbce9a167d585ee7d7d188b8fe67ead4f29bc Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:26:12 +0200 Subject: [PATCH 05/19] Support user-context local catalog testing Allow Show-RepoList to reuse non-App contexts locally, rely on supported repository properties, and suppress expected 404s for optional workflow files. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/update-index/src/Helper.psm1 | 34 +++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index 85d9179..fb2740f 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -34,18 +34,21 @@ function Show-RepoList { ) LogGroup "Connect to organization [$Owner]" { - Connect-GitHubApp -Organization $Owner -Default + $currentContext = Get-GitHubContext -ErrorAction SilentlyContinue + if ($null -eq $currentContext) { + Connect-GitHubApp -Organization $Owner -Default + } + elseif ($currentContext.AuthType -eq 'App') { + Connect-GitHubApp -Organization $Owner -Default + } + else { + Write-Output "Using existing GitHub context [$($currentContext.Name)] with auth type [$($currentContext.AuthType)]" + } Get-GitHubContext | Select-Object * | Format-List | Out-String } LogGroup "Get repositories for organization [$Owner]" { - $rawRepos = Get-GitHubRepository -Owner $Owner -AdditionalProperty @( - 'description', - 'default_branch', - 'stargazers_count', - 'open_issues_count', - 'html_url' - ) + $rawRepos = Get-GitHubRepository -Owner $Owner Write-Output "Found $($rawRepos.Count) repositories" $repos = $rawRepos | ForEach-Object { $rawRepo = $_ @@ -57,9 +60,9 @@ function Show-RepoList { Type = $type Description = $rawRepo.Description DefaultBranch = $rawRepo.DefaultBranch - Stars = $rawRepo.StargazersCount - OpenIssuesCount = $rawRepo.OpenIssuesCount - HtmlUrl = $rawRepo.HtmlUrl + Stars = $rawRepo.Stargazers + OpenIssuesCount = $rawRepo.OpenIssues + HtmlUrl = $rawRepo.Url } } } | Sort-Object Type, Name @@ -220,8 +223,15 @@ function Invoke-GitHubApi { if ($_.Exception.Response) { $statusCode = $_.Exception.Response.StatusCode.value__ } + $exceptionMessage = [string]$_.Exception.Message $errorText = $_ | Out-String - if ($statusCode -eq 404 -or $errorText -match 'StatusCode\s*:\s*404' -or $errorText -match '\(404\)') { + if ( + $statusCode -eq 404 -or + $exceptionMessage -match '\b404\b' -or + $exceptionMessage -match 'Not Found' -or + $errorText -match 'StatusCode\s*:\s*404' -or + $errorText -match '\(404\)' + ) { return $null } From d71a2038bd88e90e5d36cefb813b087412aeb45a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:31:23 +0200 Subject: [PATCH 06/19] Fix ScriptAnalyzer findings in helper Add help comments, align close-brace formatting, and add ShouldProcess support for generated catalog page writes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/update-index/src/Helper.psm1 | 98 ++++++++++++++++++-- 1 file changed, 88 insertions(+), 10 deletions(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index fb2740f..db6d181 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -37,11 +37,9 @@ function Show-RepoList { $currentContext = Get-GitHubContext -ErrorAction SilentlyContinue if ($null -eq $currentContext) { Connect-GitHubApp -Organization $Owner -Default - } - elseif ($currentContext.AuthType -eq 'App') { + } elseif ($currentContext.AuthType -eq 'App') { Connect-GitHubApp -Organization $Owner -Default - } - else { + } else { Write-Output "Using existing GitHub context [$($currentContext.Name)] with auth type [$($currentContext.AuthType)]" } Get-GitHubContext | Select-Object * | Format-List | Out-String @@ -131,6 +129,14 @@ function Update-MDSection { } function Get-PropertyValue { + <# + .SYNOPSIS + Gets the first non-empty property value from an object. + + .DESCRIPTION + Evaluates the provided property names in order and returns the first property + value that exists and is not null/whitespace. Returns the default value otherwise. + #> [OutputType([object])] [CmdletBinding()] param( @@ -163,6 +169,14 @@ function Get-PropertyValue { } function Invoke-GitHubApi { + <# + .SYNOPSIS + Invokes a GitHub REST API GET request. + + .DESCRIPTION + Calls the GitHub module API wrapper, auto-selects anonymous mode when no context + is configured, normalizes wrapped responses, and treats HTTP 404 as missing data. + #> [OutputType([object])] [CmdletBinding()] param( @@ -196,8 +210,7 @@ function Invoke-GitHubApi { if ($item.Response -is [array]) { $payloadItems += $item.Response - } - else { + } else { $payloadItems += , $item.Response } } @@ -217,8 +230,7 @@ function Invoke-GitHubApi { } return $rawResponse - } - catch { + } catch { $statusCode = $null if ($_.Exception.Response) { $statusCode = $_.Exception.Response.StatusCode.value__ @@ -241,6 +253,14 @@ function Invoke-GitHubApi { } function Get-RepositoryReadmeContent { + <# + .SYNOPSIS + Gets a repository README as plain text. + + .DESCRIPTION + Downloads the repository README from GitHub and decodes the returned + Base64 content to UTF-8 text. + #> [OutputType([string])] [CmdletBinding()] param( @@ -266,6 +286,14 @@ function Get-RepositoryReadmeContent { } function Get-MarkdownSummary { + <# + .SYNOPSIS + Extracts a short summary from markdown content. + + .DESCRIPTION + Removes common markdown formatting and returns the first non-empty paragraph, + suitable for compact previews. + #> [OutputType([string])] [CmdletBinding()] param( @@ -297,6 +325,14 @@ function Get-MarkdownSummary { } function ConvertTo-HtmlAttributeValue { + <# + .SYNOPSIS + Converts text to a safe HTML attribute preview value. + + .DESCRIPTION + Normalizes whitespace, truncates to a max length, and escapes special HTML + characters for use in attributes such as title. + #> [OutputType([string])] [CmdletBinding()] param( @@ -323,6 +359,14 @@ function ConvertTo-HtmlAttributeValue { } function Get-OpenItemCount { + <# + .SYNOPSIS + Gets the open issue or pull request count for a repository. + + .DESCRIPTION + Uses GitHub search API with a repository/type/state query and returns + the total count. + #> [OutputType([int])] [CmdletBinding()] param( @@ -346,6 +390,14 @@ function Get-OpenItemCount { } function Get-RepositoryVersion { + <# + .SYNOPSIS + Gets a repository's latest version identifier. + + .DESCRIPTION + Returns the latest release tag/name when available, otherwise falls back + to the most recent tag, or N/A. + #> [OutputType([string])] [CmdletBinding()] param( @@ -374,6 +426,14 @@ function Get-RepositoryVersion { } function Get-WorkflowReference { + <# + .SYNOPSIS + Gets the Process-PSModule workflow reference used by a repository. + + .DESCRIPTION + Scans common workflow entry files on the default branch and extracts the + `@ref` from `uses: PSModule/Process-PSModule/...@ref` if present. + #> [OutputType([string])] [CmdletBinding()] param( @@ -409,6 +469,14 @@ function Get-WorkflowReference { } function Get-ProcessReferenceStatus { + <# + .SYNOPSIS + Computes status of a Process-PSModule workflow reference. + + .DESCRIPTION + Classifies a workflow reference value relative to the latest available + Process-PSModule version. + #> [OutputType([string])] [CmdletBinding()] param( @@ -451,7 +519,15 @@ function Get-ProcessReferenceStatus { } function New-ModuleCatalogPage { - [CmdletBinding()] + <# + .SYNOPSIS + Creates or updates a generated module catalog page. + + .DESCRIPTION + Builds markdown content from module metadata and writes it to the + target page path. + #> + [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [string] $Path, @@ -481,7 +557,9 @@ $($ModuleData.About) [View source README](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)#readme) "@ - Set-Content -Path $Path -Value $content + if ($PSCmdlet.ShouldProcess($Path, 'Write module catalog page')) { + Set-Content -Path $Path -Value $content + } } function Update-ActionList { From 1db00b2af81c7781a33f7bcb816575ba2f1032e3 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:46:49 +0200 Subject: [PATCH 07/19] Increase docs schedule frequency Change Docs workflow cron to run every 5 minutes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml index f129fb6..6b3d437 100644 --- a/.github/workflows/Docs.yml +++ b/.github/workflows/Docs.yml @@ -3,7 +3,7 @@ name: Docs on: workflow_dispatch: schedule: - - cron: '0 4 * * 1' + - cron: '*/5 * * * *' push: branches: - main From cbab6c9c72cab83665b2cb881a8bd825c44dec29 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:49:49 +0200 Subject: [PATCH 08/19] Run docs lint only on PRs Gate lint job to pull_request events and remove lint as a publish dependency so scheduled/push refreshes only require build. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml index 6b3d437..433b71e 100644 --- a/.github/workflows/Docs.yml +++ b/.github/workflows/Docs.yml @@ -30,6 +30,7 @@ permissions: jobs: lint: name: Lint + if: github.event_name == 'pull_request' runs-on: ubuntu-24.04 permissions: contents: read @@ -94,7 +95,7 @@ jobs: publish: name: Publish - needs: [build, lint] + needs: [build] if: github.event_name != 'pull_request' runs-on: ubuntu-24.04 environment: From e09330790e42cadd6db772cad6de237b43992666 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:53:24 +0200 Subject: [PATCH 09/19] Keep publish gated by lint and align helper style Restore publish dependency on lint (while allowing skipped lint) and replace Out-Null pipeline usage in catalog helper to match standards. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/update-index/src/Helper.psm1 | 2 +- .github/workflows/Docs.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index db6d181..5ad06f1 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -646,7 +646,7 @@ function Update-ModuleList { $catalogFolderPath = Join-Path 'src\docs\Modules\Catalog' 'Repositories' if (-not (Test-Path $catalogFolderPath)) { - New-Item -Path $catalogFolderPath -ItemType Directory | Out-Null + $null = New-Item -Path $catalogFolderPath -ItemType Directory } $processLatestVersion = Get-RepositoryVersion -Owner 'PSModule' -Name 'Process-PSModule' diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml index 433b71e..b585c61 100644 --- a/.github/workflows/Docs.yml +++ b/.github/workflows/Docs.yml @@ -95,8 +95,8 @@ jobs: publish: name: Publish - needs: [build] - if: github.event_name != 'pull_request' + needs: [build, lint] + if: github.event_name != 'pull_request' && (needs.lint.result == 'success' || needs.lint.result == 'skipped') runs-on: ubuntu-24.04 environment: name: github-pages From d64033009d2d893c967fed2c7a450692a37c8980 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 20:57:10 +0200 Subject: [PATCH 10/19] Remove lint success condition from publish job trigger --- .github/workflows/Docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml index b585c61..1cd4c08 100644 --- a/.github/workflows/Docs.yml +++ b/.github/workflows/Docs.yml @@ -96,7 +96,7 @@ jobs: publish: name: Publish needs: [build, lint] - if: github.event_name != 'pull_request' && (needs.lint.result == 'success' || needs.lint.result == 'skipped') + if: github.event_name != 'pull_request' runs-on: ubuntu-24.04 environment: name: github-pages From 872ea90e0091f697c0ce2c046c92f1143086909c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 21:00:03 +0200 Subject: [PATCH 11/19] Version module catalog templates Store legacy catalog layout as v1 templates, move current layout to v2 templates, and render catalog from v2 templates by default. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/update-index/src/Helper.psm1 | 63 ++++++++++++------- .../templates/module-catalog/v1-row.html | 11 ++++ .../templates/module-catalog/v1-table.html | 9 +++ .../templates/module-catalog/v2-row.html | 8 +++ .../templates/module-catalog/v2-table.html | 12 ++++ 5 files changed, 79 insertions(+), 24 deletions(-) create mode 100644 .github/actions/update-index/templates/module-catalog/v1-row.html create mode 100644 .github/actions/update-index/templates/module-catalog/v1-table.html create mode 100644 .github/actions/update-index/templates/module-catalog/v2-row.html create mode 100644 .github/actions/update-index/templates/module-catalog/v2-table.html diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index 5ad06f1..25b10ec 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -128,6 +128,24 @@ function Update-MDSection { } } +function Get-TemplateContent { + <# + .SYNOPSIS + Reads a template file as raw text. + + .DESCRIPTION + Loads a UTF-8 template file from disk and returns the complete content as a string. + #> + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Path + ) + + Get-Content -Path $Path -Raw +} + function Get-PropertyValue { <# .SYNOPSIS @@ -640,6 +658,13 @@ function Update-ModuleList { $Repos = Show-RepoList } + $moduleCatalogTemplateVersion = 'v2' + $moduleCatalogTemplateFolder = Join-Path (Join-Path $PSScriptRoot '..') 'templates\module-catalog' + $moduleCatalogRowTemplatePath = Join-Path $moduleCatalogTemplateFolder "$moduleCatalogTemplateVersion-row.html" + $moduleCatalogTableTemplatePath = Join-Path $moduleCatalogTemplateFolder "$moduleCatalogTemplateVersion-table.html" + $moduleCatalogRowTemplate = Get-TemplateContent -Path $moduleCatalogRowTemplatePath + $moduleCatalogTableTemplate = Get-TemplateContent -Path $moduleCatalogTableTemplatePath + $moduleRepos = $Repos | Where-Object { $_.Type -eq 'Module' -and $_.Owner -eq 'PSModule' } | Sort-Object Name @@ -701,32 +726,22 @@ function Update-ModuleList { } New-ModuleCatalogPage -Path $modulePagePath -ModuleData $moduleData - $moduleTableRows += @" - - $name - $version - $processReference
$processStatus - $issues - $pullRequests - $stars - -"@ + $moduleTableRow = $moduleCatalogRowTemplate + $moduleTableRow = $moduleTableRow.Replace('{{ MODULE_PAGE_LINK }}', $modulePageRelativeLink) + $moduleTableRow = $moduleTableRow.Replace('{{ TITLE_SUMMARY }}', $titleSummary) + $moduleTableRow = $moduleTableRow.Replace('{{ NAME }}', $name) + $moduleTableRow = $moduleTableRow.Replace('{{ VERSION }}', $version) + $moduleTableRow = $moduleTableRow.Replace('{{ PROCESS_REFERENCE }}', $processReference) + $moduleTableRow = $moduleTableRow.Replace('{{ PROCESS_STATUS }}', $processStatus) + $moduleTableRow = $moduleTableRow.Replace('{{ OWNER }}', $owner) + $moduleTableRow = $moduleTableRow.Replace('{{ ISSUES }}', [string]$issues) + $moduleTableRow = $moduleTableRow.Replace('{{ PULL_REQUESTS }}', [string]$pullRequests) + $moduleTableRow = $moduleTableRow.Replace('{{ STARS }}', [string]$stars) + $moduleTableRows += $moduleTableRow.TrimEnd() + $moduleTableRows += [Environment]::NewLine } - $moduleTable = @" - - - - - - - - - - -$moduleTableRows
NameVersionProcessVersionIssuesPRsStars
- -"@ + $moduleTable = $moduleCatalogTableTemplate.Replace('{{ ROWS }}', $moduleTableRows.TrimEnd()) Update-MDSection -Path '.\src\docs\Modules\Catalog\index.md' -Name 'MODULE_CATALOG' -Content $moduleTable } diff --git a/.github/actions/update-index/templates/module-catalog/v1-row.html b/.github/actions/update-index/templates/module-catalog/v1-row.html new file mode 100644 index 0000000..2710e11 --- /dev/null +++ b/.github/actions/update-index/templates/module-catalog/v1-row.html @@ -0,0 +1,11 @@ + + {{ NAME }} + {{ DESCRIPTION }} +
+ Issues | + PRs | + Stars | + PS Gallery + + {{ VERSION }} + diff --git a/.github/actions/update-index/templates/module-catalog/v1-table.html b/.github/actions/update-index/templates/module-catalog/v1-table.html new file mode 100644 index 0000000..fe61d66 --- /dev/null +++ b/.github/actions/update-index/templates/module-catalog/v1-table.html @@ -0,0 +1,9 @@ + + + + + + + +{{ ROWS }}
NameDescriptionVersion
+ diff --git a/.github/actions/update-index/templates/module-catalog/v2-row.html b/.github/actions/update-index/templates/module-catalog/v2-row.html new file mode 100644 index 0000000..e4ec41b --- /dev/null +++ b/.github/actions/update-index/templates/module-catalog/v2-row.html @@ -0,0 +1,8 @@ + + {{ NAME }} + {{ VERSION }} + {{ PROCESS_REFERENCE }}
{{ PROCESS_STATUS }} + {{ ISSUES }} + {{ PULL_REQUESTS }} + {{ STARS }} + diff --git a/.github/actions/update-index/templates/module-catalog/v2-table.html b/.github/actions/update-index/templates/module-catalog/v2-table.html new file mode 100644 index 0000000..8bdc60b --- /dev/null +++ b/.github/actions/update-index/templates/module-catalog/v2-table.html @@ -0,0 +1,12 @@ + + + + + + + + + + +{{ ROWS }}
NameVersionProcessVersionIssuesPRsStars
+ From d9bade0f763f2fde94d441e87ecac9ade52ebcfe Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 21:02:54 +0200 Subject: [PATCH 12/19] Restore full legacy v1 badge template Preserve the original v1 module catalog row structure with inline encoded SVG badge links instead of the simplified placeholder version. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../templates/module-catalog/v1-row.html | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/actions/update-index/templates/module-catalog/v1-row.html b/.github/actions/update-index/templates/module-catalog/v1-row.html index 2710e11..be2fac5 100644 --- a/.github/actions/update-index/templates/module-catalog/v1-row.html +++ b/.github/actions/update-index/templates/module-catalog/v1-row.html @@ -2,10 +2,15 @@ {{ NAME }} {{ DESCRIPTION }}
- Issues | - PRs | - Stars | - PS Gallery + GitHub Issues + GitHub Pull Requests + GitHub Stars + GitHub Watchers + GitHub Forks + PowerShell Gallery Downloads + + + GitHub release (with filter) + PowerShell Gallery Version - {{ VERSION }} From e1ee9c91e64ba0a63147b68b671d4b3afc40fd5a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 21:04:14 +0200 Subject: [PATCH 13/19] Add icons to v2 catalog headers Add visual icons to Version, ProcessVersion, Issues, PRs, and Stars column headers in the v2 module catalog template. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../templates/module-catalog/v2-table.html | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/actions/update-index/templates/module-catalog/v2-table.html b/.github/actions/update-index/templates/module-catalog/v2-table.html index 8bdc60b..f31e8cd 100644 --- a/.github/actions/update-index/templates/module-catalog/v2-table.html +++ b/.github/actions/update-index/templates/module-catalog/v2-table.html @@ -2,11 +2,10 @@ - - - - - + + + + + {{ ROWS }}
NameVersionProcessVersionIssuesPRsStars🏷️ Version⚙️ ProcessVersion❗ Issues🔀 PRs⭐ Stars
- From c56cbe6c7f14ab8d10a2f29be1e70ddb92a99e6f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 21:19:33 +0200 Subject: [PATCH 14/19] Use PSModule media icons in v2 headers Replace text/emoji v2 numeric column headers with icon-only images from PSModule/.github media and include alt/title text for accessibility. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../templates/module-catalog/v2-table.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/update-index/templates/module-catalog/v2-table.html b/.github/actions/update-index/templates/module-catalog/v2-table.html index f31e8cd..d91223a 100644 --- a/.github/actions/update-index/templates/module-catalog/v2-table.html +++ b/.github/actions/update-index/templates/module-catalog/v2-table.html @@ -2,10 +2,10 @@ - - - - - + + + + + {{ ROWS }}
Name🏷️ Version⚙️ ProcessVersion❗ Issues🔀 PRs⭐ StarsVersionProcess versionIssuesPull requestsStars
From f34aad34958f00e46ee15754ed15825aff586717 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 21:21:01 +0200 Subject: [PATCH 15/19] Vendor catalog header icons locally Copy module catalog header icons into repo assets and update v2 template to use local relative paths instead of external raw.githubusercontent URLs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../templates/module-catalog/v2-table.html | 10 +++++----- src/docs/assets/images/module-catalog/githubissues.svg | 6 ++++++ .../images/module-catalog/githubpullrequests.svg | 6 ++++++ src/docs/assets/images/module-catalog/githubstars.svg | 6 ++++++ src/docs/assets/images/module-catalog/githubtags.svg | 6 ++++++ .../module-catalog/package-variant-closed-check.svg | 1 + 6 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 src/docs/assets/images/module-catalog/githubissues.svg create mode 100644 src/docs/assets/images/module-catalog/githubpullrequests.svg create mode 100644 src/docs/assets/images/module-catalog/githubstars.svg create mode 100644 src/docs/assets/images/module-catalog/githubtags.svg create mode 100644 src/docs/assets/images/module-catalog/package-variant-closed-check.svg diff --git a/.github/actions/update-index/templates/module-catalog/v2-table.html b/.github/actions/update-index/templates/module-catalog/v2-table.html index d91223a..d0f4102 100644 --- a/.github/actions/update-index/templates/module-catalog/v2-table.html +++ b/.github/actions/update-index/templates/module-catalog/v2-table.html @@ -2,10 +2,10 @@ - - - - - + + + + + {{ ROWS }}
NameVersionProcess versionIssuesPull requestsStarsVersionProcess versionIssuesPull requestsStars
diff --git a/src/docs/assets/images/module-catalog/githubissues.svg b/src/docs/assets/images/module-catalog/githubissues.svg new file mode 100644 index 0000000..496e94f --- /dev/null +++ b/src/docs/assets/images/module-catalog/githubissues.svg @@ -0,0 +1,6 @@ + + GitHub Issues + + + diff --git a/src/docs/assets/images/module-catalog/githubpullrequests.svg b/src/docs/assets/images/module-catalog/githubpullrequests.svg new file mode 100644 index 0000000..2d36399 --- /dev/null +++ b/src/docs/assets/images/module-catalog/githubpullrequests.svg @@ -0,0 +1,6 @@ + + GitHub Pull Requests + + diff --git a/src/docs/assets/images/module-catalog/githubstars.svg b/src/docs/assets/images/module-catalog/githubstars.svg new file mode 100644 index 0000000..bb41f0a --- /dev/null +++ b/src/docs/assets/images/module-catalog/githubstars.svg @@ -0,0 +1,6 @@ + + GitHub Stars + + diff --git a/src/docs/assets/images/module-catalog/githubtags.svg b/src/docs/assets/images/module-catalog/githubtags.svg new file mode 100644 index 0000000..9156a0f --- /dev/null +++ b/src/docs/assets/images/module-catalog/githubtags.svg @@ -0,0 +1,6 @@ + + GitHub Tags + + diff --git a/src/docs/assets/images/module-catalog/package-variant-closed-check.svg b/src/docs/assets/images/module-catalog/package-variant-closed-check.svg new file mode 100644 index 0000000..162c7ee --- /dev/null +++ b/src/docs/assets/images/module-catalog/package-variant-closed-check.svg @@ -0,0 +1 @@ + \ No newline at end of file From 8487dd4e622258b903fd6ccb5941b94b4ab2ab57 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 21:22:39 +0200 Subject: [PATCH 16/19] Match process icon color with catalog icons Set package-variant-closed-check.svg fill to #848D97 to align with the other module catalog header icons. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../images/module-catalog/package-variant-closed-check.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/assets/images/module-catalog/package-variant-closed-check.svg b/src/docs/assets/images/module-catalog/package-variant-closed-check.svg index 162c7ee..a14f09e 100644 --- a/src/docs/assets/images/module-catalog/package-variant-closed-check.svg +++ b/src/docs/assets/images/module-catalog/package-variant-closed-check.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 5ef6e151bb91e35d38d7619dfa9d987550000146 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 21:24:08 +0200 Subject: [PATCH 17/19] Use Primer gear icon for process column Replace the process-version header icon with a local Primer-style cogwheel SVG and keep the shared catalog icon color (#848D97). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../images/module-catalog/package-variant-closed-check.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/assets/images/module-catalog/package-variant-closed-check.svg b/src/docs/assets/images/module-catalog/package-variant-closed-check.svg index a14f09e..f3dc43d 100644 --- a/src/docs/assets/images/module-catalog/package-variant-closed-check.svg +++ b/src/docs/assets/images/module-catalog/package-variant-closed-check.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 746c24d5cec2553bccab9b6117f65eee93972ae6 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 21:26:56 +0200 Subject: [PATCH 18/19] Use original Primer icon sources Replace module catalog issue, PR, star, and tag SVGs with the upstream Primer Octicons shapes while keeping the local color override at #848D97. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/docs/assets/images/module-catalog/githubissues.svg | 7 +------ .../assets/images/module-catalog/githubpullrequests.svg | 7 +------ src/docs/assets/images/module-catalog/githubstars.svg | 7 +------ src/docs/assets/images/module-catalog/githubtags.svg | 7 +------ 4 files changed, 4 insertions(+), 24 deletions(-) diff --git a/src/docs/assets/images/module-catalog/githubissues.svg b/src/docs/assets/images/module-catalog/githubissues.svg index 496e94f..9ff6364 100644 --- a/src/docs/assets/images/module-catalog/githubissues.svg +++ b/src/docs/assets/images/module-catalog/githubissues.svg @@ -1,6 +1 @@ - - GitHub Issues - - - + diff --git a/src/docs/assets/images/module-catalog/githubpullrequests.svg b/src/docs/assets/images/module-catalog/githubpullrequests.svg index 2d36399..21a334a 100644 --- a/src/docs/assets/images/module-catalog/githubpullrequests.svg +++ b/src/docs/assets/images/module-catalog/githubpullrequests.svg @@ -1,6 +1 @@ - - GitHub Pull Requests - - + diff --git a/src/docs/assets/images/module-catalog/githubstars.svg b/src/docs/assets/images/module-catalog/githubstars.svg index bb41f0a..9073165 100644 --- a/src/docs/assets/images/module-catalog/githubstars.svg +++ b/src/docs/assets/images/module-catalog/githubstars.svg @@ -1,6 +1 @@ - - GitHub Stars - - + diff --git a/src/docs/assets/images/module-catalog/githubtags.svg b/src/docs/assets/images/module-catalog/githubtags.svg index 9156a0f..d20df96 100644 --- a/src/docs/assets/images/module-catalog/githubtags.svg +++ b/src/docs/assets/images/module-catalog/githubtags.svg @@ -1,6 +1 @@ - - GitHub Tags - - + From d7907923416a57c26ffbf4e922493f118df6caaf Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 19 Jul 2026 21:38:51 +0200 Subject: [PATCH 19/19] Disable doctype-first for HTML fragments Mark module catalog row/table templates as HTMLHint fragments so doctype-first does not fail on partial templates that are intentionally embedded snippets. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../actions/update-index/templates/module-catalog/v1-row.html | 1 + .../actions/update-index/templates/module-catalog/v1-table.html | 2 +- .../actions/update-index/templates/module-catalog/v2-row.html | 1 + .../actions/update-index/templates/module-catalog/v2-table.html | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/actions/update-index/templates/module-catalog/v1-row.html b/.github/actions/update-index/templates/module-catalog/v1-row.html index be2fac5..5350c3b 100644 --- a/.github/actions/update-index/templates/module-catalog/v1-row.html +++ b/.github/actions/update-index/templates/module-catalog/v1-row.html @@ -1,3 +1,4 @@ + {{ NAME }} {{ DESCRIPTION }} diff --git a/.github/actions/update-index/templates/module-catalog/v1-table.html b/.github/actions/update-index/templates/module-catalog/v1-table.html index fe61d66..932250e 100644 --- a/.github/actions/update-index/templates/module-catalog/v1-table.html +++ b/.github/actions/update-index/templates/module-catalog/v1-table.html @@ -1,3 +1,4 @@ + @@ -6,4 +7,3 @@ {{ ROWS }}
Version
- diff --git a/.github/actions/update-index/templates/module-catalog/v2-row.html b/.github/actions/update-index/templates/module-catalog/v2-row.html index e4ec41b..4621275 100644 --- a/.github/actions/update-index/templates/module-catalog/v2-row.html +++ b/.github/actions/update-index/templates/module-catalog/v2-row.html @@ -1,3 +1,4 @@ + {{ NAME }} {{ VERSION }} diff --git a/.github/actions/update-index/templates/module-catalog/v2-table.html b/.github/actions/update-index/templates/module-catalog/v2-table.html index d0f4102..2429e73 100644 --- a/.github/actions/update-index/templates/module-catalog/v2-table.html +++ b/.github/actions/update-index/templates/module-catalog/v2-table.html @@ -1,3 +1,4 @@ +