8.0 KiB
8.0 KiB
🔄 สัญญาทางเทคนิค: วงจรชีวิตของระบบอัปเดต (Updater Temp Lifecycle Contract)
เอกสารนี้ระบุข้อตกลงและสัญญาทางเทคนิค (Contract) สำหรับระบบอัปเดตและบิลด์ในเครื่องของ G-Launcher ซึ่งครอบคลุมทั้งสคริปต์ PowerShell (scripts/bootstrap.ps1) และบริการ Go Backend (internal/git-service/launcher.go)
1. วัตถุประสงค์และข้อจำกัดของระบบปฏิบัติการ (Operating System Constraints)
ปัญหาข้อจำกัดของ Windows:
- Windows Executable Locking: เมื่อโปรเซส
.exeกำลังทำงานอยู่ ระบบปฏิบัติการจะเปิดแฮนเดิลไฟล์ด้วยการล็อกแบบแชร์การอ่าน (FILE_SHARE_READ) แต่ไม่อนุญาตให้เขียน (GENERIC_WRITE) หรือลบทิ้ง (DELETE) โดยตรง - ข้อยกเว้นการเปลี่ยนชื่อ (Rename Privilege): บน Windows อนุญาตให้ เปลี่ยนชื่อ (Rename/Move) ไฟล์ executable ที่กำลังทำงานอยู่ได้ ตราบใดที่ยังอยู่บนโวลุม (Volume/Drive) เดียวกัน
- การหลีกเลี่ยง Build In-Place: การรัน
git pullหรือgo buildทับโฟลเดอร์หลักของ Launcher ขณะที่ตัว Launcher รันอยู่ จะทำให้เกิด ExceptionAccess is deniedทันที และอาจทำให้โฟลเดอร์ซอร์สโค้ดค้างอยู่ในสถานะไม่สมบูรณ์
2. ขั้นตอนทั้ง 4 ของวงจรชีวิต (The 4 Lifecycle Phases)
Phase 1: การจัดเตรียมพื้นที่ชั่วคราวและการดาวน์โหลด (Download to Temp)
- PowerShell:
- โฟลเดอร์เป้าหมาย:
$tempBuildDir = Join-Path $rootDir "temp\build_workspace" - หากมีโฟลเดอร์ตกค้างจากรอบก่อน ให้สั่งลบทิ้งก่อนสร้างใหม่เสมอ
- สั่ง
git clone --depth 1 --branch Dev https://gaytea.cod-algieba.ts.net/GaCy/G-Launcher.git $tempBuildDir - หากการ Clone ผ่านเน็ตเวิร์กล้มเหลว (เช่น ทำงานแบบออฟไลน์) สคริปต์จะสลับไป Clone จากโฟลเดอร์ท้องถิ่น (
$rootDir) เข้าสู่$tempBuildDirแทน
- โฟลเดอร์เป้าหมาย:
- Go Backend:
- ใช้
tempDir, err := os.MkdirTemp("", "g-launcher-build-*") - สั่งงาน Git ผ่านฟังก์ชัน
ensureGit()เพื่อรับประกันว่ามี Portable MinGit ทำงานได้โดยไม่ต้องพึ่งสิทธิ์ Administrator
- ใช้
Phase 2: การคอมไพล์แบบแยกส่วนในโฟลเดอร์ชั่วคราว (Isolated Build)
- สวิตช์ Working Directory เข้าสู่โฟลเดอร์ชั่วคราว (
Push-Location $tempBuildDirหรือcmd.Dir = tempDir) - ลำดับการคอมไพล์:
npm --prefix frontend install --no-audit --no-fund(ติดตั้ง dependencies ของ React 19)npm --prefix frontend run build(คอมไพล์ assets ผ่าน Vite 8 ได้ผลลัพธ์ลงfrontend/dist/)go mod tidy(จัดระเบียบ Go modules)wails3 generate syso(สร้าง Windows PE Resource, Manifest, DPI awareness, และ Icon)go build -tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui" -o bin/G-Launcher.exe .
- ตรวจสอบว่าไฟล์ไบนารีผลลัพธ์ถูกสร้างขึ้นจริง และมีขนาดมากกว่า 0 ไบต์
- สลับกลับสู่ Working Directory เดิม (
Pop-Location) ก่อนเริ่มขั้นตอนถัดไป
Phase 3: การสลับไฟล์ไบนารีอย่างปลอดภัยและการ Rollback (Atomic Swap & Safe Rollback)
- หากไฟล์เป้าหมาย
bin/G-Launcher.exeมีอยู่เดิม:- เปลี่ยนชื่อไฟล์เดิมเป็น
bin/G-Launcher.exe.old - ย้ายไฟล์ใหม่จากโฟลเดอร์ Temp มาวางที่
bin/G-Launcher.exe - หากการย้ายไฟล์ล้มเหลว (เกิด Exception):
- Rollback ทันที: ย้าย
bin/G-Launcher.exe.oldกลับมาเป็นbin/G-Launcher.exeเพื่อให้ผู้ใช้ยังสามารถเปิดโปรแกรมเดิมได้ - แจ้งข้อผิดพลาดและยุติการทำงาน
- Rollback ทันที: ย้าย
- หากการย้ายไฟล์สำเร็จ:
- ลบไฟล์
bin/G-Launcher.exe.old(หากโปรแกรมเดิมกำลังรันอยู่และยังลบไม่ได้ ไฟล์นี้จะถูกเพิกเฉยและรอการลบในรอบถัดไป)
- ลบไฟล์
- เปลี่ยนชื่อไฟล์เดิมเป็น
- ในฝั่ง Go Backend ใช้ไลบรารี
github.com/minio/selfupdate:- ฟังก์ชัน
selfupdate.Apply(newBinaryReader, selfupdate.Options{})ดำเนินการ Rename & Swap แบบ Atomic ในระดับ Native Windows API
- ฟังก์ชัน
Phase 4: การทำลายโฟลเดอร์ชั่วคราว (Guaranteed Temp Purge)
- PowerShell:
- ครอบกระบวนการทั้งหมดด้วยบล็อก
try { ... } finally { ... } - ในบล็อก
finally:Set-Location $rootDir if (Test-Path $tempBuildDir) { Remove-Item -LiteralPath $tempBuildDir -Recurse -Force -ErrorAction SilentlyContinue } - การันตีว่าโฟลเดอร์ Temp จะถูกลบออก 100% เสมอ ไม่ว่าการบิลด์จะสำเร็จหรือเกิดข้อผิดพลาด
- ครอบกระบวนการทั้งหมดด้วยบล็อก
- Go Backend:
- ใช้คำสั่ง
defer os.RemoveAll(tempDir)ทันทีหลังสร้างos.MkdirTempสำเร็จ
- ใช้คำสั่ง
3. หลักฐานการตรวจสอบจริง (Empirical Verification Log)
ผลการทดสอบสคริปต์จริงในสภาพแวดล้อม Windows 64-bit (Task ID: task-607):
- โฟลเดอร์ชั่วคราว:
C:\Users\Phitchayut\Desktop\G Launcher\temp\build_workspace - เวลาในการดาวน์โหลดและแตกแพ็กเกจ Frontend: 21 วินาที
- เวลาในการคอมไพล์ Vite Frontend: 751 มิลลิวินาที
- ขนาดไฟล์ Executable ผลลัพธ์: 28,677,632 ไบต์ (27.35 MB)
- ผลการตรวจสอบการล้างขยะ: คำสั่ง
Test-Path .\temp\build_workspaceคืนค่าFalse(โฟลเดอร์ชั่วคราวถูกลบทิ้งหมดจด ไร้ขยะตกค้าง)