156 lines
9.1 KiB
Batchfile
156 lines
9.1 KiB
Batchfile
@echo off
|
|
setlocal EnableDelayedExpansion
|
|
title Campus - upload newest updates
|
|
|
|
REM ============================================================================
|
|
REM Ships ONLY the server assembly - CampusServer.dll, about 2 MB.
|
|
REM
|
|
REM PackageServer.ps1 + DeployCampusServer.bat rebuild and re-upload the whole
|
|
REM tree, and Data\ alone is ~280 MB of that. None of it changes when the edits
|
|
REM are C#, so this publishes the same Release/linux-x64 build, copies out the
|
|
REM one assembly and restarts the service.
|
|
REM
|
|
REM USE THE FULL PackageServer.ps1 PATH INSTEAD WHEN:
|
|
REM - anything under Data\, Web\, Website\ or AdminPanel\ changed
|
|
REM - a NuGet package was added (a new .dll in the publish output is NOT sent)
|
|
REM Adding a new .cs file is fine - it compiles into CampusServer.dll.
|
|
REM
|
|
REM The live assembly is copied to CampusServer.dll.prev before the swap, so the
|
|
REM rollback below always works and never needs a rebuild.
|
|
REM ============================================================================
|
|
|
|
set "ROOT=%~dp0"
|
|
set "CSPROJ=%ROOT%Server\2025-RecRoom-Server-E12354-main\CampusServer.csproj"
|
|
set "CSPROJDIR=%ROOT%Server\2025-RecRoom-Server-E12354-main\"
|
|
set "OUT=%TEMP%\campus-dllupload"
|
|
set "VPS=root@50.114.179.17"
|
|
set "REMOTE=/opt/campus"
|
|
|
|
echo.
|
|
echo === Campus fast deploy =====================================================
|
|
echo.
|
|
|
|
REM ---- preflight -------------------------------------------------------------
|
|
for %%T in (dotnet.exe pscp.exe plink.exe) do (
|
|
where %%T >nul 2>&1 || (echo [x] %%T is not on PATH. & goto :fail)
|
|
)
|
|
if not exist "%CSPROJ%" (echo [x] Cannot find %CSPROJ% & goto :fail)
|
|
if not exist "%ROOT%Password.txt" (echo [x] Cannot find %ROOT%Password.txt & goto :fail)
|
|
|
|
set "PW="
|
|
for /f "usebackq delims=" %%p in ("%ROOT%Password.txt") do if not defined PW set "PW=%%p"
|
|
if not defined PW (echo [x] Password.txt is empty. & goto :fail)
|
|
|
|
REM ---- 1/4 build -------------------------------------------------------------
|
|
echo [1/4] Publishing (Release, linux-x64) ...
|
|
dotnet publish "%CSPROJ%" -c Release -r linux-x64 --self-contained true -o "%OUT%" -v quiet -clp:ErrorsOnly
|
|
if errorlevel 1 (echo. & echo [x] Build FAILED - nothing was uploaded. & goto :fail)
|
|
if not exist "%OUT%\CampusServer.dll" (echo [x] No CampusServer.dll in %OUT% & goto :fail)
|
|
|
|
for %%F in ("%OUT%\CampusServer.dll") do set /a "KB=%%~zF/1024"
|
|
echo built CampusServer.dll (!KB! KB)
|
|
|
|
REM ---- 2/4 upload ------------------------------------------------------------
|
|
echo [2/4] Uploading to %VPS% ...
|
|
pscp -batch -pw %PW% "%OUT%\CampusServer.dll" "%VPS%:%REMOTE%/CampusServer.dll.new"
|
|
if errorlevel 1 (echo. & echo [x] Upload FAILED - the live server is untouched. & goto :fail)
|
|
|
|
REM The pdb is optional - it is what turns a stack trace in journalctl into file
|
|
REM and line numbers. Failing to send it must not fail the deploy.
|
|
if exist "%OUT%\CampusServer.pdb" (
|
|
pscp -batch -pw %PW% "%OUT%\CampusServer.pdb" "%VPS%:%REMOTE%/CampusServer.pdb.new" >nul 2>&1
|
|
)
|
|
|
|
REM The admin panel page. It lives under Web\, which this script otherwise skips - but it
|
|
REM is a single static file the server reads off disk, so shipping it here costs nothing and
|
|
REM saves a 286 MB PackageServer run every time a panel button changes. Everything ELSE under
|
|
REM Web\ / Website\ / Data\ still needs the full path.
|
|
set "ADMINPAGE=%CSPROJDIR%Web\Admin\Home\HomeV4.html"
|
|
if exist "%ADMINPAGE%" (
|
|
echo + admin panel page
|
|
pscp -batch -pw %PW% "%ADMINPAGE%" "%VPS%:%REMOTE%/Web/Admin/Home/HomeV4.html"
|
|
if errorlevel 1 (echo. & echo [x] Admin page upload FAILED - the live server is untouched. & goto :fail)
|
|
)
|
|
|
|
REM The charades word lists (Data\APIS\Charades\*.json). A few KB that the ^3DCharades rooms
|
|
REM read, so they go with the DLL instead of waiting on a full PackageServer run.
|
|
set "CHARADES=%CSPROJDIR%Data\APIS\Charades"
|
|
if exist "%CHARADES%\Charades.json" (
|
|
echo + charades word lists
|
|
plink -batch -pw %PW% %VPS% "mkdir -p %REMOTE%/Data/APIS/Charades" >nul 2>&1
|
|
pscp -batch -pw %PW% "%CHARADES%\*.json" "%VPS%:%REMOTE%/Data/APIS/Charades/"
|
|
if errorlevel 1 (echo. & echo [x] Charades upload FAILED - the live server is untouched. & goto :fail)
|
|
)
|
|
|
|
REM The first-party custom-item overlay + the Watch store (ImportRealStore.py output). ~16 MB
|
|
REM between them, and the whole point of an update is usually one of these, so they ride with
|
|
REM the DLL instead of waiting on a full PackageServer run. UGC.json (70 MB) still needs that.
|
|
set "ITEMS=%CSPROJDIR%Data\APIS\items"
|
|
if exist "%ITEMS%\FirstPartyUGC.json" (
|
|
echo + first-party custom items + Watch store
|
|
pscp -batch -pw %PW% "%ITEMS%\FirstPartyUGC.json" "%VPS%:%REMOTE%/Data/APIS/items/FirstPartyUGC.json"
|
|
if errorlevel 1 (echo. & echo [x] FirstPartyUGC upload FAILED - the live server is untouched. & goto :fail)
|
|
pscp -batch -pw %PW% "%CSPROJDIR%Data\APIS\GiftDropStores\3.json" "%VPS%:%REMOTE%/Data/APIS/GiftDropStores/3.json"
|
|
if errorlevel 1 (echo. & echo [x] Store upload FAILED - the live server is untouched. & goto :fail)
|
|
pscp -batch -pw %PW% "%ITEMS%\ShownItems.json" "%VPS%:%REMOTE%/Data/APIS/items/ShownItems.json"
|
|
if errorlevel 1 (echo. & echo [x] ShownItems upload FAILED - the live server is untouched. & goto :fail)
|
|
)
|
|
|
|
REM ---- 2b/4 CampusNet (the Photon-protocol game server) ---------------------
|
|
REM Built and shipped alongside, but only when its binary actually changed: the
|
|
REM single-file publish is ~65 MB, so it is hashed against what the VPS runs and
|
|
REM skipped when identical. It is swapped with ITS OWN service stopped (same
|
|
REM overwrite-under-a-running-process rule), and its restart drops every player's
|
|
REM Photon link for a moment - they reconnect on their own.
|
|
set "NETPROJ=%ROOT%CampusNet\CampusNet.csproj"
|
|
set "NETOUT=%TEMP%\campus-netupload"
|
|
if exist "%NETPROJ%" (
|
|
echo [2b/4] Publishing CampusNet ...
|
|
dotnet publish "%NETPROJ%" -c Release -r linux-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -o "%NETOUT%" -v quiet -clp:ErrorsOnly
|
|
if errorlevel 1 (echo. & echo [x] CampusNet build FAILED - nothing was uploaded. & goto :fail)
|
|
set "NETLOCAL="
|
|
for /f "skip=1 tokens=1" %%h in ('certutil -hashfile "%NETOUT%\campusnet" SHA256 ^| findstr /v /i "certutil"') do if not defined NETLOCAL set "NETLOCAL=%%h"
|
|
set "NETREMOTE="
|
|
for /f "tokens=1" %%h in ('plink -batch -pw %PW% %VPS% "sha256sum /opt/campusnet/campusnet 2>/dev/null"') do if not defined NETREMOTE set "NETREMOTE=%%h"
|
|
if /i "!NETLOCAL!"=="!NETREMOTE!" (
|
|
echo CampusNet unchanged - skipped
|
|
) else (
|
|
echo uploading campusnet ^(~65 MB^) ...
|
|
pscp -batch -pw %PW% "%NETOUT%\campusnet" "%VPS%:/opt/campusnet/campusnet.new"
|
|
if errorlevel 1 (echo. & echo [x] CampusNet upload FAILED - the live servers are untouched. & goto :fail)
|
|
plink -batch -pw %PW% %VPS% "set -e; chmod +x /opt/campusnet/campusnet.new; cp -f /opt/campusnet/campusnet /opt/campusnet/campusnet.prev; systemctl stop campusnet; mv /opt/campusnet/campusnet.new /opt/campusnet/campusnet; systemctl start campusnet; sleep 2; systemctl is-active --quiet campusnet || { echo 'CAMPUSNET IS NOT RUNNING'; journalctl -u campusnet -n 20 --no-pager; exit 1; }; echo ' campusnet restarted'"
|
|
if errorlevel 1 (echo. & echo [x] CampusNet swap FAILED. Previous binary is /opt/campusnet/campusnet.prev & goto :fail)
|
|
)
|
|
)
|
|
|
|
REM ---- 3/4 swap --------------------------------------------------------------
|
|
REM With the service STOPPED. Overwriting a DLL under a running process is what
|
|
REM caused the SIGBUS / BadImageFormat crashes in the deploy notes.
|
|
echo [3/4] Backing up, swapping, restarting ...
|
|
plink -batch -pw %PW% %VPS% "set -e; cp -f %REMOTE%/CampusServer.dll %REMOTE%/CampusServer.dll.prev; systemctl stop campus; mv %REMOTE%/CampusServer.dll.new %REMOTE%/CampusServer.dll; if [ -f %REMOTE%/CampusServer.pdb.new ]; then mv %REMOTE%/CampusServer.pdb.new %REMOTE%/CampusServer.pdb; fi; systemctl start campus"
|
|
if errorlevel 1 (echo. & echo [x] Swap FAILED. & goto :rollbackhint)
|
|
|
|
REM ---- 4/4 verify ------------------------------------------------------------
|
|
echo [4/4] Waiting for it to come back up ...
|
|
plink -batch -pw %PW% %VPS% "sleep 12; systemctl is-active --quiet campus || { echo 'SERVICE IS NOT RUNNING'; journalctl -u campus -n 30 --no-pager; exit 1; }; journalctl -u campus --since '-2min' --no-pager | grep -qE 'Now listening' || { echo 'STARTED BUT NEVER BOUND A PORT'; journalctl -u campus -n 30 --no-pager; exit 1; }; echo '--- startup ---'; journalctl -u campus --since '-2min' --no-pager | grep -E 'Now listening|\[orientation\]|\[hair\]|\[items\]|\[rooms\]|\[signup-guard\]' | tail -12"
|
|
if errorlevel 1 (echo. & echo [x] The server did NOT come back healthy. & goto :rollbackhint)
|
|
|
|
echo.
|
|
echo === DONE. Live on https://gameauth.ddns.net ================================
|
|
echo.
|
|
echo If something is wrong, roll back with: RollbackUpdate.bat
|
|
echo.
|
|
endlocal
|
|
exit /b 0
|
|
|
|
:rollbackhint
|
|
echo.
|
|
echo The previous assembly is still on the VPS as CampusServer.dll.prev.
|
|
echo Roll back with: RollbackUpdate.bat
|
|
:fail
|
|
echo.
|
|
echo === FAILED =================================================================
|
|
echo.
|
|
endlocal
|
|
exit /b 1
|