| | |
| | | } |
| | | } |
| | | |
| | | function Assert-ExactSourceSnapshot([string]$Root, [string]$ManifestPath, [string[]]$ExpectedFiles, [object]$Manifest) { |
| | | Assert-ExactSourceTree $Root $ManifestPath $ExpectedFiles |
| | | foreach ($entry in $Manifest.files) { |
| | | if ($entry.path -notmatch '^[A-Za-z0-9._/-]+$' -or $entry.path.Contains('..') -or |
| | | $entry.sha256 -notmatch '^[A-F0-9]{64}$' -or $entry.bytes -lt 1) { |
| | | throw 'Source artifact manifest contains an invalid entry.' |
| | | } |
| | | $candidate = [System.IO.Path]::GetFullPath((Join-Path $Root $entry.path)) |
| | | if (-not $candidate.StartsWith($Root + [System.IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase)) { |
| | | throw 'Source artifact path escaped its root.' |
| | | } |
| | | $item = Get-Item -LiteralPath $candidate |
| | | if (($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or |
| | | $item.Length -ne $entry.bytes -or |
| | | (Get-FileHash -Algorithm SHA256 -LiteralPath $candidate).Hash -cne $entry.sha256) { |
| | | throw 'Source artifact hash mismatch.' |
| | | } |
| | | } |
| | | } |
| | | |
| | | $resolvedOutput = [System.IO.Path]::GetFullPath($OutputRoot) |
| | | if (-not [System.IO.Path]::IsPathRooted($resolvedOutput) -or $resolvedOutput.StartsWith('\\')) { |
| | | throw 'OutputRoot must be an absolute local path.' |
| | |
| | | '__init__.py', 'background.js', 'build_host.ps1', 'config.example.json', |
| | | 'constants.py', 'dependencies/dependency-artifact-manifest.json', |
| | | 'dependencies/yt_dlp-2026.7.4-py3-none-any.whl', |
| | | 'install_native_host.ps1', 'job.py', 'manifest.json', |
| | | 'formal_legacy_identity_manifest.py', 'install_native_host.ps1', 'job.py', 'manifest.json', |
| | | 'native-host-manifest.template.json', 'native_host.py', 'protocol.py', |
| | | 'queue-producer.example.json', 'queue_producer.py', 'queue_state.py', |
| | | 'sidepanel.css', 'sidepanel.html', 'sidepanel.js', 'worker.py' |
| | | ) |
| | | Assert-ExactSourceTree $sourceRoot $resolvedSourceManifest $expectedSourceFiles |
| | | $dependencyManifestPath = Join-Path $sourceRoot 'dependencies/dependency-artifact-manifest.json' |
| | | $dependencyManifestItem = Get-Item -LiteralPath $dependencyManifestPath |
| | | $sourceManifest = Get-StrictJson $resolvedSourceManifest |
| | | if ($sourceManifest.schema -ne 1 -or $sourceManifest.target -cne 'BV1HA3o6oEJJ' -or |
| | | if ($sourceManifest.schema -ne 1 -or $sourceManifest.scope -cne 'generic-bilibili-queue' -or |
| | | $sourceManifest.extension_id -cne 'oidmclckpdmpabbfedplkbdplmfcenbb' -or |
| | | $sourceManifest.extension_build -cne 'project-info-bili-auth-ingress/1.0.0+20260805.v002' -or |
| | | $sourceManifest.host_build -cne 'project-info-bili-auth-native-host/1.0.0+20260805.v002' -or |
| | | $sourceManifest.extension_build -cne 'project-info-bili-auth-ingress/1.2.25+20260829.generic.v027' -or |
| | | $sourceManifest.host_build -cne 'project-info-bili-auth-native-host/1.2.25+20260829.generic.v027' -or |
| | | $sourceManifest.dependency_artifact_manifest_bytes -ne $dependencyManifestItem.Length -or |
| | | $sourceManifest.dependency_artifact_manifest_sha256 -cne (Get-FileHash -Algorithm SHA256 -LiteralPath $dependencyManifestPath).Hash) { |
| | | throw 'Source artifact manifest identity mismatch.' |
| | |
| | | if (Compare-Object -CaseSensitive ($expectedSourceFiles | Sort-Object) $actualSourceFiles) { |
| | | throw 'Source artifact manifest file set mismatch.' |
| | | } |
| | | foreach ($entry in $sourceManifest.files) { |
| | | if ($entry.path -notmatch '^[A-Za-z0-9._/-]+$' -or $entry.path.Contains('..') -or |
| | | $entry.sha256 -notmatch '^[A-F0-9]{64}$' -or $entry.bytes -lt 1) { |
| | | throw 'Source artifact manifest contains an invalid entry.' |
| | | } |
| | | $candidate = [System.IO.Path]::GetFullPath((Join-Path $sourceRoot $entry.path)) |
| | | if (-not $candidate.StartsWith($sourceRoot + [System.IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase)) { |
| | | throw 'Source artifact path escaped its root.' |
| | | } |
| | | $item = Get-Item -LiteralPath $candidate |
| | | if (($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or |
| | | $item.Length -ne $entry.bytes -or |
| | | (Get-FileHash -Algorithm SHA256 -LiteralPath $candidate).Hash -cne $entry.sha256) { |
| | | throw 'Source artifact hash mismatch.' |
| | | } |
| | | } |
| | | Assert-ExactSourceSnapshot $sourceRoot $resolvedSourceManifest $expectedSourceFiles $sourceManifest |
| | | |
| | | $dependencyManifest = Get-StrictJson $dependencyManifestPath |
| | | $expectedDependencyKeys = @( |
| | |
| | | foreach ($name in @($pythonEnvironment.Keys)) { |
| | | Remove-Item -LiteralPath "Env:$name" -ErrorAction SilentlyContinue |
| | | } |
| | | $env:PYTHONDONTWRITEBYTECODE = '1' |
| | | $pyInstallerVersion = & $resolvedPython -I -B -c "import importlib.metadata; print(importlib.metadata.version('PyInstaller'))" |
| | | if ($LASTEXITCODE -ne 0 -or $pyInstallerVersion.Trim() -cne '6.15.0') { |
| | | throw 'PyInstaller 6.15.0 is required; no unpinned builder is allowed.' |
| | |
| | | $hostItem = Get-Item -LiteralPath $hostExecutable |
| | | $buildManifest = [ordered]@{ |
| | | schema = 2 |
| | | target = 'BV1HA3o6oEJJ' |
| | | scope = 'generic-bilibili-queue' |
| | | extension_id = 'oidmclckpdmpabbfedplkbdplmfcenbb' |
| | | extension_build = 'project-info-bili-auth-ingress/1.0.0+20260805.v002' |
| | | host_build = 'project-info-bili-auth-native-host/1.0.0+20260805.v002' |
| | | extension_build = 'project-info-bili-auth-ingress/1.2.25+20260829.generic.v027' |
| | | host_build = 'project-info-bili-auth-native-host/1.2.25+20260829.generic.v027' |
| | | packaging = 'pyinstaller-onefile' |
| | | pyinstaller_version = '6.15.0' |
| | | yt_dlp_version = '2026.7.4' |
| | |
| | | ($buildManifest | ConvertTo-Json -Depth 5), |
| | | $utf8NoBom |
| | | ) |
| | | Assert-ExactSourceSnapshot $sourceRoot $resolvedSourceManifest $expectedSourceFiles $sourceManifest |
| | | } catch { |
| | | $caught = $_ |
| | | if ($outputCreated -and (Test-Path -LiteralPath $resolvedOutput)) { |
| | | Remove-Item -LiteralPath $resolvedOutput -Recurse -Force |
| | | } |
| | | throw |
| | | try { |
| | | Assert-ExactSourceSnapshot $sourceRoot $resolvedSourceManifest $expectedSourceFiles $sourceManifest |
| | | } catch { |
| | | throw "Post-build source snapshot drifted: $($_.Exception.Message)" |
| | | } |
| | | throw $caught |
| | | } finally { |
| | | Remove-Item -LiteralPath 'Env:PYTHONDONTWRITEBYTECODE' -ErrorAction SilentlyContinue |
| | | foreach ($name in @($pythonEnvironment.Keys)) { |
| | | Set-Item -LiteralPath "Env:$name" -Value $pythonEnvironment[$name] |
| | | } |