fix(docker): multi-theme packaging with PS1 orchestration and full bundle export
Replace all-themes bat logic with PowerShell to survive branch checkout; add api-admin and full-themes service modes; fix bat findstr path check and cmd exit codes; document six-in-one tar and update gitignore for player/full-themes artifacts.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -8,6 +8,10 @@ docker-build.log
|
|||||||
thebet365-images.tar
|
thebet365-images.tar
|
||||||
thebet365-images-*.tar
|
thebet365-images-*.tar
|
||||||
thebet365-images-*.manifest.txt
|
thebet365-images-*.manifest.txt
|
||||||
|
thebet365-full-themes-*.tar
|
||||||
|
thebet365-full-themes-*.manifest.txt
|
||||||
|
thebet365-player-*.tar
|
||||||
|
thebet365-player-*.manifest.txt
|
||||||
thebet365-admin-latest.tar
|
thebet365-admin-latest.tar
|
||||||
thebet365-admin-latest.manifest.txt
|
thebet365-admin-latest.manifest.txt
|
||||||
.claude/
|
.claude/
|
||||||
|
|||||||
@@ -1,261 +1,13 @@
|
|||||||
@echo off
|
@echo off
|
||||||
setlocal EnableDelayedExpansion
|
REM Thin launcher for build-and-export-all-themes.ps1
|
||||||
|
REM CMD reads batch files line-by-line from disk; git checkout to theme-* removes
|
||||||
REM ================================================================
|
REM this file from the working tree. PowerShell loads the script into memory first.
|
||||||
REM build-and-export-all-themes.bat
|
|
||||||
REM
|
REM
|
||||||
REM Four-theme player image batch builder.
|
|
||||||
REM Automatically switches Git branches to build each theme.
|
|
||||||
REM Usage:
|
REM Usage:
|
||||||
REM docs\docker\build-and-export-all-themes.bat
|
REM docs\docker\build-and-export-all-themes.bat
|
||||||
REM docs\docker\build-and-export-all-themes.bat --use-cache
|
REM docs\docker\build-and-export-all-themes.bat --use-cache
|
||||||
REM docs\docker\build-and-export-all-themes.bat --export-only
|
REM docs\docker\build-and-export-all-themes.bat --export-only
|
||||||
REM docs\docker\build-and-export-all-themes.bat --skip-api-admin
|
REM docs\docker\build-and-export-all-themes.bat --skip-api-admin
|
||||||
REM
|
|
||||||
REM Output files (project root, already in .gitignore):
|
|
||||||
REM thebet365-player-main.tar -> thebet365-player:main
|
|
||||||
REM thebet365-player-theme-2.tar -> thebet365-player:theme-2
|
|
||||||
REM thebet365-player-theme-3.tar -> thebet365-player:theme-3
|
|
||||||
REM thebet365-player-theme-4.tar -> thebet365-player:theme-4
|
|
||||||
REM thebet365-images-latest.tar -> api:latest + admin:latest
|
|
||||||
REM ================================================================
|
|
||||||
|
|
||||||
cd /d "%~dp0..\.."
|
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0build-and-export-all-themes.ps1" %*
|
||||||
set "ROOT_DIR=%CD%"
|
exit /b %ERRORLEVEL%
|
||||||
|
|
||||||
set "USE_CACHE=0"
|
|
||||||
set "EXPORT_ONLY=0"
|
|
||||||
set "SKIP_API_ADMIN=0"
|
|
||||||
|
|
||||||
:parse_args
|
|
||||||
if "%~1"=="" goto args_done
|
|
||||||
if /i "%~1"=="--use-cache" set "USE_CACHE=1" & shift & goto parse_args
|
|
||||||
if /i "%~1"=="--export-only" set "EXPORT_ONLY=1" & shift & goto parse_args
|
|
||||||
if /i "%~1"=="--skip-api-admin" set "SKIP_API_ADMIN=1" & shift & goto parse_args
|
|
||||||
if /i "%~1"=="-h" goto show_help
|
|
||||||
if /i "%~1"=="--help" goto show_help
|
|
||||||
if /i "%~1"=="/?" goto show_help
|
|
||||||
echo Unknown argument: %~1
|
|
||||||
goto show_help
|
|
||||||
|
|
||||||
:show_help
|
|
||||||
echo.
|
|
||||||
echo Usage: docs\docker\build-and-export-all-themes.bat [options]
|
|
||||||
echo.
|
|
||||||
echo --use-cache Use Docker build cache (default: --no-cache)
|
|
||||||
echo --export-only Skip build, export existing images only
|
|
||||||
echo --skip-api-admin Only build 4 player themes, skip api/admin
|
|
||||||
echo -h, --help Show this help
|
|
||||||
echo.
|
|
||||||
echo Output (project root):
|
|
||||||
echo thebet365-player-main.tar
|
|
||||||
echo thebet365-player-theme-2.tar
|
|
||||||
echo thebet365-player-theme-3.tar
|
|
||||||
echo thebet365-player-theme-4.tar
|
|
||||||
echo thebet365-images-latest.tar (api + admin, unless --skip-api-admin)
|
|
||||||
echo.
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
:args_done
|
|
||||||
|
|
||||||
REM -- Validate docker is available
|
|
||||||
where docker >nul 2>&1
|
|
||||||
if errorlevel 1 (
|
|
||||||
echo ERROR: docker not found. Please start Docker Desktop first.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM -- Record current branch so we can restore it
|
|
||||||
set "ORIGINAL_BRANCH="
|
|
||||||
for /f "delims=" %%B in ('git rev-parse --abbrev-ref HEAD 2^>nul') do set "ORIGINAL_BRANCH=%%B"
|
|
||||||
if not defined ORIGINAL_BRANCH (
|
|
||||||
echo ERROR: Cannot determine current Git branch. Run this script from the repo root.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
echo [INFO] Current branch: %ORIGINAL_BRANCH%
|
|
||||||
|
|
||||||
REM -- Stash any local changes so branch switching works cleanly
|
|
||||||
set "DID_STASH=0"
|
|
||||||
git diff --quiet 2>nul
|
|
||||||
set "D1=!ERRORLEVEL!"
|
|
||||||
git diff --cached --quiet 2>nul
|
|
||||||
set "D2=!ERRORLEVEL!"
|
|
||||||
if not "!D1!"=="0" goto do_stash
|
|
||||||
if not "!D2!"=="0" goto do_stash
|
|
||||||
goto stash_done
|
|
||||||
|
|
||||||
:do_stash
|
|
||||||
echo [INFO] Stashing local changes before branch switching...
|
|
||||||
git stash push -m "build-all-themes auto-stash" >nul 2>&1
|
|
||||||
if errorlevel 1 (
|
|
||||||
echo [WARN] git stash failed. Branch switching may fail if there are conflicts.
|
|
||||||
) else (
|
|
||||||
set "DID_STASH=1"
|
|
||||||
echo [INFO] Changes stashed.
|
|
||||||
)
|
|
||||||
|
|
||||||
:stash_done
|
|
||||||
|
|
||||||
REM -- Build extra arguments for the base script
|
|
||||||
set "EXTRA_ARGS="
|
|
||||||
if "%USE_CACHE%"=="1" set "EXTRA_ARGS=!EXTRA_ARGS! --use-cache"
|
|
||||||
if "%EXPORT_ONLY%"=="1" set "EXTRA_ARGS=!EXTRA_ARGS! --export-only"
|
|
||||||
|
|
||||||
set "FAILED_THEMES="
|
|
||||||
set "SUCCESS_COUNT=0"
|
|
||||||
|
|
||||||
REM ================================================================
|
|
||||||
REM Build each player theme
|
|
||||||
REM ================================================================
|
|
||||||
|
|
||||||
call :build_theme main main
|
|
||||||
call :build_theme theme-2 theme-2
|
|
||||||
call :build_theme theme-3 theme-3
|
|
||||||
call :build_theme theme-4 theme-4
|
|
||||||
|
|
||||||
REM -- Restore original branch
|
|
||||||
echo.
|
|
||||||
echo [INFO] Restoring original branch: %ORIGINAL_BRANCH%
|
|
||||||
cd /d "%ROOT_DIR%"
|
|
||||||
git checkout %ORIGINAL_BRANCH% >nul 2>&1
|
|
||||||
if errorlevel 1 (
|
|
||||||
echo [WARN] Could not restore branch %ORIGINAL_BRANCH%. Run: git checkout %ORIGINAL_BRANCH%
|
|
||||||
) else (
|
|
||||||
echo [INFO] Restored to %ORIGINAL_BRANCH%
|
|
||||||
)
|
|
||||||
|
|
||||||
REM -- Pop stash if we stashed earlier
|
|
||||||
if "%DID_STASH%"=="1" (
|
|
||||||
echo [INFO] Restoring stashed changes...
|
|
||||||
git stash pop >nul 2>&1
|
|
||||||
if errorlevel 1 (
|
|
||||||
echo [WARN] git stash pop failed. Run: git stash pop
|
|
||||||
) else (
|
|
||||||
echo [INFO] Stash restored.
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
REM -- Build api + admin on main branch
|
|
||||||
if "%SKIP_API_ADMIN%"=="1" goto skip_api_admin
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo [INFO] Building api + admin (tag: latest) on branch main...
|
|
||||||
cd /d "%ROOT_DIR%"
|
|
||||||
git checkout main >nul 2>&1
|
|
||||||
cd /d "%ROOT_DIR%"
|
|
||||||
call docs\docker\build-and-export-images.bat --tag latest!EXTRA_ARGS!
|
|
||||||
set "API_ERR=!ERRORLEVEL!"
|
|
||||||
cd /d "%ROOT_DIR%"
|
|
||||||
if "!API_ERR!"=="0" goto api_ok
|
|
||||||
echo [ERROR] api/admin build failed
|
|
||||||
set "FAILED_THEMES=!FAILED_THEMES! api/admin"
|
|
||||||
goto after_api_admin
|
|
||||||
|
|
||||||
:api_ok
|
|
||||||
set /a SUCCESS_COUNT+=1
|
|
||||||
|
|
||||||
:after_api_admin
|
|
||||||
echo.
|
|
||||||
echo [INFO] Restoring original branch: %ORIGINAL_BRANCH%
|
|
||||||
git checkout %ORIGINAL_BRANCH% >nul 2>&1
|
|
||||||
|
|
||||||
:skip_api_admin
|
|
||||||
|
|
||||||
REM ================================================================
|
|
||||||
REM Summary
|
|
||||||
REM ================================================================
|
|
||||||
echo.
|
|
||||||
echo ================================================================
|
|
||||||
echo BUILD SUMMARY
|
|
||||||
echo ================================================================
|
|
||||||
echo Succeeded: !SUCCESS_COUNT! task(s)
|
|
||||||
if not defined FAILED_THEMES goto all_ok
|
|
||||||
|
|
||||||
echo Failed: !FAILED_THEMES!
|
|
||||||
echo.
|
|
||||||
echo Tip: Retry failed themes manually:
|
|
||||||
echo git checkout ^<branch^>
|
|
||||||
echo docs\docker\build-and-export-images.bat --service player --tag ^<tag^>
|
|
||||||
echo ================================================================
|
|
||||||
echo.
|
|
||||||
endlocal
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:all_ok
|
|
||||||
echo.
|
|
||||||
echo All done! Output files in project root:
|
|
||||||
echo thebet365-player-main.tar
|
|
||||||
echo thebet365-player-theme-2.tar
|
|
||||||
echo thebet365-player-theme-3.tar
|
|
||||||
echo thebet365-player-theme-4.tar
|
|
||||||
if "%SKIP_API_ADMIN%"=="0" (
|
|
||||||
echo thebet365-images-latest.tar (api + admin)
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
echo Server import commands:
|
|
||||||
echo docker load -i thebet365-images-latest.tar
|
|
||||||
echo docker load -i thebet365-player-main.tar
|
|
||||||
echo docker load -i thebet365-player-theme-2.tar
|
|
||||||
echo docker load -i thebet365-player-theme-3.tar
|
|
||||||
echo docker load -i thebet365-player-theme-4.tar
|
|
||||||
echo.
|
|
||||||
echo Start (first multi-theme deploy):
|
|
||||||
echo docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker up -d
|
|
||||||
echo ================================================================
|
|
||||||
echo.
|
|
||||||
endlocal
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
|
|
||||||
REM ================================================================
|
|
||||||
REM :build_theme <branch> <tag>
|
|
||||||
REM Switch to branch, build player, mark success/fail.
|
|
||||||
REM Uses cd /d ROOT_DIR instead of pushd to avoid stack issues.
|
|
||||||
REM ================================================================
|
|
||||||
:build_theme
|
|
||||||
set "THEME_BRANCH=%~1"
|
|
||||||
set "THEME_TAG=%~2"
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ----------------------------------------------------------------
|
|
||||||
echo [INFO] Theme: %THEME_BRANCH% (image tag: %THEME_TAG%)
|
|
||||||
echo ----------------------------------------------------------------
|
|
||||||
|
|
||||||
cd /d "%ROOT_DIR%"
|
|
||||||
git checkout %THEME_BRANCH% >nul 2>&1
|
|
||||||
if errorlevel 1 (
|
|
||||||
echo [ERROR] Cannot switch to branch %THEME_BRANCH% -- skipping
|
|
||||||
set "FAILED_THEMES=!FAILED_THEMES! %THEME_BRANCH%"
|
|
||||||
exit /b 0
|
|
||||||
)
|
|
||||||
echo [INFO] Switched to %THEME_BRANCH%
|
|
||||||
|
|
||||||
cd /d "%ROOT_DIR%"
|
|
||||||
call docs\docker\build-and-export-images.bat --service player --tag %THEME_TAG%!EXTRA_ARGS!
|
|
||||||
set "BUILD_ERR=!ERRORLEVEL!"
|
|
||||||
|
|
||||||
cd /d "%ROOT_DIR%"
|
|
||||||
if "!BUILD_ERR!"=="0" goto build_ok_%THEME_TAG%
|
|
||||||
echo [ERROR] Player build failed for %THEME_BRANCH%
|
|
||||||
set "FAILED_THEMES=!FAILED_THEMES! %THEME_BRANCH%"
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
:build_ok_main
|
|
||||||
echo [OK] thebet365-player:main exported successfully
|
|
||||||
set /a SUCCESS_COUNT+=1
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
:build_ok_theme-2
|
|
||||||
echo [OK] thebet365-player:theme-2 exported successfully
|
|
||||||
set /a SUCCESS_COUNT+=1
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
:build_ok_theme-3
|
|
||||||
echo [OK] thebet365-player:theme-3 exported successfully
|
|
||||||
set /a SUCCESS_COUNT+=1
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
:build_ok_theme-4
|
|
||||||
echo [OK] thebet365-player:theme-4 exported successfully
|
|
||||||
set /a SUCCESS_COUNT+=1
|
|
||||||
exit /b 0
|
|
||||||
|
|||||||
285
docs/docker/build-and-export-all-themes.ps1
Normal file
285
docs/docker/build-and-export-all-themes.ps1
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
# 四套主题 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
|
||||||
|
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 <branch>"
|
||||||
|
Write-Host " docs\docker\build-and-export-images.bat --service player --tag <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
|
||||||
@@ -69,7 +69,7 @@ goto parse_args
|
|||||||
echo.
|
echo.
|
||||||
echo Usage: docs\docker\build-and-export-images.bat [options]
|
echo Usage: docs\docker\build-and-export-images.bat [options]
|
||||||
echo.
|
echo.
|
||||||
echo --service SVC api ^| player ^| admin ^| all (default: all)
|
echo --service SVC api ^| player ^| admin ^| api-admin ^| full-themes ^| all (default: all)
|
||||||
echo --tag TAG Image tag (default: latest)
|
echo --tag TAG Image tag (default: latest)
|
||||||
echo --use-cache Use Docker build cache
|
echo --use-cache Use Docker build cache
|
||||||
echo --export-only Skip build, export existing images only
|
echo --export-only Skip build, export existing images only
|
||||||
@@ -117,8 +117,7 @@ if errorlevel 1 exit /b 1
|
|||||||
if not defined OUTPUT call :default_output
|
if not defined OUTPUT call :default_output
|
||||||
|
|
||||||
set "OUTPUT_PATH=%OUTPUT%"
|
set "OUTPUT_PATH=%OUTPUT%"
|
||||||
echo %OUTPUT_PATH%| findstr /r "^[A-Za-z]:\\" >nul
|
if /i not "%OUTPUT:~1,1%"==":" set "OUTPUT_PATH=%CD%\%OUTPUT%"
|
||||||
if errorlevel 1 set "OUTPUT_PATH=%CD%\%OUTPUT%"
|
|
||||||
|
|
||||||
where docker >nul 2>&1
|
where docker >nul 2>&1
|
||||||
if errorlevel 1 (
|
if errorlevel 1 (
|
||||||
@@ -126,7 +125,7 @@ if errorlevel 1 (
|
|||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%EXPORT_ONLY%"=="0" goto do_build
|
if "%EXPORT_ONLY%"=="0" if /i not "%SERVICE%"=="full-themes" goto do_build
|
||||||
goto do_export
|
goto do_export
|
||||||
|
|
||||||
:do_build
|
:do_build
|
||||||
@@ -135,6 +134,8 @@ set "IMAGE_TAG=%TAG%"
|
|||||||
if "%NO_CACHE%"=="1" goto build_no_cache
|
if "%NO_CACHE%"=="1" goto build_no_cache
|
||||||
if /i "%SERVICE%"=="all" (
|
if /i "%SERVICE%"=="all" (
|
||||||
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build api player admin
|
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build api player admin
|
||||||
|
) else if /i "%SERVICE%"=="api-admin" (
|
||||||
|
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build api admin
|
||||||
) else (
|
) else (
|
||||||
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build %SERVICE%
|
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build %SERVICE%
|
||||||
)
|
)
|
||||||
@@ -143,6 +144,8 @@ goto build_done
|
|||||||
:build_no_cache
|
:build_no_cache
|
||||||
if /i "%SERVICE%"=="all" (
|
if /i "%SERVICE%"=="all" (
|
||||||
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build --no-cache api player admin
|
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build --no-cache api player admin
|
||||||
|
) else if /i "%SERVICE%"=="api-admin" (
|
||||||
|
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build --no-cache api admin
|
||||||
) else (
|
) else (
|
||||||
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build --no-cache %SERVICE%
|
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build --no-cache %SERVICE%
|
||||||
)
|
)
|
||||||
@@ -157,6 +160,10 @@ if errorlevel 1 (
|
|||||||
echo ==^> Exporting %SERVICE% to %OUTPUT_PATH%
|
echo ==^> Exporting %SERVICE% to %OUTPUT_PATH%
|
||||||
if /i "%SERVICE%"=="all" (
|
if /i "%SERVICE%"=="all" (
|
||||||
docker save thebet365-api:%TAG% thebet365-player:%TAG% thebet365-admin:%TAG% -o "%OUTPUT_PATH%"
|
docker save thebet365-api:%TAG% thebet365-player:%TAG% thebet365-admin:%TAG% -o "%OUTPUT_PATH%"
|
||||||
|
) else if /i "%SERVICE%"=="api-admin" (
|
||||||
|
docker save thebet365-api:%TAG% thebet365-admin:%TAG% -o "%OUTPUT_PATH%"
|
||||||
|
) else if /i "%SERVICE%"=="full-themes" (
|
||||||
|
docker save thebet365-api:%TAG% thebet365-admin:%TAG% thebet365-player:main thebet365-player:theme-2 thebet365-player:theme-3 thebet365-player:theme-4 -o "%OUTPUT_PATH%"
|
||||||
) else (
|
) else (
|
||||||
docker save thebet365-%SERVICE%:%TAG% -o "%OUTPUT_PATH%"
|
docker save thebet365-%SERVICE%:%TAG% -o "%OUTPUT_PATH%"
|
||||||
)
|
)
|
||||||
@@ -187,16 +194,34 @@ for %%F in ("%OUTPUT_PATH%") do set /a SIZE_MB=%%~zF/1048576
|
|||||||
echo git_dirty=!GIT_DIRTY!
|
echo git_dirty=!GIT_DIRTY!
|
||||||
echo tar=!TAR_NAME!
|
echo tar=!TAR_NAME!
|
||||||
echo tar_sha256=!TAR_SHA256!
|
echo tar_sha256=!TAR_SHA256!
|
||||||
if /i not "!SERVICE!"=="all" (
|
if /i "!SERVICE!"=="all" (
|
||||||
echo image=thebet365-!SERVICE!:%TAG%
|
|
||||||
echo image_id=!SVC_IMAGE_ID!
|
|
||||||
) else (
|
|
||||||
echo api_image=thebet365-api:%TAG%
|
echo api_image=thebet365-api:%TAG%
|
||||||
echo api_image_id=!API_IMAGE_ID!
|
echo api_image_id=!API_IMAGE_ID!
|
||||||
echo player_image=thebet365-player:%TAG%
|
echo player_image=thebet365-player:%TAG%
|
||||||
echo player_image_id=!PLAYER_IMAGE_ID!
|
echo player_image_id=!PLAYER_IMAGE_ID!
|
||||||
echo admin_image=thebet365-admin:%TAG%
|
echo admin_image=thebet365-admin:%TAG%
|
||||||
echo admin_image_id=!ADMIN_IMAGE_ID!
|
echo admin_image_id=!ADMIN_IMAGE_ID!
|
||||||
|
) else if /i "!SERVICE!"=="api-admin" (
|
||||||
|
echo api_image=thebet365-api:%TAG%
|
||||||
|
echo api_image_id=!API_IMAGE_ID!
|
||||||
|
echo admin_image=thebet365-admin:%TAG%
|
||||||
|
echo admin_image_id=!ADMIN_IMAGE_ID!
|
||||||
|
) else if /i "!SERVICE!"=="full-themes" (
|
||||||
|
echo api_image=thebet365-api:%TAG%
|
||||||
|
echo api_image_id=!API_IMAGE_ID!
|
||||||
|
echo admin_image=thebet365-admin:%TAG%
|
||||||
|
echo admin_image_id=!ADMIN_IMAGE_ID!
|
||||||
|
echo player_main_image=thebet365-player:main
|
||||||
|
echo player_main_image_id=!PLAYER_MAIN_IMAGE_ID!
|
||||||
|
echo player_theme_2_image=thebet365-player:theme-2
|
||||||
|
echo player_theme_2_image_id=!PLAYER_THEME2_IMAGE_ID!
|
||||||
|
echo player_theme_3_image=thebet365-player:theme-3
|
||||||
|
echo player_theme_3_image_id=!PLAYER_THEME3_IMAGE_ID!
|
||||||
|
echo player_theme_4_image=thebet365-player:theme-4
|
||||||
|
echo player_theme_4_image_id=!PLAYER_THEME4_IMAGE_ID!
|
||||||
|
) else (
|
||||||
|
echo image=thebet365-!SERVICE!:%TAG%
|
||||||
|
echo image_id=!SVC_IMAGE_ID!
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -207,6 +232,12 @@ echo Server load and recreate:
|
|||||||
if /i "%SERVICE%"=="all" (
|
if /i "%SERVICE%"=="all" (
|
||||||
echo docker load -i !TAR_NAME!
|
echo docker load -i !TAR_NAME!
|
||||||
echo docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --force-recreate api player admin
|
echo docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --force-recreate api player admin
|
||||||
|
) else if /i "%SERVICE%"=="api-admin" (
|
||||||
|
echo docker load -i !TAR_NAME!
|
||||||
|
echo docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --force-recreate api admin
|
||||||
|
) else if /i "%SERVICE%"=="full-themes" (
|
||||||
|
echo docker load -i !TAR_NAME!
|
||||||
|
echo docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker up -d
|
||||||
) else (
|
) else (
|
||||||
echo docker load -i !TAR_NAME!
|
echo docker load -i !TAR_NAME!
|
||||||
echo docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --force-recreate %SERVICE%
|
echo docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --force-recreate %SERVICE%
|
||||||
@@ -223,6 +254,10 @@ exit /b 0
|
|||||||
:default_output
|
:default_output
|
||||||
if /i "%SERVICE%"=="all" (
|
if /i "%SERVICE%"=="all" (
|
||||||
set "OUTPUT=thebet365-images-%TAG%.tar"
|
set "OUTPUT=thebet365-images-%TAG%.tar"
|
||||||
|
) else if /i "%SERVICE%"=="api-admin" (
|
||||||
|
set "OUTPUT=thebet365-images-%TAG%.tar"
|
||||||
|
) else if /i "%SERVICE%"=="full-themes" (
|
||||||
|
set "OUTPUT=thebet365-full-themes-%TAG%.tar"
|
||||||
) else (
|
) else (
|
||||||
set "OUTPUT=thebet365-%SERVICE%-%TAG%.tar"
|
set "OUTPUT=thebet365-%SERVICE%-%TAG%.tar"
|
||||||
)
|
)
|
||||||
@@ -230,10 +265,12 @@ exit /b 0
|
|||||||
|
|
||||||
:validate_service
|
:validate_service
|
||||||
if /i "%SERVICE%"=="all" exit /b 0
|
if /i "%SERVICE%"=="all" exit /b 0
|
||||||
|
if /i "%SERVICE%"=="api-admin" exit /b 0
|
||||||
|
if /i "%SERVICE%"=="full-themes" exit /b 0
|
||||||
if /i "%SERVICE%"=="api" exit /b 0
|
if /i "%SERVICE%"=="api" exit /b 0
|
||||||
if /i "%SERVICE%"=="player" exit /b 0
|
if /i "%SERVICE%"=="player" exit /b 0
|
||||||
if /i "%SERVICE%"=="admin" exit /b 0
|
if /i "%SERVICE%"=="admin" exit /b 0
|
||||||
echo ERROR: invalid --service: %SERVICE% (use api, player, admin, or all)
|
echo ERROR: invalid --service: %SERVICE% (use api, player, admin, api-admin, full-themes, or all)
|
||||||
echo TIP: 四套主题一键打包请使用 docs\docker\build-and-export-all-themes.bat
|
echo TIP: 四套主题一键打包请使用 docs\docker\build-and-export-all-themes.bat
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
|
||||||
@@ -273,10 +310,19 @@ set "API_IMAGE_ID="
|
|||||||
set "PLAYER_IMAGE_ID="
|
set "PLAYER_IMAGE_ID="
|
||||||
set "ADMIN_IMAGE_ID="
|
set "ADMIN_IMAGE_ID="
|
||||||
set "SVC_IMAGE_ID="
|
set "SVC_IMAGE_ID="
|
||||||
|
set "PLAYER_MAIN_IMAGE_ID="
|
||||||
|
set "PLAYER_THEME2_IMAGE_ID="
|
||||||
|
set "PLAYER_THEME3_IMAGE_ID="
|
||||||
|
set "PLAYER_THEME4_IMAGE_ID="
|
||||||
for /f "delims=" %%I in ('docker image inspect thebet365-api:%TAG% --format "{{.Id}}" 2^>nul') do set "API_IMAGE_ID=%%I"
|
for /f "delims=" %%I in ('docker image inspect thebet365-api:%TAG% --format "{{.Id}}" 2^>nul') do set "API_IMAGE_ID=%%I"
|
||||||
for /f "delims=" %%I in ('docker image inspect thebet365-player:%TAG% --format "{{.Id}}" 2^>nul') do set "PLAYER_IMAGE_ID=%%I"
|
for /f "delims=" %%I in ('docker image inspect thebet365-player:%TAG% --format "{{.Id}}" 2^>nul') do set "PLAYER_IMAGE_ID=%%I"
|
||||||
for /f "delims=" %%I in ('docker image inspect thebet365-admin:%TAG% --format "{{.Id}}" 2^>nul') do set "ADMIN_IMAGE_ID=%%I"
|
for /f "delims=" %%I in ('docker image inspect thebet365-admin:%TAG% --format "{{.Id}}" 2^>nul') do set "ADMIN_IMAGE_ID=%%I"
|
||||||
if /i not "%SERVICE%"=="all" (
|
if /i "%SERVICE%"=="full-themes" (
|
||||||
|
for /f "delims=" %%I in ('docker image inspect thebet365-player:main --format "{{.Id}}" 2^>nul') do set "PLAYER_MAIN_IMAGE_ID=%%I"
|
||||||
|
for /f "delims=" %%I in ('docker image inspect thebet365-player:theme-2 --format "{{.Id}}" 2^>nul') do set "PLAYER_THEME2_IMAGE_ID=%%I"
|
||||||
|
for /f "delims=" %%I in ('docker image inspect thebet365-player:theme-3 --format "{{.Id}}" 2^>nul') do set "PLAYER_THEME3_IMAGE_ID=%%I"
|
||||||
|
for /f "delims=" %%I in ('docker image inspect thebet365-player:theme-4 --format "{{.Id}}" 2^>nul') do set "PLAYER_THEME4_IMAGE_ID=%%I"
|
||||||
|
) else if /i not "%SERVICE%"=="all" (
|
||||||
for /f "delims=" %%I in ('docker image inspect thebet365-%SERVICE%:%TAG% --format "{{.Id}}" 2^>nul') do set "SVC_IMAGE_ID=%%I"
|
for /f "delims=" %%I in ('docker image inspect thebet365-%SERVICE%:%TAG% --format "{{.Id}}" 2^>nul') do set "SVC_IMAGE_ID=%%I"
|
||||||
)
|
)
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
# 鏋勫缓 api / player / admin 鐢熶骇闀滃儚骞跺<EFBFBD>鍑轰负 tar
|
# ?? api / player / admin ???????? tar
|
||||||
# 鐢ㄦ硶锛堝湪椤圭洰鏍圭洰褰曟垨鏈<EFBFBD>洰褰曟墽琛屽潎鍙<EFBFBD>級:
|
# ??????????????????:
|
||||||
# .\docs\docker\build-and-export-images.ps1
|
# .\docs\docker\build-and-export-images.ps1
|
||||||
# .\docs\docker\build-and-export-images.ps1 -Service admin
|
# .\docs\docker\build-and-export-images.ps1 -Service admin
|
||||||
# .\docs\docker\build-and-export-images.ps1 -Tag v1.2.3
|
# .\docs\docker\build-and-export-images.ps1 -Tag v1.2.3
|
||||||
# .\docs\docker\build-and-export-images.ps1 -UseCache
|
# .\docs\docker\build-and-export-images.ps1 -UseCache
|
||||||
# .\docs\docker\build-and-export-images.ps1 -ExportOnly
|
# .\docs\docker\build-and-export-images.ps1 -ExportOnly
|
||||||
#
|
#
|
||||||
# 四套主题玩家端一键打包(自动切分支,推荐):
|
# ????????????????????????????????????
|
||||||
# docs\docker\build-and-export-all-themes.bat
|
# docs\docker\build-and-export-all-themes.bat
|
||||||
|
|
||||||
|
|
||||||
param(
|
param(
|
||||||
[ValidateSet("all", "api", "player", "admin")]
|
[ValidateSet("all", "api", "player", "admin", "api-admin")]
|
||||||
[string]$Service = "all",
|
[string]$Service = "all",
|
||||||
[string]$Tag = $env:IMAGE_TAG,
|
[string]$Tag = $env:IMAGE_TAG,
|
||||||
[switch]$UseCache,
|
[switch]$UseCache,
|
||||||
@@ -31,27 +31,27 @@ function Get-DefaultTag { "latest" }
|
|||||||
|
|
||||||
function Get-DefaultOutput {
|
function Get-DefaultOutput {
|
||||||
param([string]$Svc, [string]$ImageTag)
|
param([string]$Svc, [string]$ImageTag)
|
||||||
if ($Svc -eq "all") { return "thebet365-images-$ImageTag.tar" }
|
if ($Svc -eq "all" -or $Svc -eq "api-admin") { return "thebet365-images-$ImageTag.tar" }
|
||||||
return "thebet365-$Svc-$ImageTag.tar"
|
return "thebet365-$Svc-$ImageTag.tar"
|
||||||
}
|
}
|
||||||
|
|
||||||
function Assert-ImageTag {
|
function Assert-ImageTag {
|
||||||
param([string]$Value)
|
param([string]$Value)
|
||||||
if ($Value -notmatch '^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$') {
|
if ($Value -notmatch '^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$') {
|
||||||
throw "闀滃儚 tag 涓嶅悎娉? $Value"
|
throw "?? tag ???? $Value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $ComposeFile)) {
|
if (-not (Test-Path $ComposeFile)) {
|
||||||
throw "鏈<EFBFBD>壘鍒?$ComposeFile锛堝綋鍓嶇洰褰? $Root锛?
|
throw "????$ComposeFile?????? $Root??
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $EnvFile)) {
|
if (-not (Test-Path $EnvFile)) {
|
||||||
if (Test-Path ".env.docker.example") {
|
if (Test-Path ".env.docker.example") {
|
||||||
Write-Warning "鏈<EFBFBD>壘鍒?.env.docker锛屼娇鐢?.env.docker.example锛堢敓浜ц<EFBFBD>澶嶅埗骞朵慨鏀瑰瘑閽ワ級"
|
Write-Warning "????.env.docker????.env.docker.example????????????"
|
||||||
$EnvFile = ".env.docker.example"
|
$EnvFile = ".env.docker.example"
|
||||||
} else {
|
} else {
|
||||||
throw "鏈<EFBFBD>壘鍒?.env.docker 鎴?.env.docker.example"
|
throw "????.env.docker ??.env.docker.example"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,11 @@ if ([string]::IsNullOrWhiteSpace($Tag)) {
|
|||||||
}
|
}
|
||||||
Assert-ImageTag $Tag
|
Assert-ImageTag $Tag
|
||||||
|
|
||||||
$BuildServices = if ($Service -eq "all") { $AllServices } else { @($Service) }
|
$BuildServices = switch ($Service) {
|
||||||
|
"all" { $AllServices }
|
||||||
|
"api-admin" { @("api", "admin") }
|
||||||
|
default { @($Service) }
|
||||||
|
}
|
||||||
$SaveImages = $BuildServices | ForEach-Object { "thebet365-${_}:${Tag}" }
|
$SaveImages = $BuildServices | ForEach-Object { "thebet365-${_}:${Tag}" }
|
||||||
|
|
||||||
if ([string]::IsNullOrWhiteSpace($Output)) {
|
if ([string]::IsNullOrWhiteSpace($Output)) {
|
||||||
@@ -68,7 +72,7 @@ if ([string]::IsNullOrWhiteSpace($Output)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (-not $ExportOnly) {
|
if (-not $ExportOnly) {
|
||||||
Write-Host "==> 鏋勫缓闀滃儚: $($BuildServices -join ', ') (tag: $Tag)"
|
Write-Host "==> ????: $($BuildServices -join ', ') (tag: $Tag)"
|
||||||
$buildArgs = @(
|
$buildArgs = @(
|
||||||
"compose", "-f", $ComposeFile, "--env-file", $EnvFile, "build"
|
"compose", "-f", $ComposeFile, "--env-file", $EnvFile, "build"
|
||||||
)
|
)
|
||||||
@@ -80,7 +84,7 @@ if (-not $ExportOnly) {
|
|||||||
try {
|
try {
|
||||||
$env:IMAGE_TAG = $Tag
|
$env:IMAGE_TAG = $Tag
|
||||||
& docker @buildArgs
|
& docker @buildArgs
|
||||||
if ($LASTEXITCODE -ne 0) { throw "docker build 澶辫触锛岄€€鍑虹爜 $LASTEXITCODE" }
|
if ($LASTEXITCODE -ne 0) { throw "docker build ?????? $LASTEXITCODE" }
|
||||||
} finally {
|
} finally {
|
||||||
$env:IMAGE_TAG = $oldImageTag
|
$env:IMAGE_TAG = $oldImageTag
|
||||||
}
|
}
|
||||||
@@ -88,9 +92,9 @@ if (-not $ExportOnly) {
|
|||||||
|
|
||||||
$OutputPath = if ([System.IO.Path]::IsPathRooted($Output)) { $Output } else { Join-Path $Root $Output }
|
$OutputPath = if ([System.IO.Path]::IsPathRooted($Output)) { $Output } else { Join-Path $Root $Output }
|
||||||
|
|
||||||
Write-Host "==> 瀵煎嚭闀滃儚 ($Service) -> $OutputPath"
|
Write-Host "==> ???? ($Service) -> $OutputPath"
|
||||||
& docker save @SaveImages -o $OutputPath
|
& docker save @SaveImages -o $OutputPath
|
||||||
if ($LASTEXITCODE -ne 0) { throw "docker save 澶辫触锛岄€€鍑虹爜 $LASTEXITCODE" }
|
if ($LASTEXITCODE -ne 0) { throw "docker save ?????? $LASTEXITCODE" }
|
||||||
|
|
||||||
$manifestPath = if ($OutputPath.EndsWith(".tar")) {
|
$manifestPath = if ($OutputPath.EndsWith(".tar")) {
|
||||||
$OutputPath.Substring(0, $OutputPath.Length - 4) + ".manifest.txt"
|
$OutputPath.Substring(0, $OutputPath.Length - 4) + ".manifest.txt"
|
||||||
@@ -121,7 +125,7 @@ $manifestLines = @(
|
|||||||
)
|
)
|
||||||
foreach ($svc in $BuildServices) {
|
foreach ($svc in $BuildServices) {
|
||||||
$imageId = (& docker image inspect "thebet365-${svc}:${Tag}" --format "{{.Id}}").Trim()
|
$imageId = (& docker image inspect "thebet365-${svc}:${Tag}" --format "{{.Id}}").Trim()
|
||||||
if ($Service -eq "all") {
|
if ($Service -eq "all" -or $Service -eq "api-admin") {
|
||||||
$manifestLines += "${svc}_image=thebet365-${svc}:${Tag}"
|
$manifestLines += "${svc}_image=thebet365-${svc}:${Tag}"
|
||||||
$manifestLines += "${svc}_image_id=$imageId"
|
$manifestLines += "${svc}_image_id=$imageId"
|
||||||
} else {
|
} else {
|
||||||
@@ -132,13 +136,17 @@ foreach ($svc in $BuildServices) {
|
|||||||
$manifestLines | Set-Content -Encoding UTF8 $manifestPath
|
$manifestLines | Set-Content -Encoding UTF8 $manifestPath
|
||||||
|
|
||||||
$sizeMb = [math]::Round((Get-Item $OutputPath).Length / 1MB, 2)
|
$sizeMb = [math]::Round((Get-Item $OutputPath).Length / 1MB, 2)
|
||||||
Write-Host "瀹屾垚: $OutputPath (${sizeMb} MB)"
|
Write-Host "??: $OutputPath (${sizeMb} MB)"
|
||||||
Write-Host "Manifest: $manifestPath"
|
Write-Host "Manifest: $manifestPath"
|
||||||
|
|
||||||
$recreate = if ($Service -eq "all") { "api player admin" } else { $Service }
|
$recreate = switch ($Service) {
|
||||||
|
"all" { "api player admin" }
|
||||||
|
"api-admin" { "api admin" }
|
||||||
|
default { $Service }
|
||||||
|
}
|
||||||
Write-Host @"
|
Write-Host @"
|
||||||
|
|
||||||
鏈嶅姟鍣ㄥ<EFBFBD>鍏ュ苟閲嶅缓:
|
????????:
|
||||||
docker load -i $([System.IO.Path]::GetFileName($OutputPath))
|
docker load -i $([System.IO.Path]::GetFileName($OutputPath))
|
||||||
docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --force-recreate $recreate
|
docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --force-recreate $recreate
|
||||||
"@
|
"@
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ default_tag() { echo "latest"; }
|
|||||||
|
|
||||||
default_output() {
|
default_output() {
|
||||||
local svc="$1" image_tag="$2"
|
local svc="$1" image_tag="$2"
|
||||||
if [[ "$svc" == "all" ]]; then
|
if [[ "$svc" == "all" || "$svc" == "api-admin" ]]; then
|
||||||
echo "thebet365-images-${image_tag}.tar"
|
echo "thebet365-images-${image_tag}.tar"
|
||||||
else
|
else
|
||||||
echo "thebet365-${svc}-${image_tag}.tar"
|
echo "thebet365-${svc}-${image_tag}.tar"
|
||||||
@@ -39,8 +39,8 @@ validate_tag() {
|
|||||||
|
|
||||||
validate_service() {
|
validate_service() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
all|api|player|admin) ;;
|
all|api|player|admin|api-admin) ;;
|
||||||
*) echo "错误: --service 无效: $1(可选 api / player / admin / all)" >&2; exit 1 ;;
|
*) echo "错误: --service 无效: $1(可选 api / player / admin / api-admin / all)" >&2; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ usage() {
|
|||||||
用法: docs/docker/build-and-export-images.sh [选项]
|
用法: docs/docker/build-and-export-images.sh [选项]
|
||||||
|
|
||||||
选项:
|
选项:
|
||||||
--service SVC api | player | admin | all(默认 all)
|
--service SVC api | player | admin | api-admin | all(默认 all)
|
||||||
--tag TAG 镜像 tag(默认 latest)
|
--tag TAG 镜像 tag(默认 latest)
|
||||||
--use-cache 构建时使用 Docker 缓存(默认 --no-cache)
|
--use-cache 构建时使用 Docker 缓存(默认 --no-cache)
|
||||||
--export-only 跳过构建,仅导出已有指定 tag 镜像
|
--export-only 跳过构建,仅导出已有指定 tag 镜像
|
||||||
@@ -105,6 +105,8 @@ OUTPUT="${OUTPUT:-$(default_output "$SERVICE" "$TAG")}"
|
|||||||
|
|
||||||
if [[ "$SERVICE" == "all" ]]; then
|
if [[ "$SERVICE" == "all" ]]; then
|
||||||
BUILD_SERVICES=(api player admin)
|
BUILD_SERVICES=(api player admin)
|
||||||
|
elif [[ "$SERVICE" == "api-admin" ]]; then
|
||||||
|
BUILD_SERVICES=(api admin)
|
||||||
else
|
else
|
||||||
BUILD_SERVICES=("$SERVICE")
|
BUILD_SERVICES=("$SERVICE")
|
||||||
fi
|
fi
|
||||||
@@ -161,7 +163,7 @@ fi
|
|||||||
echo "tar=$(basename "$OUTPUT_PATH")"
|
echo "tar=$(basename "$OUTPUT_PATH")"
|
||||||
echo "tar_sha256=$CHECKSUM"
|
echo "tar_sha256=$CHECKSUM"
|
||||||
for svc in "${BUILD_SERVICES[@]}"; do
|
for svc in "${BUILD_SERVICES[@]}"; do
|
||||||
if [[ "$SERVICE" == "all" ]]; then
|
if [[ "$SERVICE" == "all" || "$SERVICE" == "api-admin" ]]; then
|
||||||
echo "${svc}_image=thebet365-${svc}:$TAG"
|
echo "${svc}_image=thebet365-${svc}:$TAG"
|
||||||
echo "${svc}_image_id=$(docker image inspect "thebet365-${svc}:$TAG" --format '{{.Id}}')"
|
echo "${svc}_image_id=$(docker image inspect "thebet365-${svc}:$TAG" --format '{{.Id}}')"
|
||||||
else
|
else
|
||||||
@@ -182,6 +184,8 @@ echo "Manifest: $MANIFEST_PATH"
|
|||||||
RECREATE="$SERVICE"
|
RECREATE="$SERVICE"
|
||||||
if [[ "$SERVICE" == "all" ]]; then
|
if [[ "$SERVICE" == "all" ]]; then
|
||||||
RECREATE="api player admin"
|
RECREATE="api player admin"
|
||||||
|
elif [[ "$SERVICE" == "api-admin" ]]; then
|
||||||
|
RECREATE="api admin"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
| `docs/docker/build-and-export-player-theme-3.bat` | Windows(仅 theme-3 移动主题,自动切分支) |
|
| `docs/docker/build-and-export-player-theme-3.bat` | Windows(仅 theme-3 移动主题,自动切分支) |
|
||||||
| `docs/docker/build-and-export-player-theme-4.bat` | Windows(仅 theme-4 海军蓝极简,自动切分支) |
|
| `docs/docker/build-and-export-player-theme-4.bat` | Windows(仅 theme-4 海军蓝极简,自动切分支) |
|
||||||
| `docs/docker/build-and-export-admin.bat` | Windows(仅 admin,可双击) |
|
| `docs/docker/build-and-export-admin.bat` | Windows(仅 admin,可双击) |
|
||||||
| `docs/docker/build-and-export-all-themes.bat` | Windows(**四套主题 player 一键打包**,自动切分支) |
|
| `docs/docker/build-and-export-all-themes.ps1` | Windows(**四套主题 player 一键打包**,自动切分支,推荐) |
|
||||||
|
| `docs/docker/build-and-export-all-themes.bat` | Windows(同上,薄包装启动器,双击可用) |
|
||||||
| `docs/docker/build-and-export-images.ps1` | Windows(PowerShell) |
|
| `docs/docker/build-and-export-images.ps1` | Windows(PowerShell) |
|
||||||
| `docs/docker/build-and-export-images.sh` | Linux / macOS / Git Bash |
|
| `docs/docker/build-and-export-images.sh` | Linux / macOS / Git Bash |
|
||||||
|
|
||||||
@@ -131,18 +132,27 @@ docs\docker\build-and-export-images.bat --export-only
|
|||||||
|
|
||||||
脚本会自动:切到各主题分支 → 构建 player 镜像 → 导出 tar → 切回原分支 → 构建 api/admin。
|
脚本会自动:切到各主题分支 → 构建 player 镜像 → 导出 tar → 切回原分支 → 构建 api/admin。
|
||||||
|
|
||||||
```bat
|
> **为何用 PowerShell?** 本脚本仅存在于 `main` 分支;执行过程中会 `git checkout theme-*`,CMD 批处理会从磁盘逐行读取,切分支后脚本文件消失会导致中断。PowerShell 启动时已将整份脚本载入内存,可安全跨分支执行。`.bat` 仅为薄包装,内部转调 `.ps1`。
|
||||||
|
|
||||||
|
```powershell
|
||||||
cd C:\path\to\thebet365
|
cd C:\path\to\thebet365
|
||||||
|
.\docs\docker\build-and-export-all-themes.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
或双击 / CMD:
|
||||||
|
|
||||||
|
```bat
|
||||||
docs\docker\build-and-export-all-themes.bat
|
docs\docker\build-and-export-all-themes.bat
|
||||||
```
|
```
|
||||||
|
|
||||||
可选参数:
|
可选参数(PowerShell 与 bat 均支持):
|
||||||
|
|
||||||
| 参数 | 说明 |
|
| 参数 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `--use-cache` | 使用 Docker 层缓存,加快重复构建速度 |
|
| `-UseCache` / `--use-cache` | 使用 Docker 层缓存,加快重复构建速度 |
|
||||||
| `--export-only` | 跳过构建,仅导出本地已有镜像 |
|
| `-ExportOnly` / `--export-only` | 跳过构建,仅导出本地已有镜像 |
|
||||||
| `--skip-api-admin` | 只打四套 player,跳过 api/admin |
|
| `-SkipApiAdmin` / `--skip-api-admin` | 只打四套 player,跳过 api/admin |
|
||||||
|
| `-SkipBundle` / `--skip-bundle` | 跳过六合一包,仅保留分散 tar |
|
||||||
|
|
||||||
### 产物
|
### 产物
|
||||||
|
|
||||||
@@ -153,6 +163,13 @@ docs\docker\build-and-export-all-themes.bat
|
|||||||
| `thebet365-player-theme-3.tar` | `thebet365-player:theme-3` |
|
| `thebet365-player-theme-3.tar` | `thebet365-player:theme-3` |
|
||||||
| `thebet365-player-theme-4.tar` | `thebet365-player:theme-4` |
|
| `thebet365-player-theme-4.tar` | `thebet365-player:theme-4` |
|
||||||
| `thebet365-images-latest.tar` | `thebet365-api:latest` + `thebet365-admin:latest` |
|
| `thebet365-images-latest.tar` | `thebet365-api:latest` + `thebet365-admin:latest` |
|
||||||
|
| **`thebet365-full-themes-latest.tar`** | **上面全部 6 个镜像(上传这一个即可)** |
|
||||||
|
|
||||||
|
也可单独导出六合一包(本地镜像已齐时):
|
||||||
|
|
||||||
|
```bat
|
||||||
|
docs\docker\build-and-export-images.bat --service full-themes --export-only --tag latest
|
||||||
|
```
|
||||||
|
|
||||||
### 分支要求
|
### 分支要求
|
||||||
|
|
||||||
|
|||||||
@@ -276,7 +276,18 @@ pnpm dev:player # http://localhost:5173 目视确认仍是本主题皮
|
|||||||
|
|
||||||
## 六、构建与上传镜像
|
## 六、构建与上传镜像
|
||||||
|
|
||||||
### 6.1 四个 player 镜像(Windows CMD)
|
### 6.1 四个 player 镜像
|
||||||
|
|
||||||
|
**一键打包(推荐,仅 `main` 分支提供脚本):**
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd C:\path\to\thebet365
|
||||||
|
.\docs\docker\build-and-export-all-themes.ps1 -SkipApiAdmin
|
||||||
|
```
|
||||||
|
|
||||||
|
或 `docs\docker\build-and-export-all-themes.bat --skip-api-admin`(内部转调 PowerShell,避免切分支后 bat 从磁盘消失)。
|
||||||
|
|
||||||
|
**手动逐步(Windows CMD):**
|
||||||
|
|
||||||
```bat
|
```bat
|
||||||
cd C:\path\to\thebet365
|
cd C:\path\to\thebet365
|
||||||
|
|||||||
Reference in New Issue
Block a user