Deploy-Brass: extend manifest verification to all fields
The previous check covered version, launcherVersion/Url, and a single
sampled self-hosted URL. Expanded to cover every field that has ever
been a foot-gun:
Required (must always be present and match pack.lock.json):
name, version, minecraft.version, loader.type, loader.version,
launcherVersion, launcherUrl
Optional but consistency-checked: if pack.lock.json declares the
field, the manifest MUST also have it (and defaultServer must include
a non-empty ip). Catches the case where someone removes the field
from pack.lock or Build-Pack drops it silently:
panelUrl, defaultShader, defaultServer
files[]: every entry validated for path/url/sha1/size shape; every
self-hosted (non-CDN) url checked for the expected host. Catches
partial-update bugs where some URLs migrate hosts but others don't.
URL host checks use the configured $ManifestPublicUrl host as the
source of truth; CDN-hosted mods (modrinth/forgecdn/curseforge) are
intentionally exempt.
This commit is contained in:
+50
-12
@@ -259,30 +259,68 @@ if ($shouldRunPack -and -not $DryRun -and $ManifestPublicUrl) {
|
||||
catch { throw "Failed to fetch deployed manifest: $($_.Exception.Message)" }
|
||||
|
||||
$expectedHost = ([uri]$ManifestPublicUrl).Host
|
||||
$problems = @()
|
||||
|
||||
$lock = Get-Content (Join-Path $repoRoot 'pack\pack.lock.json') -Raw | ConvertFrom-Json
|
||||
if ($live.version -ne $lock.version) {
|
||||
$problems += "version mismatch: live=$($live.version), local=$($lock.version)"
|
||||
}
|
||||
$problems = @()
|
||||
$hasLockField = { param($name) ($lock.PSObject.Properties.Name -contains $name) -and $lock.$name }
|
||||
|
||||
# ── Top-level required fields (sourced from pack.lock) ──
|
||||
if (-not $live.name) { $problems += "name missing" }
|
||||
elseif ($live.name -ne $lock.name) { $problems += "name mismatch: live=$($live.name), local=$($lock.name)" }
|
||||
if (-not $live.version) { $problems += "version missing" }
|
||||
elseif ($live.version -ne $lock.version) { $problems += "version mismatch: live=$($live.version), local=$($lock.version)" }
|
||||
if (-not $live.minecraft.version) { $problems += "minecraft.version missing" }
|
||||
elseif ($live.minecraft.version -ne $lock.minecraft) { $problems += "minecraft.version mismatch: live=$($live.minecraft.version), local=$($lock.minecraft)" }
|
||||
if (-not $live.loader.type) { $problems += "loader.type missing" }
|
||||
elseif ($live.loader.type -ne $lock.loader.type) { $problems += "loader.type mismatch: live=$($live.loader.type), local=$($lock.loader.type)" }
|
||||
if (-not $live.loader.version) { $problems += "loader.version missing" }
|
||||
elseif ($live.loader.version -ne $lock.loader.version) { $problems += "loader.version mismatch: live=$($live.loader.version), local=$($lock.loader.version)" }
|
||||
|
||||
# ── Launcher metadata (always required once a launcher has ever shipped) ──
|
||||
if (-not $live.launcherVersion) { $problems += "launcherVersion missing (old launchers won't see upgrade banner)" }
|
||||
if (-not $live.launcherUrl) { $problems += "launcherUrl missing" }
|
||||
if ($live.launcherUrl -and ([uri]$live.launcherUrl).Host -ne $expectedHost) {
|
||||
$problems += "launcherUrl host is $([uri]$live.launcherUrl).Host, expected $expectedHost"
|
||||
$problems += "launcherUrl host is $(([uri]$live.launcherUrl).Host), expected $expectedHost"
|
||||
}
|
||||
# Sample a self-hosted file (skip CDN-hosted mods)
|
||||
$local = $live.files | Where-Object { $_.url -notmatch 'modrinth|forgecdn|curseforge' } | Select-Object -First 1
|
||||
if ($local -and ([uri]$local.url).Host -ne $expectedHost) {
|
||||
$problems += "self-hosted file URL host is $([uri]$local.url).Host, expected $expectedHost (path: $($local.path))"
|
||||
|
||||
# ── Optional fields: consistency check. If pack.lock has it, manifest must too. ──
|
||||
if ((& $hasLockField 'panelUrl') -and -not $live.panelUrl) {
|
||||
$problems += "panelUrl missing from manifest but set in pack.lock.json (friend whitelist requests will fail)"
|
||||
}
|
||||
if ((& $hasLockField 'defaultShader') -and -not $live.defaultShader) {
|
||||
$problems += "defaultShader missing from manifest but set in pack.lock.json"
|
||||
}
|
||||
if ((& $hasLockField 'defaultServer') -and (-not $live.defaultServer -or -not $live.defaultServer.ip)) {
|
||||
$problems += "defaultServer missing/incomplete in manifest but set in pack.lock.json"
|
||||
}
|
||||
|
||||
# ── files[]: every entry has the shape clients depend on; self-hosted URLs use expected host ──
|
||||
if (-not $live.files -or $live.files.Count -eq 0) {
|
||||
$problems += "files array is empty"
|
||||
} else {
|
||||
$i = 0
|
||||
foreach ($f in $live.files) {
|
||||
if (-not $f.path) { $problems += "files[$i].path missing" }
|
||||
if (-not $f.url) { $problems += "files[$i].url missing (path=$($f.path))" }
|
||||
if (-not $f.sha1 -or $f.sha1.Length -ne 40) { $problems += "files[$i].sha1 invalid (path=$($f.path))" }
|
||||
if (-not $f.size -or $f.size -le 0) { $problems += "files[$i].size invalid (path=$($f.path))" }
|
||||
# Self-hosted (non-CDN) URLs must use the expected host. CDN mods are exempt.
|
||||
if ($f.url -and $f.url -notmatch 'modrinth|forgecdn|curseforge') {
|
||||
$h = ([uri]$f.url).Host
|
||||
if ($h -ne $expectedHost) {
|
||||
$problems += "files[$i] self-hosted URL host is $h, expected $expectedHost (path=$($f.path))"
|
||||
}
|
||||
}
|
||||
$i++
|
||||
}
|
||||
}
|
||||
|
||||
if ($problems.Count -gt 0) {
|
||||
Write-Host ""
|
||||
Write-Host "DEPLOYED MANIFEST FAILED VERIFICATION:" -ForegroundColor Red
|
||||
foreach ($p in $problems) { Write-Host " - $p" -ForegroundColor Red }
|
||||
throw "Deployed manifest is missing required fields. Fix and redeploy."
|
||||
throw "Deployed manifest has $($problems.Count) issue(s). Fix and redeploy."
|
||||
}
|
||||
Write-Host (" version={0} launcherVersion={1} ok" -f $live.version, $live.launcherVersion) -ForegroundColor DarkGray
|
||||
Write-Host (" version={0} launcherVersion={1} files={2} ok" -f $live.version, $live.launcherVersion, $live.files.Count) -ForegroundColor DarkGray
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user