修复前端发布缓存完整性与资源清单覆盖
This commit is contained in:
parent
cb5b7fb680
commit
339a67efde
@ -29,6 +29,7 @@ $dependencyFingerprintPath = Join-Path $frontendCacheRoot 'node-modules.sha'
|
||||
$jsManifestCachePath = Join-Path $frontendCacheRoot 'manifest-js.json'
|
||||
$cssManifestCachePath = Join-Path $frontendCacheRoot 'manifest-css.json'
|
||||
$cachedVendorPath = Join-Path $frontendOutputRoot 'vendor'
|
||||
$outputFingerprintPath = Join-Path $frontendCacheRoot 'frontend-output.sha'
|
||||
|
||||
function Invoke-Native {
|
||||
param(
|
||||
@ -147,6 +148,10 @@ $cssFingerprintInputs = @(
|
||||
$jsFingerprint = "$NodeVersion|$TerserWorkers|$(Get-PathFingerprint $jsFingerprintInputs)"
|
||||
$cssFingerprint = "$NodeVersion|$(Get-PathFingerprint $cssFingerprintInputs)"
|
||||
$dependencyFingerprint = "$NodeVersion|$packageLockHash"
|
||||
$outputCacheValid = (Test-Path -LiteralPath $outputFingerprintPath) -and
|
||||
(Test-Path -LiteralPath $frontendOutputRoot) -and
|
||||
((Get-Content -Raw -LiteralPath $outputFingerprintPath).Trim() -eq
|
||||
(Get-PathFingerprint @('.caiwu-build/public')))
|
||||
|
||||
$jsCacheValid = Test-CacheFingerprint `
|
||||
-FingerprintPath $jsFingerprintPath `
|
||||
@ -170,6 +175,12 @@ $cssCacheValid = Test-CacheFingerprint `
|
||||
$cssManifestCachePath
|
||||
)
|
||||
|
||||
if (-not $outputCacheValid) {
|
||||
$jsCacheValid = $false
|
||||
$cssCacheValid = $false
|
||||
Write-Host 'Frontend output integrity is missing or changed. Rebuilding assets.'
|
||||
}
|
||||
|
||||
if ($jsCacheValid -and $cssCacheValid) {
|
||||
Write-Host 'Frontend inputs unchanged. Reusing JavaScript, CSS, and dependency caches.'
|
||||
|
||||
@ -337,12 +348,19 @@ try {
|
||||
foreach ($manifestPath in @($jsManifestCachePath, $cssManifestCachePath)) {
|
||||
$manifest = Get-Content -Raw -LiteralPath $manifestPath | ConvertFrom-Json
|
||||
foreach ($property in $manifest.PSObject.Properties) {
|
||||
if ($manifestPath -eq $jsManifestCachePath -and $property.Name -notlike '*.js') { continue }
|
||||
if ($manifestPath -eq $cssManifestCachePath -and $property.Name -notlike '*.css') { continue }
|
||||
$mergedManifest[$property.Name] = $property.Value
|
||||
}
|
||||
}
|
||||
$mergedManifestJson = $mergedManifest | ConvertTo-Json
|
||||
Write-Utf8NoBom -Path (Join-Path $frontendOutputRoot 'mix-manifest.json') -Value $mergedManifestJson
|
||||
Write-Utf8NoBom -Path $publicManifestPath -Value $mergedManifestJson
|
||||
if ($jsFingerprint -ne "$NodeVersion|$TerserWorkers|$(Get-PathFingerprint $jsFingerprintInputs)" -or
|
||||
$cssFingerprint -ne "$NodeVersion|$(Get-PathFingerprint $cssFingerprintInputs)") {
|
||||
throw 'Frontend sources changed during build. Retry from a stable checkout.'
|
||||
}
|
||||
Write-Utf8NoBom -Path $outputFingerprintPath -Value (Get-PathFingerprint @('.caiwu-build/public'))
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
|
||||
@ -356,6 +356,20 @@ try {
|
||||
docker run --rm --network none --user www-data --entrypoint php $fullImage artisan --version
|
||||
} '发布镜像无法引导 Laravel。服务器未发生任何变更。'
|
||||
|
||||
# Compare the image's source and compiled assets with this workstation build.
|
||||
# This also catches a Docker COPY or stale build-context overwrite before upload.
|
||||
foreach ($asset in @(
|
||||
@{ Local = 'resources/assets/js/components/business/AccountBills.vue'; Image = 'resources/assets/js/components/business/AccountBills.vue' },
|
||||
@{ Local = '.caiwu-build/public/js/business/pages.min.js'; Image = 'public/js/business/pages.min.js' },
|
||||
@{ Local = '.caiwu-build/public/mix-manifest.json'; Image = 'public/mix-manifest.json' }
|
||||
)) {
|
||||
$expectedHash = (Get-FileHash -LiteralPath (Join-Path $repoRoot $asset.Local) -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
$imageHash = @(& docker run --rm --network none --user www-data --entrypoint sha256sum $fullImage $asset.Image)
|
||||
if ($LASTEXITCODE -ne 0 -or ($imageHash -join ' ') -notmatch "^$expectedHash\s") {
|
||||
throw "发布镜像源码或前端资源不匹配:$($asset.Image)。服务器未发生任何变更。"
|
||||
}
|
||||
}
|
||||
|
||||
$previousShaOutput = @(& ssh @sshOptions -o StrictHostKeyChecking=accept-new $sshTarget "cat '$RemotePath/.deployed-sha' 2>/dev/null || true")
|
||||
$previousSha = ($previousShaOutput -join "`n").Trim()
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
|
||||
25
tests/scripts/frontend-cache-integrity.test.ps1
Normal file
25
tests/scripts/frontend-cache-integrity.test.ps1
Normal file
@ -0,0 +1,25 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$source = Join-Path $PSScriptRoot '../../scripts/build-frontend.ps1'
|
||||
$ast = [Management.Automation.Language.Parser]::ParseFile((Resolve-Path $source), [ref]$null, [ref]$null)
|
||||
$function = $ast.Find({ param($node) $node -is [Management.Automation.Language.FunctionDefinitionAst] -and $node.Name -eq 'Get-PathFingerprint' }, $true)
|
||||
Invoke-Expression $function.Extent.Text
|
||||
$check = $ast.Find({ param($node) $node -is [Management.Automation.Language.AssignmentStatementAst] -and $node.Left.Extent.Text -eq '$outputCacheValid' }, $true).Right.Extent.Text
|
||||
$repoRoot = Join-Path ([IO.Path]::GetTempPath()) ('caiwu-cache-test-' + [guid]::NewGuid().ToString('N'))
|
||||
$frontendOutputRoot = Join-Path $repoRoot '.caiwu-build/public'
|
||||
$outputFingerprintPath = Join-Path $repoRoot 'output.sha'
|
||||
New-Item -ItemType Directory -Path $frontendOutputRoot -Force | Out-Null
|
||||
try {
|
||||
$asset = Join-Path $frontendOutputRoot 'pages.js'
|
||||
Set-Content -LiteralPath $asset -Value 'new calendar'
|
||||
if (Invoke-Expression $check) { throw 'Missing integrity stamp was accepted.' }
|
||||
Set-Content -LiteralPath $outputFingerprintPath -Value (Get-PathFingerprint @('.caiwu-build/public'))
|
||||
if (-not (Invoke-Expression $check)) { throw 'Valid output was rejected.' }
|
||||
Set-Content -LiteralPath $asset -Value 'old calendar'
|
||||
if (Invoke-Expression $check) { throw 'Overwritten output was accepted.' }
|
||||
Remove-Item -LiteralPath $asset
|
||||
if (Invoke-Expression $check) { throw 'Missing output was accepted.' }
|
||||
Write-Host 'PASS missing stamp, valid cache, overwritten and missing asset detection'
|
||||
} finally {
|
||||
if ((Split-Path $repoRoot -Leaf) -notlike 'caiwu-cache-test-*') { throw 'Unexpected test directory.' }
|
||||
Remove-Item -LiteralPath $repoRoot -Recurse -Force
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user