# 四套主题 player 一键打包(自动切换 Git 分支) # PowerShell 会在启动时将整份脚本载入内存,git checkout 后仍可继续执行。 # 用法(项目根目录或本目录均可): # .\docs\docker\build-and-export-all-themes.ps1 # .\docs\docker\build-and-export-all-themes.ps1 -UseCache # .\docs\docker\build-and-export-all-themes.ps1 -ExportOnly # .\docs\docker\build-and-export-all-themes.ps1 -SkipApiAdmin # 或通过 bat 启动(参数支持 --use-cache 等 CMD 风格): # docs\docker\build-and-export-all-themes.bat --use-cache param( [switch]$UseCache, [switch]$ExportOnly, [switch]$SkipApiAdmin, [switch]$SkipBundle, [switch]$Help ) $ErrorActionPreference = "Stop" foreach ($arg in $args) { switch ($arg.ToLowerInvariant()) { "--use-cache" { $UseCache = $true; continue } "--export-only" { $ExportOnly = $true; continue } "--skip-api-admin" { $SkipApiAdmin = $true; continue } "--skip-bundle" { $SkipBundle = $true; continue } "-h" { $Help = $true; continue } "--help" { $Help = $true; continue } "/?" { $Help = $true; continue } default { throw "Unknown argument: $arg" } } } function Show-Help { Write-Host @" Usage: docs\docker\build-and-export-all-themes.ps1 [options] -UseCache, --use-cache Use Docker build cache (default: --no-cache) -ExportOnly, --export-only Skip build, export existing images only -SkipApiAdmin, --skip-api-admin Only build 4 player themes, skip api/admin -SkipBundle, --skip-bundle Skip thebet365-full-themes-latest.tar (6-in-1 bundle) -Help, -h, --help Show this help Output (project root): thebet365-player-main.tar thebet365-player-theme-2.tar thebet365-player-theme-3.tar thebet365-player-theme-4.tar thebet365-images-latest.tar (api + admin, unless -SkipApiAdmin) thebet365-full-themes-latest.tar (api + admin + 4 player themes, unless -SkipBundle) "@ } if ($Help) { Show-Help exit 0 } $Root = (Resolve-Path (Join-Path $PSScriptRoot "../..")).Path $Themes = @( @{ Branch = "main"; Tag = "main" }, @{ Branch = "theme-2"; Tag = "theme-2" }, @{ Branch = "theme-3"; Tag = "theme-3" }, @{ Branch = "theme-4"; Tag = "theme-4" } ) if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { throw "docker not found. Please start Docker Desktop first." } if (-not (Test-Path (Join-Path $Root "docs\docker\build-and-export-images.bat"))) { throw "Missing build script: docs\docker\build-and-export-images.bat" } function Invoke-Git { param([Parameter(ValueFromRemainingArguments = $true)][string[]]$GitArgs) $prevErrorAction = $ErrorActionPreference $ErrorActionPreference = "SilentlyContinue" try { & git @GitArgs 2>$null | Out-Null return $LASTEXITCODE } finally { $ErrorActionPreference = $prevErrorAction } } function Get-GitOutput { param([Parameter(ValueFromRemainingArguments = $true)][string[]]$GitArgs) $prevErrorAction = $ErrorActionPreference $ErrorActionPreference = "SilentlyContinue" try { return ((& git @GitArgs 2>$null | Out-String).Trim()) } finally { $ErrorActionPreference = $prevErrorAction } } Set-Location $Root $OriginalBranch = Get-GitOutput rev-parse --abbrev-ref HEAD if ([string]::IsNullOrWhiteSpace($OriginalBranch)) { throw "Cannot determine current Git branch. Run this script from the repo root." } Write-Host "[INFO] Current branch: $OriginalBranch" $DidStash = $false $diffExit = Invoke-Git diff --quiet $cachedExit = Invoke-Git diff --cached --quiet if ($diffExit -ne 0 -or $cachedExit -ne 0) { Write-Host "[INFO] Stashing local changes before branch switching..." $stashExit = Invoke-Git stash push -m "build-all-themes auto-stash" if ($stashExit -eq 0) { $DidStash = $true Write-Host "[INFO] Changes stashed." } else { Write-Warning "git stash failed. Branch switching may fail if there are conflicts." } } $FailedThemes = [System.Collections.Generic.List[string]]::new() $SuccessCount = 0 function Invoke-BuildExport { param( [string]$Service = "", [string]$Tag ) $argList = @() if (-not [string]::IsNullOrWhiteSpace($Service)) { $argList += "--service" $argList += $Service } $argList += "--tag" $argList += $Tag if ($UseCache) { $argList += "--use-cache" } if ($ExportOnly) { $argList += "--export-only" } Set-Location $Root $batPath = Join-Path $Root "docs\docker\build-and-export-images.bat" $argText = ($argList | ForEach-Object { if ($_ -match '\s') { "`"$_`"" } else { $_ } }) -join ' ' & cmd.exe /c "`"$batPath`" $argText" return $LASTEXITCODE } function Invoke-PlayerThemeBuild { param( [string]$Branch, [string]$Tag ) Write-Host "" Write-Host "----------------------------------------------------------------" Write-Host "[INFO] Theme: $Branch (image tag: $Tag)" Write-Host "----------------------------------------------------------------" Set-Location $Root $checkoutExit = Invoke-Git checkout $Branch if ($checkoutExit -ne 0) { Write-Host "[ERROR] Cannot switch to branch $Branch -- skipping" $script:FailedThemes.Add($Branch) | Out-Null return } Write-Host "[INFO] Switched to $Branch" Set-Location $Root $env:PLAYER_IMAGE_TAG = $Tag if ((Invoke-BuildExport -Service "player" -Tag $Tag) -ne 0) { Write-Host "[ERROR] Player build failed for $Branch" $script:FailedThemes.Add($Branch) | Out-Null return } Write-Host "[OK] thebet365-player:$Tag exported successfully" $script:SuccessCount++ } foreach ($theme in $Themes) { Invoke-PlayerThemeBuild -Branch $theme.Branch -Tag $theme.Tag } Write-Host "" Write-Host "[INFO] Restoring original branch: $OriginalBranch" Set-Location $Root if ((Invoke-Git checkout $OriginalBranch) -eq 0) { Write-Host "[INFO] Restored to $OriginalBranch" } else { Write-Warning "Could not restore branch $OriginalBranch. Run: git checkout $OriginalBranch" } if ($DidStash) { Write-Host "[INFO] Restoring stashed changes..." if ((Invoke-Git stash pop) -eq 0) { Write-Host "[INFO] Stash restored." } else { Write-Warning "git stash pop failed. Run: git stash pop" } } if (-not $SkipApiAdmin) { Write-Host "" Write-Host "[INFO] Building api + admin (tag: latest) on branch main..." Set-Location $Root if ((Invoke-Git checkout main) -ne 0) { Write-Host "[ERROR] Cannot switch to branch main for api/admin build" $FailedThemes.Add("api/admin") | Out-Null } else { Set-Location $Root if ((Invoke-BuildExport -Service "api-admin" -Tag "latest") -ne 0) { Write-Host "[ERROR] api/admin build failed" $FailedThemes.Add("api/admin") | Out-Null } else { $SuccessCount++ } } Write-Host "" Write-Host "[INFO] Restoring original branch: $OriginalBranch" Set-Location $Root Invoke-Git checkout $OriginalBranch | Out-Null } if (-not $SkipBundle -and -not $SkipApiAdmin -and $FailedThemes.Count -eq 0) { Write-Host "" Write-Host "[INFO] Exporting full bundle (api + admin + 4 player themes)..." Set-Location $Root if ((Invoke-BuildExport -Service "full-themes" -Tag "latest") -ne 0) { Write-Host "[ERROR] Full bundle export failed" $FailedThemes.Add("full-bundle") | Out-Null } else { Write-Host "[OK] thebet365-full-themes-latest.tar exported successfully" $SuccessCount++ } } Write-Host "" Write-Host "================================================================" Write-Host " BUILD SUMMARY" Write-Host "================================================================" Write-Host " Succeeded: $SuccessCount task(s)" if ($FailedThemes.Count -gt 0) { Write-Host " Failed: $($FailedThemes -join ' ')" Write-Host "" Write-Host " Tip: Retry failed themes manually:" Write-Host " git checkout " Write-Host " docs\docker\build-and-export-images.bat --service player --tag " Write-Host "================================================================" exit 1 } Write-Host "" Write-Host " All done! Output files in project root:" Write-Host " thebet365-player-main.tar" Write-Host " thebet365-player-theme-2.tar" Write-Host " thebet365-player-theme-3.tar" Write-Host " thebet365-player-theme-4.tar" if (-not $SkipApiAdmin) { Write-Host " thebet365-images-latest.tar (api + admin)" } if (-not $SkipBundle -and -not $SkipApiAdmin) { Write-Host " thebet365-full-themes-latest.tar (api + admin + 4 themes, upload this only)" } Write-Host "" Write-Host " Server import (single bundle):" Write-Host " docker load -i thebet365-full-themes-latest.tar" Write-Host " docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker up -d" Write-Host "" Write-Host " Or import separate tars:" if (-not $SkipApiAdmin) { Write-Host " docker load -i thebet365-images-latest.tar" } Write-Host " docker load -i thebet365-player-main.tar" Write-Host " docker load -i thebet365-player-theme-2.tar" Write-Host " docker load -i thebet365-player-theme-3.tar" Write-Host " docker load -i thebet365-player-theme-4.tar" Write-Host "================================================================" exit 0