build: 更新版本号并重构发布脚本

-重构 release-linux.ps1 脚本,添加版本号读取和输出路径定义
- 新增 release-windows.ps1 脚本,实现 Windows 版本的构建和打包
- 添加 dotenv.ps1工具脚本,用于统一解析 .env 文件
This commit is contained in:
Luke 2025-08-25 13:17:16 +08:00
parent a16f0ac059
commit b2c0b986c4
4 changed files with 204 additions and 5 deletions

2
.env
View File

@ -1,2 +1,2 @@
# Auto-generated by build\tools\generate-dotenv.ps1
SNOW_VERSION=0.7.0
SNOW_VERSION=0.8.0

View File

@ -1,11 +1,17 @@
# run-linux-snow-export.ps1
# Build and package linux-snow-export, version read from SNOW_VERSION in .env
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# Import shared dotenv parser function
. "$PSScriptRoot\tools\dotenv.ps1"
Write-Host "Step 0: Generate .env..."
try {
& "$PSScriptRoot\tools\generate-dotenv.ps1" -ErrorAction Stop
}
catch {
Write-Error "Failed to generate .env: $($_.Exception.Message)"
} catch {
Write-Error "Failed to generate .env: $( $_.Exception.Message )"
exit 1
}
@ -23,4 +29,27 @@ if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
Write-Host "All steps completed successfully!"
# ===== Step 3: Read version from .env =====
$projectRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
$dotenvPath = Join-Path $projectRoot ".env"
if (-not (Test-Path -LiteralPath $dotenvPath)) {
Write-Error ".env not found at: $dotenvPath"
exit 1
}
$version = Read-DotEnvValue -FilePath $dotenvPath -Key 'SNOW_VERSION'
if (-not $version) {
Write-Error "SNOW_VERSION not found in .env"
exit 1
}
# ===== Step 4: Define output paths =====
$targetDir = Join-Path $projectRoot "target\release"
$outDir = Join-Path $targetDir "Snow-v$version-linux-x64"
$tgzPath = Join-Path $targetDir "Snow-v$version-linux-x64.tgz"
Write-Host ">>> Package ready!" -ForegroundColor Green
Write-Host "Version : $version"
Write-Host "Output Dir : $outDir"
Write-Host "Tgz File : $tgzPath"

117
build/release-windows.ps1 Normal file
View File

