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.
329 lines
10 KiB
Batchfile
329 lines
10 KiB
Batchfile
@echo off
|
|
setlocal EnableDelayedExpansion
|
|
|
|
REM Build api/player/admin images and export as tar (Windows CMD).
|
|
REM Usage:
|
|
REM docs\docker\build-and-export-images.bat
|
|
REM docs\docker\build-and-export-images.bat --service admin
|
|
REM docs\docker\build-and-export-images.bat --tag v1.2.3
|
|
REM docs\docker\build-and-export-images.bat --use-cache
|
|
REM docs\docker\build-and-export-images.bat --export-only
|
|
REM
|
|
REM 四套主题玩家端一键打包(自动切分支,推荐):
|
|
REM docs\docker\build-and-export-all-themes.bat
|
|
|
|
cd /d "%~dp0..\.."
|
|
|
|
set "COMPOSE_FILE=docker-compose.prod.yml"
|
|
set "ENV_FILE=.env.docker"
|
|
set "OUTPUT="
|
|
set "NO_CACHE=1"
|
|
set "EXPORT_ONLY=0"
|
|
set "SERVICE=all"
|
|
if defined IMAGE_TAG (set "TAG=%IMAGE_TAG%") else (set "TAG=")
|
|
|
|
:parse_args
|
|
if "%~1"=="" goto args_done
|
|
if /i "%~1"=="--tag" goto parse_tag
|
|
if /i "%~1"=="--service" goto parse_service
|
|
if /i "%~1"=="--use-cache" set "NO_CACHE=0" & shift & goto parse_args
|
|
if /i "%~1"=="--export-only" set "EXPORT_ONLY=1" & shift & goto parse_args
|
|
if /i "%~1"=="--output" goto parse_output
|
|
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
|
|
|
|
:parse_tag
|
|
if "%~2"=="" (
|
|
echo ERROR: missing value for --tag
|
|
exit /b 1
|
|
)
|
|
set "TAG=%~2"
|
|
shift
|
|
shift
|
|
goto parse_args
|
|
|
|
:parse_service
|
|
if "%~2"=="" (
|
|
echo ERROR: missing value for --service
|
|
exit /b 1
|
|
)
|
|
set "SERVICE=%~2"
|
|
shift
|
|
shift
|
|
goto parse_args
|
|
|
|
:parse_output
|
|
if "%~2"=="" (
|
|
echo ERROR: missing value for --output
|
|
exit /b 1
|
|
)
|
|
set "OUTPUT=%~2"
|
|
shift
|
|
shift
|
|
goto parse_args
|
|
|
|
:show_help
|
|
echo.
|
|
echo Usage: docs\docker\build-and-export-images.bat [options]
|
|
echo.
|
|
echo --service SVC api ^| player ^| admin ^| api-admin ^| full-themes ^| all (default: all)
|
|
echo --tag TAG Image tag (default: latest)
|
|
echo --use-cache Use Docker build cache
|
|
echo --export-only Skip build, export existing images only
|
|
echo --output PATH Output tar path
|
|
echo -h, --help Show help
|
|
echo.
|
|
echo Examples:
|
|
echo docs\docker\build-and-export-images.bat --service admin
|
|
echo docs\docker\build-and-export-admin.bat
|
|
echo docs\docker\build-and-export-admin.bat --export-only
|
|
echo.
|
|
echo 四套主题玩家端批量打包(自动切分支,推荐):
|
|
echo docs\docker\build-and-export-all-themes.bat
|
|
echo.
|
|
exit /b 0
|
|
|
|
:args_done
|
|
if not exist "%COMPOSE_FILE%" (
|
|
echo ERROR: missing %COMPOSE_FILE% in %CD%
|
|
exit /b 1
|
|
)
|
|
|
|
if not exist "%ENV_FILE%" (
|
|
if exist ".env.docker.example" (
|
|
echo WARN: using .env.docker.example instead of .env.docker
|
|
set "ENV_FILE=.env.docker.example"
|
|
) else (
|
|
echo ERROR: missing .env.docker and .env.docker.example
|
|
exit /b 1
|
|
)
|
|
)
|
|
|
|
call :validate_service
|
|
if errorlevel 1 exit /b 1
|
|
|
|
if not defined TAG call :default_tag
|
|
if not defined TAG (
|
|
echo ERROR: unable to determine image tag
|
|
exit /b 1
|
|
)
|
|
|
|
call :validate_tag
|
|
if errorlevel 1 exit /b 1
|
|
|
|
if not defined OUTPUT call :default_output
|
|
|
|
set "OUTPUT_PATH=%OUTPUT%"
|
|
if /i not "%OUTPUT:~1,1%"==":" set "OUTPUT_PATH=%CD%\%OUTPUT%"
|
|
|
|
where docker >nul 2>&1
|
|
if errorlevel 1 (
|
|
echo ERROR: docker not found. Start Docker Desktop first.
|
|
exit /b 1
|
|
)
|
|
|
|
if "%EXPORT_ONLY%"=="0" if /i not "%SERVICE%"=="full-themes" goto do_build
|
|
goto do_export
|
|
|
|
:do_build
|
|
echo ==^> Building %SERVICE% (tag: %TAG%)
|
|
set "IMAGE_TAG=%TAG%"
|
|
if "%NO_CACHE%"=="1" goto build_no_cache
|
|
if /i "%SERVICE%"=="all" (
|
|
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 (
|
|
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build %SERVICE%
|
|
)
|
|
goto build_done
|
|
|
|
:build_no_cache
|
|
if /i "%SERVICE%"=="all" (
|
|
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 (
|
|
docker compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" build --no-cache %SERVICE%
|
|
)
|
|
|
|
:build_done
|
|
if errorlevel 1 (
|
|
echo ERROR: docker build failed
|
|
exit /b 1
|
|
)
|
|
|
|
:do_export
|
|
echo ==^> Exporting %SERVICE% to %OUTPUT_PATH%
|
|
if /i "%SERVICE%"=="all" (
|
|
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 (
|
|
docker save thebet365-%SERVICE%:%TAG% -o "%OUTPUT_PATH%"
|
|
)
|
|
if errorlevel 1 (
|
|
echo ERROR: docker save failed
|
|
exit /b 1
|
|
)
|
|
|
|
if /i "%OUTPUT_PATH:~-4%"==".tar" (
|
|
set "MANIFEST_PATH=%OUTPUT_PATH:~0,-4%.manifest.txt"
|
|
) else (
|
|
set "MANIFEST_PATH=%OUTPUT_PATH%.manifest.txt"
|
|
)
|
|
|
|
call :collect_git_info
|
|
call :collect_built_at
|
|
call :collect_tar_sha256
|
|
call :collect_image_ids
|
|
|
|
for %%F in ("%OUTPUT_PATH%") do set "TAR_NAME=%%~nxF"
|
|
for %%F in ("%OUTPUT_PATH%") do set /a SIZE_MB=%%~zF/1048576
|
|
|
|
> "%MANIFEST_PATH%" (
|
|
echo tag=%TAG%
|
|
echo service=%SERVICE%
|
|
echo built_at=!BUILT_AT!
|
|
echo git_commit=!GIT_COMMIT!
|
|
echo git_dirty=!GIT_DIRTY!
|
|
echo tar=!TAR_NAME!
|
|
echo tar_sha256=!TAR_SHA256!
|
|
if /i "!SERVICE!"=="all" (
|
|
echo api_image=thebet365-api:%TAG%
|
|
echo api_image_id=!API_IMAGE_ID!
|
|
echo player_image=thebet365-player:%TAG%
|
|
echo player_image_id=!PLAYER_IMAGE_ID!
|
|
echo admin_image=thebet365-admin:%TAG%
|
|
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!
|
|
)
|
|
)
|
|
|
|
echo Done: %OUTPUT_PATH% ^(!SIZE_MB! MB^)
|
|
echo Manifest: %MANIFEST_PATH%
|
|
echo.
|
|
echo Server load and recreate:
|
|
if /i "%SERVICE%"=="all" (
|
|
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
|
|
) 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 (
|
|
echo docker load -i !TAR_NAME!
|
|
echo docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --force-recreate %SERVICE%
|
|
)
|
|
echo.
|
|
|
|
endlocal
|
|
exit /b 0
|
|
|
|
:default_tag
|
|
set "TAG=latest"
|
|
exit /b 0
|
|
|
|
:default_output
|
|
if /i "%SERVICE%"=="all" (
|
|
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 (
|
|
set "OUTPUT=thebet365-%SERVICE%-%TAG%.tar"
|
|
)
|
|
exit /b 0
|
|
|
|
:validate_service
|
|
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%"=="player" exit /b 0
|
|
if /i "%SERVICE%"=="admin" exit /b 0
|
|
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
|
|
exit /b 1
|
|
|
|
:validate_tag
|
|
echo %TAG%| findstr /r "^[A-Za-z0-9_][A-Za-z0-9_.-]*$" >nul
|
|
if errorlevel 1 (
|
|
echo ERROR: invalid image tag: %TAG%
|
|
exit /b 1
|
|
)
|
|
exit /b 0
|
|
|
|
:collect_git_info
|
|
set "GIT_COMMIT=unknown"
|
|
set "GIT_DIRTY=unknown"
|
|
for /f "delims=" %%C in ('git rev-parse HEAD 2^>nul') do set "GIT_COMMIT=%%C"
|
|
git diff --quiet 2>nul
|
|
set "DIFF_EXIT=!ERRORLEVEL!"
|
|
git diff --cached --quiet 2>nul
|
|
set "CACHED_EXIT=!ERRORLEVEL!"
|
|
if "!DIFF_EXIT!"=="0" if "!CACHED_EXIT!"=="0" set "GIT_DIRTY=false"
|
|
if not "!GIT_COMMIT!"=="unknown" if not "!GIT_DIRTY!"=="false" set "GIT_DIRTY=true"
|
|
exit /b 0
|
|
|
|
:collect_built_at
|
|
set "BUILT_AT=unknown"
|
|
for /f "delims=" %%T in ('powershell -NoProfile -Command "(Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')"') do set "BUILT_AT=%%T"
|
|
exit /b 0
|
|
|
|
:collect_tar_sha256
|
|
set "TAR_SHA256=unavailable"
|
|
for /f "usebackq delims=" %%H in (`certutil -hashfile "%OUTPUT_PATH%" SHA256 ^| findstr /r "^[0-9a-fA-F][0-9a-fA-F]"`) do set "TAR_SHA256=%%H"
|
|
if defined TAR_SHA256 set "TAR_SHA256=!TAR_SHA256: =!"
|
|
exit /b 0
|
|
|
|
:collect_image_ids
|
|
set "API_IMAGE_ID="
|
|
set "PLAYER_IMAGE_ID="
|
|
set "ADMIN_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-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"
|
|
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"
|
|
)
|
|
exit /b 0
|