fix(updater): build in temp directory, replace old launcher binary, and cleanup temp
This commit is contained in:
1 parent
0ec9f62857
commit
0a97749a1c
8 files changed
+281
-98
No files matched your search
@@ -10,7 +10,7 @@ import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Cr
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function CloseApp() {
|
||||
return $Call.ByID(3422460836);
|
||||
return $Call.ByID(1501559548);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -18,40 +18,40 @@ export function CloseApp() {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function CloseAppAfterTimeout(timeout) {
|
||||
return $Call.ByID(1705931481, timeout);
|
||||
return $Call.ByID(1916027393, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function GetCurrentLauncherVersion() {
|
||||
return $Call.ByID(3575133982);
|
||||
return $Call.ByID(1802499222);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function HideApp() {
|
||||
return $Call.ByID(88003266);
|
||||
return $Call.ByID(2987475338);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function MaximizeApp() {
|
||||
return $Call.ByID(1257306588);
|
||||
return $Call.ByID(1960157700);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function MinimizeApp() {
|
||||
return $Call.ByID(3434614194);
|
||||
return $Call.ByID(227494378);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function RestoreApp() {
|
||||
return $Call.ByID(3115625834);
|
||||
return $Call.ByID(229693554);
|
||||
}
|
||||
@@ -6,12 +6,21 @@
|
||||
// @ts-ignore: Unused imports
|
||||
import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime";
|
||||
|
||||
/**
|
||||
* @param {string} gamePath
|
||||
* @param {string} patchPath
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function ApplyDiffZiff(gamePath, patchPath) {
|
||||
return $Call.ByID(3398476317, gamePath, patchPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} patchPath
|
||||
* @returns {$CancellablePromise<[boolean, string, string]>}
|
||||
*/
|
||||
export function CheckTypeHDiff(patchPath) {
|
||||
return $Call.ByID(3717449114, patchPath);
|
||||
return $Call.ByID(2449959810, patchPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -19,7 +28,7 @@ export function CheckTypeHDiff(patchPath) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function CutData(gamePath) {
|
||||
return $Call.ByID(2019290107, gamePath);
|
||||
return $Call.ByID(279510819, gamePath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,7 +37,7 @@ export function CutData(gamePath) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function DataExtract(gamePath, patchPath) {
|
||||
return $Call.ByID(2161622254, gamePath, patchPath);
|
||||
return $Call.ByID(3151294534, gamePath, patchPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +45,7 @@ export function DataExtract(gamePath, patchPath) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function DeleteFiles(gamePath) {
|
||||
return $Call.ByID(1103091613, gamePath);
|
||||
return $Call.ByID(308950549, gamePath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +53,7 @@ export function DeleteFiles(gamePath) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function HDiffPatchData(gamePath) {
|
||||
return $Call.ByID(3944051994, gamePath);
|
||||
return $Call.ByID(4008196450, gamePath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +61,7 @@ export function HDiffPatchData(gamePath) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function LDiffPatchData(gamePath) {
|
||||
return $Call.ByID(360123238, gamePath);
|
||||
return $Call.ByID(2041639182, gamePath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,5 +70,5 @@ export function LDiffPatchData(gamePath) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function VersionValidate(gamePath, patchPath) {
|
||||
return $Call.ByID(2105077257, gamePath, patchPath);
|
||||
return $Call.ByID(169848129, gamePath, patchPath);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Cr
|
||||
* @returns {$CancellablePromise<boolean>}
|
||||
*/
|
||||
export function DirExists(path) {
|
||||
return $Call.ByID(1772289644, path);
|
||||
return $Call.ByID(4102029604, path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -19,7 +19,7 @@ export function DirExists(path) {
|
||||
* @returns {$CancellablePromise<boolean>}
|
||||
*/
|
||||
export function FileExists(path) {
|
||||
return $Call.ByID(1782610747, path);
|
||||
return $Call.ByID(865459, path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,7 +28,7 @@ export function FileExists(path) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function FileExistsInZip(archivePath, fileInside) {
|
||||
return $Call.ByID(2509699047, archivePath, fileInside);
|
||||
return $Call.ByID(3506095695, archivePath, fileInside);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +36,14 @@ export function FileExistsInZip(archivePath, fileInside) {
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function GetDir(path) {
|
||||
return $Call.ByID(1744445742, path);
|
||||
return $Call.ByID(1567262998, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<[string, string]>}
|
||||
*/
|
||||
export function GetSavedGameSelection() {
|
||||
return $Call.ByID(858061230);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +51,7 @@ export function GetDir(path) {
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function Join(...paths) {
|
||||
return $Call.ByID(2460588289, paths);
|
||||
return $Call.ByID(3036412633, paths);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +59,7 @@ export function Join(...paths) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function OpenFolder(path) {
|
||||
return $Call.ByID(1635714001, path);
|
||||
return $Call.ByID(1601714793, path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,14 +67,23 @@ export function OpenFolder(path) {
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function PickFile(filter) {
|
||||
return $Call.ByID(3756474934, filter);
|
||||
return $Call.ByID(2493433102, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function PickFolder() {
|
||||
return $Call.ByID(3654471460);
|
||||
return $Call.ByID(1673632540);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} gameDir
|
||||
* @param {string} fileName
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function ReadConfigFile(gameDir, fileName) {
|
||||
return $Call.ByID(3834168665, gameDir, fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +91,16 @@ export function PickFolder() {
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function RemoveFile(path) {
|
||||
return $Call.ByID(3206735043, path);
|
||||
return $Call.ByID(2698409755, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} gamePath
|
||||
* @param {string} gameDir
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function SaveGameSelection(gamePath, gameDir) {
|
||||
return $Call.ByID(1414185756, gamePath, gameDir);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +108,7 @@ export function RemoveFile(path) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function StartApp(path) {
|
||||
return $Call.ByID(1267568402, path);
|
||||
return $Call.ByID(2875051690, path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,5 +116,15 @@ export function StartApp(path) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function StartWithConsole(path) {
|
||||
return $Call.ByID(3249271428, path);
|
||||
return $Call.ByID(3393986364, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} gameDir
|
||||
* @param {string} fileName
|
||||
* @param {string} content
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function WriteConfigFile(gameDir, fileName, content) {
|
||||
return $Call.ByID(1143842060, gameDir, fileName, content);
|
||||
}
|
||||
@@ -6,12 +6,20 @@
|
||||
// @ts-ignore: Unused imports
|
||||
import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime";
|
||||
|
||||
/**
|
||||
* @param {string} branch
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function BuildAndUpdateFromSource(branch) {
|
||||
return $Call.ByID(4215502398, branch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} version
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function DownloadProxyProgress(version) {
|
||||
return $Call.ByID(3559275334, version);
|
||||
return $Call.ByID(681315470, version);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -19,35 +27,35 @@ export function DownloadProxyProgress(version) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function DownloadServerProgress(version) {
|
||||
return $Call.ByID(1954767259, version);
|
||||
return $Call.ByID(1818966979, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<[boolean, string, string]>}
|
||||
*/
|
||||
export function GetLatestLauncherVersion() {
|
||||
return $Call.ByID(262637602);
|
||||
return $Call.ByID(977883722);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<[boolean, string, string]>}
|
||||
*/
|
||||
export function GetLatestProxyVersion() {
|
||||
return $Call.ByID(289488362);
|
||||
return $Call.ByID(2666043362);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<[boolean, string, string]>}
|
||||
*/
|
||||
export function GetLatestServerVersion() {
|
||||
return $Call.ByID(2918980975);
|
||||
return $Call.ByID(1731469511);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function UnzipServer() {
|
||||
return $Call.ByID(1126363284);
|
||||
return $Call.ByID(2625719532);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,5 +63,5 @@ export function UnzipServer() {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function UpdateLauncherProgress(version) {
|
||||
return $Call.ByID(97272861, version);
|
||||
return $Call.ByID(1270188021, version);
|
||||
}
|
||||
@@ -11,7 +11,16 @@ import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Cr
|
||||
* @returns {$CancellablePromise<[boolean, string, string, string]>}
|
||||
*/
|
||||
export function GetLanguage(path) {
|
||||
return $Call.ByID(3574191687, path);
|
||||
return $Call.ByID(2603098415, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} gameRoot
|
||||
* @param {string} packageRoot
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function InstallThaiPatch(gameRoot, packageRoot) {
|
||||
return $Call.ByID(1436799318, gameRoot, packageRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,5 +30,5 @@ export function GetLanguage(path) {
|
||||
* @returns {$CancellablePromise<[boolean, string]>}
|
||||
*/
|
||||
export function SetLanguage(path, text, voice) {
|
||||
return $Call.ByID(2768939795, path, text, voice);
|
||||
return $Call.ByID(1811821051, path, text, voice);
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -87,7 +89,72 @@ func (g *GitService) UpdateLauncherProgress(version string) (bool, string) {
|
||||
}
|
||||
}
|
||||
|
||||
return false, "could not locate valid launcher update package"
|
||||
// Mode 3: Build from source inside a temporary workspace, replace binary, and delete temp
|
||||
return g.BuildAndUpdateFromSource(constant.LauncherBranch)
|
||||
}
|
||||
|
||||
func (g *GitService) BuildAndUpdateFromSource(branch string) (bool, string) {
|
||||
if branch == "" {
|
||||
branch = constant.LauncherBranch
|
||||
}
|
||||
|
||||
gitExe, err := ensureGit()
|
||||
if err != nil {
|
||||
return false, fmt.Sprintf("git is required for source update: %v", err)
|
||||
}
|
||||
|
||||
// 1. Create clean temporary directory
|
||||
tempDir, err := os.MkdirTemp("", "g-launcher-build-*")
|
||||
if err != nil {
|
||||
return false, fmt.Sprintf("create temp build directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir) // Guarantee temporary directory is completely deleted
|
||||
|
||||
// 2. Clone repository into temp directory
|
||||
cloneCmd := exec.Command(gitExe, "clone", "--depth", "1", "--branch", branch, constant.LauncherRepoURL, tempDir)
|
||||
cloneCmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0")
|
||||
if out, err := cloneCmd.CombinedOutput(); err != nil {
|
||||
return false, fmt.Sprintf("clone repository to temp: %v (%s)", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
// 3. Build frontend inside temp
|
||||
frontendDir := filepath.Join(tempDir, "frontend")
|
||||
npmInstall := exec.Command("npm", "install", "--no-audit", "--no-fund")
|
||||
npmInstall.Dir = frontendDir
|
||||
if out, err := npmInstall.CombinedOutput(); err != nil {
|
||||
return false, fmt.Sprintf("npm install in temp: %v (%s)", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
npmBuild := exec.Command("npm", "run", "build")
|
||||
npmBuild.Dir = frontendDir
|
||||
if out, err := npmBuild.CombinedOutput(); err != nil {
|
||||
return false, fmt.Sprintf("npm run build in temp: %v (%s)", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
// 4. Build Go binary inside temp
|
||||
builtExePath := filepath.Join(tempDir, "bin", "G-Launcher.exe")
|
||||
if err := os.MkdirAll(filepath.Dir(builtExePath), 0755); err != nil {
|
||||
return false, fmt.Sprintf("create temp bin directory: %v", err)
|
||||
}
|
||||
|
||||
goBuild := exec.Command("go", "build", "-tags", "production", "-trimpath", "-buildvcs=false", "-ldflags=-w -s -H windowsgui", "-o", builtExePath, ".")
|
||||
goBuild.Dir = tempDir
|
||||
if out, err := goBuild.CombinedOutput(); err != nil {
|
||||
return false, fmt.Sprintf("go build in temp: %v (%s)", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
// 5. Replace current running binary with newly built binary
|
||||
builtFile, err := os.Open(builtExePath)
|
||||
if err != nil {
|
||||
return false, fmt.Sprintf("open built launcher in temp: %v", err)
|
||||
}
|
||||
defer builtFile.Close()
|
||||
|
||||
if err := selfupdate.Apply(builtFile, selfupdate.Options{}); err != nil {
|
||||
return false, fmt.Sprintf("apply launcher update: %v", err)
|
||||
}
|
||||
|
||||
return true, ""
|
||||
}
|
||||
|
||||
func (g *GitService) applyManifestUpdate(manifest launcherManifest) (bool, string) {
|
||||
|
||||
@@ -5,6 +5,9 @@ const ServerGitUrl = "https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/Firefl
|
||||
const LauncherGitUrl = "https://gaytea.cod-algieba.ts.net/api/v1/repos/GaCy/G-Launcher/releases"
|
||||
const LauncherManifestURL = "https://gaytea.cod-algieba.ts.net/GaCy/G-Launcher/releases/download/latest/latest.json"
|
||||
const LauncherDownloadURL = "https://gaytea.cod-algieba.ts.net/GaCy/G-Launcher/releases/download/latest/G-Launcher.exe"
|
||||
const LauncherRepoURL = "https://gaytea.cod-algieba.ts.net/GaCy/G-Launcher.git"
|
||||
const LauncherBranch = "Dev"
|
||||
const LauncherBuildTempDir = "temp/updater_build"
|
||||
|
||||
const ServerStorageUrl = "./server"
|
||||
const ProxyStorageUrl = "./proxy"
|
||||
|
||||
+115
-63
@@ -1,5 +1,6 @@
|
||||
# ==============================================================================
|
||||
# G-Launcher Auto-Updater & Environment Bootstrap Script
|
||||
# Architecture: Download to Temp -> Build in Temp -> Replace Old -> Delete Temp
|
||||
# ==============================================================================
|
||||
param(
|
||||
[string]$Branch = "Dev",
|
||||
@@ -13,7 +14,11 @@ $ErrorActionPreference = "Stop"
|
||||
$rootDir = Split-Path -Parent $PSScriptRoot
|
||||
Set-Location $rootDir
|
||||
$toolsDir = Join-Path $rootDir "tools"
|
||||
$binDir = Join-Path $rootDir "bin"
|
||||
$targetExe = Join-Path $binDir "G-Launcher.exe"
|
||||
|
||||
if (!(Test-Path $toolsDir)) { New-Item -ItemType Directory -Path $toolsDir -Force | Out-Null }
|
||||
if (!(Test-Path $binDir)) { New-Item -ItemType Directory -Path $binDir -Force | Out-Null }
|
||||
|
||||
Write-Host "==========================================================" -ForegroundColor Cyan
|
||||
Write-Host " G-Launcher: Auto-Update & Local Build System" -ForegroundColor Cyan
|
||||
@@ -123,79 +128,126 @@ if (-not $wailsCmd) {
|
||||
Write-Host " -> Wails v3 CLI is ready" -ForegroundColor Gray
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# 5. Git Pull latest code
|
||||
# 5. Download to Temp -> Build in Temp -> Replace Old -> Delete Temp
|
||||
# ------------------------------------------------------------------------------
|
||||
Write-Host "[5/6] Syncing latest code from branch '$Branch'..." -ForegroundColor White
|
||||
$env:GIT_TERMINAL_PROMPT = "0"
|
||||
if (Test-Path (Join-Path $rootDir ".git")) {
|
||||
try {
|
||||
& git fetch origin $Branch --progress
|
||||
& git checkout $Branch
|
||||
$pullOutput = & git pull origin $Branch
|
||||
Write-Host " -> $pullOutput" -ForegroundColor Gray
|
||||
} catch {
|
||||
Write-Host "Warning: Could not pull latest changes (offline or local modifications). Proceeding with current local code." -ForegroundColor DarkYellow
|
||||
}
|
||||
} else {
|
||||
Write-Host ">> Cloning repository from $RepoUrl..." -ForegroundColor Yellow
|
||||
& git clone --branch $Branch $RepoUrl .
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# 6. Build Project (Frontend + Go Backend)
|
||||
# ------------------------------------------------------------------------------
|
||||
Write-Host "[6/6] Compiling G-Launcher..." -ForegroundColor White
|
||||
|
||||
Write-Host " [6.1] Installing Frontend dependencies..." -ForegroundColor Gray
|
||||
& npm --prefix frontend install --no-audit --no-fund
|
||||
|
||||
Write-Host " [6.2] Building React 19 Frontend..." -ForegroundColor Gray
|
||||
& npm --prefix frontend run build
|
||||
|
||||
Write-Host " [6.3] Running go mod tidy..." -ForegroundColor Gray
|
||||
& go mod tidy
|
||||
|
||||
$binDir = Join-Path $rootDir "bin"
|
||||
if (!(Test-Path $binDir)) { New-Item -ItemType Directory -Path $binDir -Force | Out-Null }
|
||||
$outputExe = Join-Path $binDir "G-Launcher.exe"
|
||||
$sysoPath = Join-Path $rootDir "wails_windows_amd64.syso"
|
||||
$tempBuildDir = Join-Path $rootDir "temp\build_workspace"
|
||||
$tempExe = Join-Path $tempBuildDir "bin\G-Launcher.exe"
|
||||
|
||||
try {
|
||||
Write-Host " [6.4] Generating Windows Manifest & Syso..." -ForegroundColor Gray
|
||||
if (Get-Command wails3 -ErrorAction SilentlyContinue) {
|
||||
& wails3 generate syso -arch amd64 -icon build/windows/icon.ico -manifest build/windows/wails.exe.manifest -info build/windows/info.json -out $sysoPath
|
||||
Write-Host "[5/6] Preparing clean temporary workspace..." -ForegroundColor White
|
||||
if (Test-Path $tempBuildDir) {
|
||||
Remove-Item -Path $tempBuildDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Warning: Syso generation skipped, building executable without embedded syso." -ForegroundColor DarkYellow
|
||||
}
|
||||
New-Item -ItemType Directory -Path $tempBuildDir -Force | Out-Null
|
||||
|
||||
Write-Host " [6.5] Compiling Go backend binary..." -ForegroundColor Gray
|
||||
& go build -tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui" -o $outputExe .
|
||||
Write-Host ">> Downloading latest source code from branch '$Branch' into temp..." -ForegroundColor Yellow
|
||||
$env:GIT_TERMINAL_PROMPT = "0"
|
||||
$cloned = $false
|
||||
try {
|
||||
& git clone --depth 1 --branch $Branch $RepoUrl $tempBuildDir
|
||||
$cloned = $true
|
||||
} catch {
|
||||
Write-Host "Warning: Remote clone failed. Attempting local repository clone..." -ForegroundColor DarkYellow
|
||||
}
|
||||
|
||||
if (Test-Path $sysoPath) {
|
||||
Remove-Item -Path $sysoPath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
if (-not $cloned -and (Test-Path (Join-Path $rootDir ".git"))) {
|
||||
& git clone --depth 1 --branch $Branch $rootDir $tempBuildDir
|
||||
$cloned = $true
|
||||
}
|
||||
|
||||
if ($LASTEXITCODE -ne 0 -or !(Test-Path $outputExe)) {
|
||||
if (-not $cloned) {
|
||||
throw "Failed to download repository source into temporary directory!"
|
||||
}
|
||||
|
||||
Write-Host "[6/6] Building new G-Launcher in temporary workspace..." -ForegroundColor White
|
||||
Push-Location $tempBuildDir
|
||||
|
||||
Write-Host " [6.1] Installing Frontend dependencies in temp..." -ForegroundColor Gray
|
||||
& npm --prefix frontend install --no-audit --no-fund
|
||||
|
||||
Write-Host " [6.2] Compiling React 19 Frontend in temp..." -ForegroundColor Gray
|
||||
& npm --prefix frontend run build
|
||||
|
||||
Write-Host " [6.3] Running go mod tidy in temp..." -ForegroundColor Gray
|
||||
& go mod tidy
|
||||
|
||||
$tempBinDir = Join-Path $tempBuildDir "bin"
|
||||
if (!(Test-Path $tempBinDir)) { New-Item -ItemType Directory -Path $tempBinDir -Force | Out-Null }
|
||||
$sysoPath = Join-Path $tempBuildDir "wails_windows_amd64.syso"
|
||||
|
||||
try {
|
||||
Write-Host " [6.4] Generating Windows Manifest & Syso in temp..." -ForegroundColor Gray
|
||||
if (Get-Command wails3 -ErrorAction SilentlyContinue) {
|
||||
& wails3 generate syso -arch amd64 -icon build/windows/icon.ico -manifest build/windows/wails.exe.manifest -info build/windows/info.json -out $sysoPath
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Warning: Syso generation skipped, building executable without embedded syso." -ForegroundColor DarkYellow
|
||||
}
|
||||
|
||||
Write-Host " [6.5] Compiling Go backend binary in temp..." -ForegroundColor Gray
|
||||
& go build -tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui" -o $tempExe .
|
||||
|
||||
if (Test-Path $sysoPath) {
|
||||
Remove-Item -Path $sysoPath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
if ($LASTEXITCODE -ne 0 -or !(Test-Path $tempExe)) {
|
||||
throw "Compilation inside temporary workspace failed!"
|
||||
}
|
||||
|
||||
$upxCmd = Get-Command upx -ErrorAction SilentlyContinue
|
||||
if ($upxCmd) {
|
||||
Write-Host " [6.6] Compressing binary with UPX in temp..." -ForegroundColor Gray
|
||||
& upx --best --lzma $tempExe
|
||||
}
|
||||
|
||||
Pop-Location
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Replace old executable with newly built binary (with rollback protection)
|
||||
# --------------------------------------------------------------------------
|
||||
Write-Host ">> Replacing old launcher binary with new build..." -ForegroundColor Cyan
|
||||
$backupExe = "$targetExe.old"
|
||||
|
||||
if (Test-Path $targetExe) {
|
||||
if (Test-Path $backupExe) {
|
||||
Remove-Item -Path $backupExe -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
Rename-Item -LiteralPath $targetExe -NewName (Split-Path -Leaf $backupExe) -Force
|
||||
try {
|
||||
Move-Item -LiteralPath $tempExe -Destination $targetExe -Force
|
||||
Remove-Item -LiteralPath $backupExe -Force -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
Write-Host "Error during replacement! Rolling back..." -ForegroundColor Red
|
||||
if (Test-Path $backupExe) {
|
||||
Move-Item -LiteralPath $backupExe -Destination $targetExe -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
throw "Replacement failed and was rolled back: $_"
|
||||
}
|
||||
} else {
|
||||
Move-Item -LiteralPath $tempExe -Destination $targetExe -Force
|
||||
}
|
||||
|
||||
$exeSize = (Get-Item $targetExe).Length / 1MB
|
||||
Write-Host ""
|
||||
Write-Host "==========================================================" -ForegroundColor Green
|
||||
Write-Host ("Build & Update Successful! File: bin/G-Launcher.exe ({0:N2} MB)" -f $exeSize) -ForegroundColor Green
|
||||
Write-Host "==========================================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "[ERROR] Compilation failed!" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
$upxCmd = Get-Command upx -ErrorAction SilentlyContinue
|
||||
if ($upxCmd) {
|
||||
Write-Host " [6.6] Compressing binary with UPX..." -ForegroundColor Gray
|
||||
& upx --best --lzma $outputExe
|
||||
} finally {
|
||||
# --------------------------------------------------------------------------
|
||||
# Always delete temporary workspace
|
||||
# --------------------------------------------------------------------------
|
||||
Set-Location $rootDir
|
||||
if (Test-Path $tempBuildDir) {
|
||||
Write-Host "🧹 Cleaning up and deleting temporary workspace ($tempBuildDir)..." -ForegroundColor Yellow
|
||||
Remove-Item -LiteralPath $tempBuildDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Write-Host "[OK] Temporary workspace deleted!" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
$exeSize = (Get-Item $outputExe).Length / 1MB
|
||||
Write-Host ""
|
||||
Write-Host "==========================================================" -ForegroundColor Green
|
||||
Write-Host ("Build Successful! Output: bin/G-Launcher.exe ({0:N2} MB)" -f $exeSize) -ForegroundColor Green
|
||||
Write-Host "==========================================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
if (-not $NoLaunch) {
|
||||
Write-Host "Launching G-Launcher..." -ForegroundColor Cyan
|
||||
Start-Process -FilePath $outputExe
|
||||
Write-Host "🎮 Launching G-Launcher..." -ForegroundColor Cyan
|
||||
Start-Process -FilePath $targetExe
|
||||
}
|
||||
Reference in new issue
Block a user