@ -0,0 +1,117 @@
# release-windows.ps1
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
Set-StrictMode -Version Latest
# Import shared dotenv parser function
. "$PSScriptRoot\tools\dotenv.ps1"
# ===== Utility Functions =====
function Find-PomUpwards([string]$startDir) {
$dir = Resolve-Path $startDir
while ($true) {
$pom = Join-Path $dir "pom.xml"
if (Test-Path $pom) { return $pom }
$parent = Split-Path $dir -Parent
if ($parent -eq $dir -or [string]::IsNullOrEmpty($parent)) { return $null }
$dir = $parent
}
}
# ===== Step 0: Generate .env =====
Write-Host "Step 0: Generate .env..."
try {
& "$PSScriptRoot\tools\generate-dotenv.ps1" -ErrorAction Stop
} catch {
Write-Error "Failed to generate .env: $($_.Exception.Message)"
exit 1
}
# ===== Step 1: Locate project root & build =====
Write-Host "Step 1: Locate project root and build..."
$pom = Find-PomUpwards -startDir $PSScriptRoot
if (-not $pom) {
Write-Error "pom.xml not found. Please run this script within the project."
exit 1
}
$projectRoot = Split-Path $pom -Parent
Push-Location $projectRoot
try {
Write-Host "→ Running: mvn clean package"
mvn clean package
if ($LASTEXITCODE -ne 0) {
Write-Error "Maven build failed, exiting script."
exit $LASTEXITCODE
}
# ===== Step 2: Read SNOW_VERSION =====
Write-Host "Step 2: Read SNOW_VERSION from .env..."
$dotenvPath = Join-Path $projectRoot ".env"
$snowVersion = Read-DotEnvValue -FilePath $dotenvPath -Key "SNOW_VERSION"
if (-not $snowVersion) {
Write-Host "SNOW_VERSION not found in .env, using placeholder 0.0.0." -ForegroundColor Yellow
$snowVersion = "0.0.0"
}
Write-Host "SNOW_VERSION = $snowVersion"
# ===== Step 3: Prepare release directory structure =====
Write-Host "Step 3: Prepare release directory structure..."
$targetDir = Join-Path $projectRoot "target"
$exePath = Join-Path $targetDir "Snow.exe"
if (-not (Test-Path $exePath)) {
Write-Error "Expected build artifact not found: $exePath"
exit 1
}
$verName = "Snow-v${snowVersion}-windows-x64"
$releaseRoot = Join-Path $targetDir "release"
$outDir = Join-Path $releaseRoot $verName
$binDir = Join-Path $outDir "bin"
$libDir = Join-Path $outDir "lib"
# Clean old directory
if (Test-Path $outDir) {
Write-Host "→ Cleaning previous output directory..."
Remove-Item $outDir -Recurse -Force
}
New-Item -ItemType Directory -Force -Path $binDir | Out-Null
Copy-Item -Path $exePath -Destination (Join-Path $binDir "Snow.exe") -Force
Write-Host ">>> Collected Snow.exe"
# Optional lib
$projectLib = Join-Path $projectRoot "lib"
if (Test-Path $projectLib) {
New-Item -ItemType Directory -Force -Path $libDir | Out-Null
Copy-Item -Path (Join-Path $projectLib "*") -Destination $libDir -Recurse -Force
Write-Host ">>> Copied lib directory"
} else {
Write-Host ">>> lib directory not found, skipping." -ForegroundColor Yellow
}
# ===== Step 4: Create zip =====
Write-Host "Step 4: Create release zip..."
New-Item -ItemType Directory -Force -Path $releaseRoot | Out-Null
$zipPath = Join-Path $releaseRoot ("{0}.zip" -f $verName)
if (Test-Path $zipPath) {
Write-Host "→ Removing existing zip: $zipPath"
Remove-Item $zipPath -Force
}
try {
Compress-Archive -Path $outDir -DestinationPath $zipPath -Force
} catch {
Write-Error "Failed to create zip: $($_.Exception.Message)"
exit 1
}
Write-Host ">>> Package ready!" -ForegroundColor Green
Write-Host "Version : $snowVersion"
Write-Host "Output Dir : $outDir"
Write-Host "Zip File : $zipPath"
}
finally {
Pop-Location
}

53
build/tools/dotenv.ps1 Normal file
View File

@ -0,0 +1,53 @@
# tools/dotenv.ps1
# Unified .env reader function:
# - Supports `KEY=VAL` and `export KEY=VAL`
# - Skips blank lines and comments
# - Handles quoted values (single or double quotes)
# - Allows inline comments at the end of a line (space + #)
# - If the same KEY is defined multiple times, the last one takes precedence
Set-StrictMode -Version Latest
function Read-DotEnvValue {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$FilePath,
[Parameter(Mandatory=$true)][string]$Key
)
if (-not (Test-Path -LiteralPath $FilePath)) { return $null }
# Match the target key (escaped), allowing optional "export" prefix
$pattern = '^(?:\s*export\s+)?(?<k>' + [regex]::Escape($Key) + ')\s*=\s*(?<v>.*)$'
$value = $null
# Read line by line for large file compatibility
Get-Content -LiteralPath $FilePath | ForEach-Object {
$line = $_
# Skip blank lines and full-line comments
if ($line -match '^\s*$') { return }
if ($line -match '^\s*#') { return }
if ($line -match $pattern) {
$v = $matches['v']
# Remove surrounding quotes if present
$trimmed = $v.Trim()
if ($trimmed -match '^\s*"(.*)"\s*$') {
$v = $matches[1]
} elseif ($trimmed -match "^\s*'(.*)'\s*$") {
$v = $matches[1]
} else {
# Strip inline comments (space + # …), ignoring escaped \#
if ($v -match '^(.*?)(?<!\\)\s+#.*$') {
$v = $matches[1]
}
}
$value = $v.Trim()
}
}
return $value
}