mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
8d24c5680b
.github/scripts/Get-Endpoints.ps1 defines the storage account (blob and table derived from its name), the containers, the AdminConfiguration row, the legacy mirror, the download alias, API, MCP, portal, www, docs and the timestamp server. Workflows load it once per job; the script publisher and the local release build call it; the dev-render anchors are built from the alias entry. deploy-web takes NEXT_PUBLIC_API_BASE_URL and NEXT_PUBLIC_PLATFORM_STATS_MANIFEST_URL from the registry instead of repository variables and refuses an empty value. A new Workflow gates job fails on any host spelled out in a workflow or CI helper; the enforced list is derived from the registry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
85 lines
3.1 KiB
PowerShell
85 lines
3.1 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Fails when a workflow or a CI helper spells out a host instead of reading Get-Endpoints.ps1.
|
|
|
|
.DESCRIPTION
|
|
The CI counterpart of the URL-registry guard tests (HardcodedUrlGuardTests,
|
|
hardcodedUrls.guard.test.ts, hardcoded-urls.guard.test.ts). Enforced: every host the registry
|
|
defines -- derived from it, so the list cannot fall behind -- plus any Azure storage, App Service
|
|
or autopilotmonitor.com host, so a new or misspelled account is caught as well.
|
|
|
|
Scans .github/workflows/*.yml and .github/scripts/*.ps1 except the registry itself. Comment lines
|
|
and PowerShell block comments do not count: comments may cite URLs.
|
|
|
|
.PARAMETER Root
|
|
Repository root to scan. Defaults to the parent of .github/scripts.
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$Root
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
if (-not $Root) {
|
|
$Root = (Resolve-Path (Join-Path $PSScriptRoot '../..')).Path
|
|
}
|
|
|
|
$endpoints = & (Join-Path $PSScriptRoot 'Get-Endpoints.ps1')
|
|
$registryHosts = $endpoints.Values | ForEach-Object { ([uri]$_).Host } | Sort-Object -Unique
|
|
$patterns = @($registryHosts | ForEach-Object { [regex]::Escape($_) }) + @(
|
|
'[a-z0-9-]+\.(blob|table|queue|file)\.core\.windows\.net'
|
|
'[a-z0-9-]+\.azurewebsites\.net'
|
|
'([a-z0-9-]+\.)*autopilotmonitor\.com'
|
|
)
|
|
$hostPattern = [regex]::new('(' + ($patterns -join '|') + ')', 'IgnoreCase')
|
|
|
|
$files = @(
|
|
Get-ChildItem -Path (Join-Path $Root '.github/workflows') -File -Filter '*.yml'
|
|
Get-ChildItem -Path (Join-Path $Root '.github/workflows') -File -Filter '*.yaml'
|
|
Get-ChildItem -Path (Join-Path $Root '.github/scripts') -File -Filter '*.ps1' |
|
|
Where-Object Name -ne 'Get-Endpoints.ps1'
|
|
)
|
|
|
|
$findings = 0
|
|
foreach ($file in $files) {
|
|
$relative = [System.IO.Path]::GetRelativePath($Root, $file.FullName) -replace '\\', '/'
|
|
$isPowerShell = $file.Extension -eq '.ps1'
|
|
$inBlock = $false
|
|
$lineNumber = 0
|
|
foreach ($line in [System.IO.File]::ReadAllLines($file.FullName)) {
|
|
$lineNumber++
|
|
$code = $line
|
|
if ($isPowerShell) {
|
|
if ($inBlock) {
|
|
$end = $code.IndexOf('#>')
|
|
if ($end -lt 0) { continue }
|
|
$code = $code.Substring($end + 2)
|
|
$inBlock = $false
|
|
}
|
|
$start = $code.IndexOf('<#')
|
|
if ($start -ge 0) {
|
|
$end = $code.IndexOf('#>', $start + 2)
|
|
if ($end -lt 0) {
|
|
$code = $code.Substring(0, $start)
|
|
$inBlock = $true
|
|
} else {
|
|
$code = $code.Remove($start, $end + 2 - $start)
|
|
}
|
|
}
|
|
}
|
|
if ($code.TrimStart().StartsWith('#')) { continue }
|
|
|
|
$match = $hostPattern.Match($code)
|
|
if ($match.Success) {
|
|
Write-Host "::error file=$relative,line=$lineNumber::$($match.Value) is spelled out here -- take it from .github/scripts/Get-Endpoints.ps1."
|
|
$findings++
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($findings -gt 0) {
|
|
throw "$findings host literal(s) outside the endpoint registry."
|
|
}
|
|
Write-Host "No host literal outside .github/scripts/Get-Endpoints.ps1 ($($files.Count) files scanned)."
|