mirror of https://github.com/ospab/ostp.git
refactor: professionalize all scripts and CI workflow
build.ps1: - Added mandatory cargo check pre-flight that blocks releases on errors - Added --Check flag for check-only mode (no build, no release) - Reverts version bump if check fails - Professionalized all output (removed informal language) - Cleaner output structure with consistent [ok], [warn], [error] tags install.ps1 / install.sh: - Professionalized all prompts and messages - Removed informal phrasing - Consistent formatting test_linux.sh: - Updated all log string matchers to match professionalized output: 'Connection established' (was 'Bridge connection established') 'Starting server' (was 'Starting in SERVER mode') 'Starting client' (was 'Starting in CLIENT mode') RTT regex updated for new format release.yml: - Added cargo check pre-flight step before native compilation
This commit is contained in:
parent
aa9a93fcbf
commit
e36d743ad5
|
|
@ -137,6 +137,13 @@ jobs:
|
||||||
if: ${{ matrix.os == 'ubuntu-latest' && !matrix.use_cross }}
|
if: ${{ matrix.os == 'ubuntu-latest' && !matrix.use_cross }}
|
||||||
run: sudo apt-get update && sudo apt-get install -y musl-tools
|
run: sudo apt-get update && sudo apt-get install -y musl-tools
|
||||||
|
|
||||||
|
- name: Pre-flight compilation check
|
||||||
|
if: ${{ !matrix.use_cross }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cargo check --target ${{ matrix.target }} --bin ostp 2>&1
|
||||||
|
echo "Pre-flight check passed."
|
||||||
|
|
||||||
- name: Execute Standard Native Compilation (Windows)
|
- name: Execute Standard Native Compilation (Windows)
|
||||||
if: ${{ !matrix.use_cross && matrix.os == 'windows-latest' }}
|
if: ${{ !matrix.use_cross && matrix.os == 'windows-latest' }}
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
|
|
@ -745,7 +745,7 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp"
|
name = "ostp"
|
||||||
version = "0.1.60"
|
version = "0.1.61"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|
@ -762,7 +762,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-client"
|
name = "ostp-client"
|
||||||
version = "0.1.60"
|
version = "0.1.61"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|
@ -780,7 +780,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-core"
|
name = "ostp-core"
|
||||||
version = "0.1.60"
|
version = "0.1.61"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|
@ -813,7 +813,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-server"
|
name = "ostp-server"
|
||||||
version = "0.1.60"
|
version = "0.1.61"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|
@ -828,7 +828,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-tun-helper"
|
name = "ostp-tun-helper"
|
||||||
version = "0.1.60"
|
version = "0.1.61"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,23 @@
|
||||||
# OSTP High-Performance Cross-Platform Build & Release Pipeline
|
# OSTP Build & Release Pipeline
|
||||||
|
# Usage:
|
||||||
|
# .\scripts\build.ps1 Build locally + trigger CI/CD
|
||||||
|
# .\scripts\build.ps1 -TriggerOnly Skip local builds, trigger CI/CD only
|
||||||
|
# .\scripts\build.ps1 -Check Run cargo check only (no build, no release)
|
||||||
|
|
||||||
param(
|
param(
|
||||||
[switch]$Flatten, # Consolidate raw uncompressed binaries with arch suffixes under dist/release/
|
[switch]$Flatten,
|
||||||
[switch]$TriggerOnly # Bypasses all local builds to instantly execute global cloud CI/CD tag injection
|
[switch]$TriggerOnly,
|
||||||
|
[switch]$Check
|
||||||
)
|
)
|
||||||
|
|
||||||
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
||||||
Push-Location $ProjectRoot
|
Push-Location $ProjectRoot
|
||||||
|
|
||||||
Write-Output "Synchronizing latest workspace source code from origin master..."
|
# --- Sync ---
|
||||||
# Leverage autostash and rebase to pull cleanly even with uncommitted local edits
|
Write-Output "Synchronizing with origin master..."
|
||||||
& git pull origin master --rebase --autostash | Out-Null
|
& git pull origin master --rebase --autostash | Out-Null
|
||||||
|
|
||||||
Write-Output "Starting Universal OSTP Build & Release Pipeline in $ProjectRoot"
|
# --- Version bump ---
|
||||||
|
|
||||||
# Unblock binaries by terminating any existing active instances
|
|
||||||
Stop-Process -Name ostp -ErrorAction SilentlyContinue | Out-Null
|
|
||||||
|
|
||||||
# 1. Read and automatically bump version inside Cargo.toml PRIOR to compilation
|
|
||||||
$CargoToml = Join-Path $ProjectRoot "Cargo.toml"
|
$CargoToml = Join-Path $ProjectRoot "Cargo.toml"
|
||||||
$Version = "0.1.0"
|
$Version = "0.1.0"
|
||||||
if (Test-Path $CargoToml) {
|
if (Test-Path $CargoToml) {
|
||||||
|
|
@ -30,195 +31,205 @@ if (Test-Path $CargoToml) {
|
||||||
$NewVersionStr = 'version = "' + $Version + '"'
|
$NewVersionStr = 'version = "' + $Version + '"'
|
||||||
$NewContent = $Content -replace 'version\s*=\s*"\d+\.\d+\.\d+"', $NewVersionStr
|
$NewContent = $Content -replace 'version\s*=\s*"\d+\.\d+\.\d+"', $NewVersionStr
|
||||||
[System.IO.File]::WriteAllText($CargoToml, $NewContent)
|
[System.IO.File]::WriteAllText($CargoToml, $NewContent)
|
||||||
Write-Output "[OK] Bounded workspace package to target release version: v$Version"
|
Write-Output "[ok] Version: v$Version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$DistDir = Join-Path $ProjectRoot "dist"
|
# --- Pre-flight: cargo check ---
|
||||||
$StagingDir = Join-Path $DistDir "staging"
|
Write-Output ""
|
||||||
|
Write-Output "Running pre-flight cargo check..."
|
||||||
|
$checkOutput = & cargo check 2>&1 | Out-String
|
||||||
|
$checkErrors = $checkOutput | Select-String "^error\[" -CaseSensitive
|
||||||
|
|
||||||
# Wipe legacy artifacts to prepare a clean clean slate
|
if ($checkErrors) {
|
||||||
if (Test-Path $DistDir) { Remove-Item -Path $DistDir -Recurse -Force -ErrorAction SilentlyContinue }
|
Write-Output ""
|
||||||
New-Item -ItemType Directory -Force -Path $DistDir | Out-Null
|
Write-Output "[error] Compilation check failed. Fix errors before releasing:"
|
||||||
|
Write-Output $checkOutput
|
||||||
# Collection for dynamically mapping successful build archives
|
# Revert version bump
|
||||||
$ReleaseArchives = @()
|
[System.IO.File]::WriteAllText($CargoToml, $Content)
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# CONDITIONAL BUILD SUITE execution
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
if (-not $TriggerOnly) {
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# PHASE 1: WINDOWS COMPILATION MATRIX (Native Host)
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
$WindowsTargets = @(
|
|
||||||
@{ Target = "x86_64-pc-windows-msvc"; Arch = "x64"; BinaryName = "ostp.exe" }
|
|
||||||
)
|
|
||||||
|
|
||||||
Write-Output "========================================================="
|
|
||||||
Write-Output " PHASE 1: Compiling Windows Architectures"
|
|
||||||
Write-Output "========================================================="
|
|
||||||
$TempWinTargetDir = Join-Path $env:TEMP "ostp_target_win"
|
|
||||||
|
|
||||||
foreach ($item in $WindowsTargets) {
|
|
||||||
$target = $item.Target
|
|
||||||
$arch = $item.Arch
|
|
||||||
$bin = $item.BinaryName
|
|
||||||
|
|
||||||
Write-Output "--> Compiling target: Windows $arch [$target]..."
|
|
||||||
|
|
||||||
# Attempt setup of the rust toolchain for this architecture
|
|
||||||
& rustup target add $target 2>&1 | Out-Null
|
|
||||||
|
|
||||||
$env:CARGO_TARGET_DIR = $TempWinTargetDir
|
|
||||||
& cargo build --release --target $target --bin ostp
|
|
||||||
|
|
||||||
if ($LASTEXITCODE -eq 0) {
|
|
||||||
$compiledBin = Join-Path $TempWinTargetDir "$target\release\$bin"
|
|
||||||
if (Test-Path $compiledBin) {
|
|
||||||
$archiveName = "ostp-v$Version-windows-$arch.zip"
|
|
||||||
$targetStaging = Join-Path $StagingDir "windows-$arch"
|
|
||||||
New-Item -ItemType Directory -Force -Path $targetStaging | Out-Null
|
|
||||||
|
|
||||||
# Stage and package binary natively
|
|
||||||
Copy-Item -Path $compiledBin -Destination $targetStaging -Force
|
|
||||||
|
|
||||||
$archivePath = Join-Path $DistDir $archiveName
|
|
||||||
Compress-Archive -Path "$targetStaging\*" -DestinationPath $archivePath -Force
|
|
||||||
|
|
||||||
$ReleaseArchives += $archivePath
|
|
||||||
Write-Output "[OK] SUCCESSFULLY PACKAGED: $archiveName"
|
|
||||||
|
|
||||||
if ($Flatten) {
|
|
||||||
$RawReleaseDir = Join-Path $DistDir "release"
|
|
||||||
New-Item -ItemType Directory -Force -Path $RawReleaseDir | Out-Null
|
|
||||||
$FlatName = "ostp-windows-$arch.exe"
|
|
||||||
Copy-Item -Path $compiledBin -Destination (Join-Path $RawReleaseDir $FlatName) -Force
|
|
||||||
Write-Output " -> Flat copied: dist/release/$FlatName"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Write-Output "[WARN] FAILED compiling Windows $arch ($target). Missing local platform C++ toolchain components."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# Restore environment variables
|
|
||||||
Remove-Item Env:\CARGO_TARGET_DIR -ErrorAction SilentlyContinue | Out-Null
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# PHASE 2: LINUX CROSS-COMPILATION MATRIX (via WSL + rust-lld)
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
Write-Output "`n========================================================="
|
|
||||||
Write-Output " PHASE 2: Compiling Linux Architectures via WSL"
|
|
||||||
Write-Output "========================================================="
|
|
||||||
|
|
||||||
if (Get-Command wsl -ErrorAction SilentlyContinue) {
|
|
||||||
# Anchor output cache on Windows disk to survive WSL instance cycling
|
|
||||||
$LinuxBuildDir = Join-Path $ProjectRoot "target_linux"
|
|
||||||
New-Item -ItemType Directory -Force -Path $LinuxBuildDir | Out-Null
|
|
||||||
$LinuxBuildUnix = $LinuxBuildDir.Replace("\", "/")
|
|
||||||
$WslBuildDir = & wsl wslpath -u $LinuxBuildUnix
|
|
||||||
|
|
||||||
$LinuxTargets = @(
|
|
||||||
@{ Target = "x86_64-unknown-linux-musl"; Arch = "x64"; BinaryName = "ostp" }
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach ($item in $LinuxTargets) {
|
|
||||||
$target = $item.Target
|
|
||||||
$arch = $item.Arch
|
|
||||||
$bin = $item.BinaryName
|
|
||||||
|
|
||||||
$osPrefix = "linux"
|
|
||||||
if ($target -match "freebsd") { $osPrefix = "freebsd" }
|
|
||||||
|
|
||||||
Write-Output "--> Compiling target: $osPrefix $arch [$target] via rust-lld..."
|
|
||||||
|
|
||||||
& wsl rustup target add $target 2>&1 | Out-Null
|
|
||||||
|
|
||||||
# Invoke Cargo cross-compiling via toolless rust-lld LLVM backend for Musl targets!
|
|
||||||
& wsl env RUSTFLAGS="-C linker=rust-lld" CARGO_TARGET_DIR=$WslBuildDir cargo build --release --target $target --bin ostp
|
|
||||||
|
|
||||||
if ($LASTEXITCODE -eq 0) {
|
|
||||||
$compiledBin = Join-Path $LinuxBuildDir "$target\release\$bin"
|
|
||||||
if (Test-Path $compiledBin) {
|
|
||||||
$archiveName = "ostp-v$Version-$osPrefix-$arch.tar.gz"
|
|
||||||
$targetStaging = Join-Path $StagingDir "$osPrefix-$arch"
|
|
||||||
New-Item -ItemType Directory -Force -Path $targetStaging | Out-Null
|
|
||||||
|
|
||||||
Copy-Item -Path $compiledBin -Destination $targetStaging -Force
|
|
||||||
|
|
||||||
# Translate staging paths to Linux formats for WSL tar archiving
|
|
||||||
$wslStagingDir = & wsl wslpath -u ($targetStaging.Replace("\", "/"))
|
|
||||||
$wslArchiveFile = & wsl wslpath -u ((Join-Path $DistDir $archiveName).Replace("\", "/"))
|
|
||||||
|
|
||||||
# Generate clean compressed tarball natively via WSL tar engine
|
|
||||||
& wsl tar -czf $wslArchiveFile -C $wslStagingDir $bin
|
|
||||||
|
|
||||||
$ReleaseArchives += Join-Path $DistDir $archiveName
|
|
||||||
Write-Output "[OK] SUCCESSFULLY PACKAGED: $archiveName"
|
|
||||||
|
|
||||||
if ($Flatten) {
|
|
||||||
$RawReleaseDir = Join-Path $DistDir "release"
|
|
||||||
New-Item -ItemType Directory -Force -Path $RawReleaseDir | Out-Null
|
|
||||||
$FlatName = "ostp-$osPrefix-$arch"
|
|
||||||
Copy-Item -Path $compiledBin -Destination (Join-Path $RawReleaseDir $FlatName) -Force
|
|
||||||
Write-Output " -> Flat copied: dist/release/$FlatName"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Write-Output "[WARN] FAILED compiling Linux $arch ($target)."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Write-Output "[WARN] WSL utility not discovered on host. Skipping Linux binary compilations."
|
|
||||||
}
|
|
||||||
|
|
||||||
# Dissolve staging buffer directory
|
|
||||||
if (Test-Path $StagingDir) { Remove-Item -Path $StagingDir -Recurse -Force -ErrorAction SilentlyContinue }
|
|
||||||
|
|
||||||
Write-Output "`n========================================================="
|
|
||||||
Write-Output " RELEASE ARTIFACTS SUMMARY"
|
|
||||||
Write-Output "========================================================="
|
|
||||||
if ($ReleaseArchives.Count -gt 0) {
|
|
||||||
$ReleaseArchives | ForEach-Object { Write-Output " [+] $_" }
|
|
||||||
} else {
|
|
||||||
Write-Output "[ERROR] CRITICAL: No architectures compiled successfully."
|
|
||||||
Pop-Location
|
Pop-Location
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Show warnings if any
|
||||||
|
$checkWarnings = $checkOutput | Select-String "^warning:" -CaseSensitive
|
||||||
|
if ($checkWarnings) {
|
||||||
|
Write-Output "[warn] Compiler warnings detected (non-blocking):"
|
||||||
|
$checkWarnings | ForEach-Object { Write-Output " $_" }
|
||||||
} else {
|
} else {
|
||||||
Write-Output "`n--> [TRIGGER ONLY MODE] Bypassing all local compilations as requested."
|
Write-Output "[ok] No errors or warnings."
|
||||||
}
|
}
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
if ($Check) {
|
||||||
# PHASE 3: TRIGGER GLOBAL CI/CD RELEASE PIPELINE (Via Git Tag)
|
Write-Output ""
|
||||||
# ---------------------------------------------------------------------
|
Write-Output "Check-only mode. Exiting without build or release."
|
||||||
Write-Output "`n========================================================="
|
# Revert version bump
|
||||||
Write-Output " PHASE 3: Launching Unified Global Cloud Release"
|
[System.IO.File]::WriteAllText($CargoToml, $Content)
|
||||||
Write-Output "========================================================="
|
Pop-Location
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
Write-Output "Synchronizing workspace version metadata to origin master..."
|
Write-Output ""
|
||||||
# Commit current Cargo.toml bump to establish version lineage
|
Write-Output "Starting build pipeline for v$Version"
|
||||||
& git add Cargo.toml
|
|
||||||
|
# Kill existing instances
|
||||||
|
Stop-Process -Name ostp -ErrorAction SilentlyContinue | Out-Null
|
||||||
|
|
||||||
|
$DistDir = Join-Path $ProjectRoot "dist"
|
||||||
|
$StagingDir = Join-Path $DistDir "staging"
|
||||||
|
|
||||||
|
if (Test-Path $DistDir) { Remove-Item -Path $DistDir -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
|
New-Item -ItemType Directory -Force -Path $DistDir | Out-Null
|
||||||
|
|
||||||
|
$ReleaseArchives = @()
|
||||||
|
|
||||||
|
# --- Conditional local build ---
|
||||||
|
if (-not $TriggerOnly) {
|
||||||
|
|
||||||
|
# Phase 1: Windows
|
||||||
|
$WindowsTargets = @(
|
||||||
|
@{ Target = "x86_64-pc-windows-msvc"; Arch = "x64"; BinaryName = "ostp.exe" }
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Output ""
|
||||||
|
Write-Output "--- Phase 1: Windows compilation ---"
|
||||||
|
$TempWinTargetDir = Join-Path $env:TEMP "ostp_target_win"
|
||||||
|
|
||||||
|
foreach ($item in $WindowsTargets) {
|
||||||
|
$target = $item.Target
|
||||||
|
$arch = $item.Arch
|
||||||
|
$bin = $item.BinaryName
|
||||||
|
|
||||||
|
Write-Output " Compiling: Windows $arch ($target)"
|
||||||
|
& rustup target add $target 2>&1 | Out-Null
|
||||||
|
|
||||||
|
$env:CARGO_TARGET_DIR = $TempWinTargetDir
|
||||||
|
& cargo build --release --target $target --bin ostp
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
$compiledBin = Join-Path $TempWinTargetDir "$target\release\$bin"
|
||||||
|
if (Test-Path $compiledBin) {
|
||||||
|
$archiveName = "ostp-v$Version-windows-$arch.zip"
|
||||||
|
$targetStaging = Join-Path $StagingDir "windows-$arch"
|
||||||
|
New-Item -ItemType Directory -Force -Path $targetStaging | Out-Null
|
||||||
|
Copy-Item -Path $compiledBin -Destination $targetStaging -Force
|
||||||
|
|
||||||
|
$archivePath = Join-Path $DistDir $archiveName
|
||||||
|
Compress-Archive -Path "$targetStaging\*" -DestinationPath $archivePath -Force
|
||||||
|
$ReleaseArchives += $archivePath
|
||||||
|
Write-Output " [ok] $archiveName"
|
||||||
|
|
||||||
|
if ($Flatten) {
|
||||||
|
$RawReleaseDir = Join-Path $DistDir "release"
|
||||||
|
New-Item -ItemType Directory -Force -Path $RawReleaseDir | Out-Null
|
||||||
|
$FlatName = "ostp-windows-$arch.exe"
|
||||||
|
Copy-Item -Path $compiledBin -Destination (Join-Path $RawReleaseDir $FlatName) -Force
|
||||||
|
Write-Output " [ok] Flat: dist/release/$FlatName"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Output " [warn] Failed: Windows $arch ($target)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Remove-Item Env:\CARGO_TARGET_DIR -ErrorAction SilentlyContinue | Out-Null
|
||||||
|
|
||||||
|
# Phase 2: Linux via WSL
|
||||||
|
Write-Output ""
|
||||||
|
Write-Output "--- Phase 2: Linux compilation via WSL ---"
|
||||||
|
|
||||||
|
if (Get-Command wsl -ErrorAction SilentlyContinue) {
|
||||||
|
$LinuxBuildDir = Join-Path $ProjectRoot "target_linux"
|
||||||
|
New-Item -ItemType Directory -Force -Path $LinuxBuildDir | Out-Null
|
||||||
|
$LinuxBuildUnix = $LinuxBuildDir.Replace("\", "/")
|
||||||
|
$WslBuildDir = & wsl wslpath -u $LinuxBuildUnix
|
||||||
|
|
||||||
|
$LinuxTargets = @(
|
||||||
|
@{ Target = "x86_64-unknown-linux-musl"; Arch = "x64"; BinaryName = "ostp" }
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($item in $LinuxTargets) {
|
||||||
|
$target = $item.Target
|
||||||
|
$arch = $item.Arch
|
||||||
|
$bin = $item.BinaryName
|
||||||
|
$osPrefix = "linux"
|
||||||
|
if ($target -match "freebsd") { $osPrefix = "freebsd" }
|
||||||
|
|
||||||
|
Write-Output " Compiling: $osPrefix $arch ($target)"
|
||||||
|
& wsl rustup target add $target 2>&1 | Out-Null
|
||||||
|
& wsl env RUSTFLAGS="-C linker=rust-lld" CARGO_TARGET_DIR=$WslBuildDir cargo build --release --target $target --bin ostp
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
$compiledBin = Join-Path $LinuxBuildDir "$target\release\$bin"
|
||||||
|
if (Test-Path $compiledBin) {
|
||||||
|
$archiveName = "ostp-v$Version-$osPrefix-$arch.tar.gz"
|
||||||
|
$targetStaging = Join-Path $StagingDir "$osPrefix-$arch"
|
||||||
|
New-Item -ItemType Directory -Force -Path $targetStaging | Out-Null
|
||||||
|
Copy-Item -Path $compiledBin -Destination $targetStaging -Force
|
||||||
|
|
||||||
|
$wslStagingDir = & wsl wslpath -u ($targetStaging.Replace("\", "/"))
|
||||||
|
$wslArchiveFile = & wsl wslpath -u ((Join-Path $DistDir $archiveName).Replace("\", "/"))
|
||||||
|
& wsl tar -czf $wslArchiveFile -C $wslStagingDir $bin
|
||||||
|
|
||||||
|
$ReleaseArchives += Join-Path $DistDir $archiveName
|
||||||
|
Write-Output " [ok] $archiveName"
|
||||||
|
|
||||||
|
if ($Flatten) {
|
||||||
|
$RawReleaseDir = Join-Path $DistDir "release"
|
||||||
|
New-Item -ItemType Directory -Force -Path $RawReleaseDir | Out-Null
|
||||||
|
$FlatName = "ostp-$osPrefix-$arch"
|
||||||
|
Copy-Item -Path $compiledBin -Destination (Join-Path $RawReleaseDir $FlatName) -Force
|
||||||
|
Write-Output " [ok] Flat: dist/release/$FlatName"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Output " [warn] Failed: $osPrefix $arch ($target)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Output " [skip] WSL not available."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup staging
|
||||||
|
if (Test-Path $StagingDir) { Remove-Item -Path $StagingDir -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
|
|
||||||
|
Write-Output ""
|
||||||
|
Write-Output "--- Build summary ---"
|
||||||
|
if ($ReleaseArchives.Count -gt 0) {
|
||||||
|
$ReleaseArchives | ForEach-Object { Write-Output " $_" }
|
||||||
|
} else {
|
||||||
|
Write-Output "[error] No architectures compiled successfully."
|
||||||
|
Pop-Location
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Write-Output ""
|
||||||
|
Write-Output "[info] Trigger-only mode. Skipping local compilation."
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Phase 3: CI/CD release trigger ---
|
||||||
|
Write-Output ""
|
||||||
|
Write-Output "--- Phase 3: CI/CD release ---"
|
||||||
|
|
||||||
|
Write-Output "Pushing version metadata..."
|
||||||
|
& git add Cargo.toml Cargo.lock
|
||||||
& git commit -m "CI/CD: release version v$Version" --allow-empty | Out-Null
|
& git commit -m "CI/CD: release version v$Version" --allow-empty | Out-Null
|
||||||
& git push origin master | Out-Null
|
& git push origin master | Out-Null
|
||||||
|
|
||||||
Write-Output "Generating release tracking tag: v$Version"
|
Write-Output "Creating release tag: v$Version"
|
||||||
# Purge local tracking tag if pre-existing to guarantee clean sync
|
|
||||||
& git tag -d "v$Version" 2>&1 | Out-Null
|
& git tag -d "v$Version" 2>&1 | Out-Null
|
||||||
& git tag "v$Version"
|
& git tag "v$Version"
|
||||||
|
|
||||||
Write-Output "Deploying trigger tag to GitHub..."
|
Write-Output "Pushing tag to GitHub..."
|
||||||
# Pushing the tag forces GitHub Actions to instantly spin up the cloud builders
|
|
||||||
& git push origin "v$Version" --force
|
& git push origin "v$Version" --force
|
||||||
|
|
||||||
if ($LASTEXITCODE -eq 0) {
|
if ($LASTEXITCODE -eq 0) {
|
||||||
Write-Output "`n[OK] EXCELLENT! Release trigger successfully synchronized with Cloud runners!"
|
Write-Output ""
|
||||||
Write-Output "[INFO] GitHub Actions is now compiling all 13 architectures in parallel."
|
Write-Output "[ok] Release v$Version triggered on GitHub Actions."
|
||||||
Write-Output "[INFO] Live monitoring link: https://github.com/ospab/ostp/actions"
|
Write-Output " Monitor: https://github.com/ospab/ostp/actions"
|
||||||
} else {
|
} else {
|
||||||
Write-Output "`n[ERROR] Failed to deliver release tag to remote origin."
|
Write-Output ""
|
||||||
|
Write-Output "[error] Failed to push release tag."
|
||||||
}
|
}
|
||||||
|
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,22 @@
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
$repo = "ospab/ostp"
|
$repo = "ospab/ostp"
|
||||||
|
|
||||||
# 1. Smart & Aggressive Installation Path Resolution
|
# 1. Install path resolution
|
||||||
$InstallDir = "C:\opt\ostp" # Standard default fallback
|
$InstallDir = "C:\opt\ostp"
|
||||||
|
|
||||||
if (Test-Path "config.json") {
|
if (Test-Path "config.json") {
|
||||||
# Config is in active current directory
|
|
||||||
$InstallDir = (Get-Item .).FullName
|
$InstallDir = (Get-Item .).FullName
|
||||||
} elseif (Test-Path "ostp.exe") {
|
} elseif (Test-Path "ostp.exe") {
|
||||||
# Binary is in active current directory
|
|
||||||
$InstallDir = (Get-Item .).FullName
|
$InstallDir = (Get-Item .).FullName
|
||||||
} elseif ($cmd = Get-Command "ostp" -ErrorAction SilentlyContinue) {
|
} elseif ($cmd = Get-Command "ostp" -ErrorAction SilentlyContinue) {
|
||||||
# Binary is registered in system PATH
|
|
||||||
$InstallDir = Split-Path $cmd.Path
|
$InstallDir = Split-Path $cmd.Path
|
||||||
} else {
|
} else {
|
||||||
# Aggressive search in current directory tree (excluding compiler target and Git directories)
|
$found = Get-ChildItem -Filter "ostp.exe" -Recurse -File -ErrorAction SilentlyContinue |
|
||||||
$found = Get-ChildItem -Filter "ostp.exe" -Recurse -File -ErrorAction SilentlyContinue |
|
Where-Object { $_.FullName -notlike "*\target\*" -and $_.FullName -notlike "*\.git\*" } |
|
||||||
Where-Object { $_.FullName -notlike "*\target\*" -and $_.FullName -notlike "*\.git\*" } |
|
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$InstallDir = Split-Path $found.FullName
|
$InstallDir = Split-Path $found.FullName
|
||||||
} else {
|
} else {
|
||||||
# Scan parent directory as fallback
|
|
||||||
$parentFound = Get-ChildItem -Path .. -Filter "ostp.exe" -File -ErrorAction SilentlyContinue | Select-Object -First 1
|
$parentFound = Get-ChildItem -Path .. -Filter "ostp.exe" -File -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
if ($parentFound) {
|
if ($parentFound) {
|
||||||
$InstallDir = Split-Path $parentFound.FullName
|
$InstallDir = Split-Path $parentFound.FullName
|
||||||
|
|
@ -30,18 +25,18 @@ if (Test-Path "config.json") {
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "========================================================"
|
Write-Host "========================================================"
|
||||||
Write-Host " Installing Ospab Stealth Transport Protocol (OSTP)"
|
Write-Host " OSTP Installer"
|
||||||
Write-Host "========================================================"
|
Write-Host "========================================================"
|
||||||
Write-Host "Target deployment location: $InstallDir"
|
Write-Host "Install directory: $InstallDir"
|
||||||
|
|
||||||
# 2. Check Write Access & Elevation Status
|
# 2. Access check
|
||||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||||
|
|
||||||
if (-not (Test-Path $InstallDir)) {
|
if (-not (Test-Path $InstallDir)) {
|
||||||
try {
|
try {
|
||||||
New-Item -ItemType Directory -Path $InstallDir -ErrorAction Stop | Out-Null
|
New-Item -ItemType Directory -Path $InstallDir -ErrorAction Stop | Out-Null
|
||||||
} catch {
|
} catch {
|
||||||
Write-Error "Access Denied: Cannot create target directory '$InstallDir'. Run as Administrator."
|
Write-Error "Cannot create '$InstallDir'. Run as Administrator."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -50,27 +45,26 @@ if (-not (Test-Path $InstallDir)) {
|
||||||
"test" | Set-Content $testFile -ErrorAction Stop
|
"test" | Set-Content $testFile -ErrorAction Stop
|
||||||
Remove-Item $testFile -Force
|
Remove-Item $testFile -Force
|
||||||
} catch {
|
} catch {
|
||||||
Write-Error "Access Denied: Directory '$InstallDir' is read-only. Run as Administrator to update."
|
Write-Error "Directory '$InstallDir' is read-only. Run as Administrator."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 3. Detect Architecture
|
# 3. Architecture detection
|
||||||
$arch = "amd64"
|
$arch = "amd64"
|
||||||
if ([System.Environment]::Is64BitOperatingSystem -and ($Env:PROCESSOR_ARCHITECTURE -eq "ARM64" -or $Env:PROCESSOR_ARCHITEW6432 -eq "ARM64")) {
|
if ([System.Environment]::Is64BitOperatingSystem -and ($Env:PROCESSOR_ARCHITECTURE -eq "ARM64" -or $Env:PROCESSOR_ARCHITEW6432 -eq "ARM64")) {
|
||||||
$arch = "arm64"
|
$arch = "arm64"
|
||||||
}
|
}
|
||||||
|
|
||||||
# 4. Fetch Stable Version Asset (with -UseBasicParsing to prevent Internet Explorer hangs)
|
# 4. Fetch latest release
|
||||||
Write-Host "Fetching latest stable version from the repository..."
|
Write-Host "Fetching latest release..."
|
||||||
try {
|
try {
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
# Explicitly set -UseBasicParsing to guarantee execution doesn't hang on headless servers
|
|
||||||
$api = Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases/latest" -UseBasicParsing
|
$api = Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases/latest" -UseBasicParsing
|
||||||
$tag = $api.tag_name
|
$tag = $api.tag_name
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host "[Notice] Failed to retrieve tag automatically."
|
Write-Host "[notice] Could not determine latest release automatically."
|
||||||
$tag = Read-Host "Enter release version tag manually (e.g., v0.1.23)"
|
$tag = Read-Host "Enter release tag (e.g. v0.1.60)"
|
||||||
if (-not $tag) { exit 1 }
|
if (-not $tag) { exit 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,132 +73,125 @@ $url = "https://github.com/$repo/releases/download/$tag/$archive"
|
||||||
$zipPath = Join-Path $env:TEMP "ostp_temp_$($PID).zip"
|
$zipPath = Join-Path $env:TEMP "ostp_temp_$($PID).zip"
|
||||||
$extractPath = Join-Path $env:TEMP "ostp_extract_$($PID)"
|
$extractPath = Join-Path $env:TEMP "ostp_extract_$($PID)"
|
||||||
|
|
||||||
Write-Host "Downloading asset windows-${arch}: $url ..."
|
Write-Host "Downloading: $archive ($tag)"
|
||||||
# Explicitly set -UseBasicParsing to prevent any engine initialization stalls
|
|
||||||
Invoke-WebRequest -Uri $url -OutFile $zipPath -UseBasicParsing
|
Invoke-WebRequest -Uri $url -OutFile $zipPath -UseBasicParsing
|
||||||
|
|
||||||
if (-not (Test-Path $zipPath)) {
|
if (-not (Test-Path $zipPath)) {
|
||||||
Write-Error "Failed to download zip package."
|
Write-Error "Download failed."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Overwrite and clear file locks
|
|
||||||
if (Test-Path $extractPath) { Remove-Item $extractPath -Recurse -Force }
|
if (Test-Path $extractPath) { Remove-Item $extractPath -Recurse -Force }
|
||||||
Expand-Archive -Path $zipPath -DestinationPath $extractPath -Force
|
Expand-Archive -Path $zipPath -DestinationPath $extractPath -Force
|
||||||
|
|
||||||
$extractedFiles = Get-ChildItem -Path $extractPath -File -Recurse
|
$extractedFiles = Get-ChildItem -Path $extractPath -File -Recurse
|
||||||
if ($extractedFiles.Count -gt 0) {
|
if ($extractedFiles.Count -gt 0) {
|
||||||
Write-Host "Stopping any active instances of ostp to unlock binary targets..."
|
Write-Host "Stopping active instances..."
|
||||||
Stop-Process -Name "ostp", "tun2socks" -Force -ErrorAction SilentlyContinue
|
Stop-Process -Name "ostp", "tun2socks" -Force -ErrorAction SilentlyContinue
|
||||||
Start-Sleep -Seconds 2
|
Start-Sleep -Seconds 2
|
||||||
|
|
||||||
foreach ($file in $extractedFiles) {
|
foreach ($file in $extractedFiles) {
|
||||||
$destPath = Join-Path $InstallDir $file.Name
|
$destPath = Join-Path $InstallDir $file.Name
|
||||||
if (Test-Path $destPath) {
|
if (Test-Path $destPath) {
|
||||||
# Rename the existing executable out of the way to bypass file locks
|
|
||||||
$oldPath = $destPath + ".old_$PID"
|
$oldPath = $destPath + ".old_$PID"
|
||||||
Rename-Item -Path $destPath -NewName $oldPath -ErrorAction SilentlyContinue
|
Rename-Item -Path $destPath -NewName $oldPath -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
Copy-Item -Path $file.FullName -Destination $destPath -Force
|
Copy-Item -Path $file.FullName -Destination $destPath -Force
|
||||||
(Get-Item $destPath).LastWriteTime = [DateTime]::Now
|
(Get-Item $destPath).LastWriteTime = [DateTime]::Now
|
||||||
}
|
}
|
||||||
|
|
||||||
# Try to clean up any leftover old files
|
|
||||||
Get-ChildItem -Path $InstallDir -Filter "*.old_*" | Remove-Item -Force -ErrorAction SilentlyContinue
|
Get-ChildItem -Path $InstallDir -Filter "*.old_*" | Remove-Item -Force -ErrorAction SilentlyContinue
|
||||||
|
Write-Host "Files deployed to $InstallDir."
|
||||||
Write-Host "Executables and dependencies successfully deployed to $InstallDir."
|
|
||||||
} else {
|
} else {
|
||||||
Write-Error "No files found in archive package."
|
Write-Error "Archive is empty."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Remove-Item $zipPath -Force
|
Remove-Item $zipPath -Force
|
||||||
Remove-Item $extractPath -Recurse -Force
|
Remove-Item $extractPath -Recurse -Force
|
||||||
|
|
||||||
# 5. Smart Auto-Updater Mode
|
# 5. Update detection
|
||||||
$configPath = Join-Path $InstallDir "config.json"
|
$configPath = Join-Path $InstallDir "config.json"
|
||||||
if (Test-Path $configPath) {
|
if (Test-Path $configPath) {
|
||||||
Write-Host "--------------------------------------------------------"
|
Write-Host "--------------------------------------------------------"
|
||||||
Write-Host "[Update] Existing configuration detected at $configPath."
|
Write-Host "Existing configuration found. Binary updated to $tag."
|
||||||
Write-Host "[Update] Binary successfully hot-swapped to version $tag."
|
|
||||||
Write-Host "--------------------------------------------------------"
|
Write-Host "--------------------------------------------------------"
|
||||||
Write-Host "Update completed successfully!"
|
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# 6. Interactive Setup
|
# 6. Interactive setup
|
||||||
Write-Host "--------------------------------------------------------"
|
Write-Host "--------------------------------------------------------"
|
||||||
Write-Host "Select configuration mode:"
|
Write-Host "Select mode:"
|
||||||
Write-Host "1) Configure Server"
|
Write-Host " 1) Server"
|
||||||
Write-Host "2) Configure Client"
|
Write-Host " 2) Client"
|
||||||
Write-Host "--------------------------------------------------------"
|
Write-Host "--------------------------------------------------------"
|
||||||
$mode = Read-Host "Enter choice [1-2]"
|
$mode = Read-Host "Choice [1-2]"
|
||||||
|
|
||||||
Push-Location $InstallDir
|
Push-Location $InstallDir
|
||||||
|
|
||||||
if ($mode -eq "1") {
|
if ($mode -eq "1") {
|
||||||
Write-Host "Initializing server configuration..."
|
Write-Host "Initializing server configuration..."
|
||||||
& .\ostp.exe --init server --config config.json
|
& .\ostp.exe --init server --config config.json
|
||||||
|
|
||||||
$config = Get-Content "config.json" -Raw | ConvertFrom-Json
|
$config = Get-Content "config.json" -Raw | ConvertFrom-Json
|
||||||
$listen = Read-Host "Enter IP and port to accept incoming traffic [default: 0.0.0.0:50000]"
|
$listen = Read-Host "Listen address [default: 0.0.0.0:50000]"
|
||||||
if ($listen) { $config.listen = $listen }
|
if ($listen) { $config.listen = $listen }
|
||||||
|
|
||||||
$keyCount = Read-Host "How many access keys to generate? [default: 1]"
|
$keyCount = Read-Host "Number of access keys [default: 1]"
|
||||||
if (-not $keyCount) { $keyCount = 1 }
|
if (-not $keyCount) { $keyCount = 1 }
|
||||||
|
|
||||||
if ([int]$keyCount -gt 1) {
|
if ([int]$keyCount -gt 1) {
|
||||||
Write-Host "Generating additional security keys..."
|
Write-Host "Generating $keyCount access keys..."
|
||||||
$keys = & .\ostp.exe -g -c $keyCount
|
$keys = & .\ostp.exe -g -c $keyCount
|
||||||
$config.access_keys = $keys -split "`r`n" | Where-Object { $_ -ne "" }
|
$config.access_keys = $keys -split "`r`n" | Where-Object { $_ -ne "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
$config | ConvertTo-Json -Depth 10 | Set-Content "config.json"
|
$config | ConvertTo-Json -Depth 10 | Set-Content "config.json"
|
||||||
Write-Host "Server configuration completed. Config written to $(Join-Path $InstallDir 'config.json')"
|
Write-Host "Server configuration saved: $(Join-Path $InstallDir 'config.json')"
|
||||||
|
|
||||||
} elseif ($mode -eq "2") {
|
} elseif ($mode -eq "2") {
|
||||||
Write-Host "Initializing client configuration..."
|
Write-Host "Initializing client configuration..."
|
||||||
& .\ostp.exe --init client --config config.json
|
& .\ostp.exe --init client --config config.json
|
||||||
|
|
||||||
$config = Get-Content "config.json" -Raw | ConvertFrom-Json
|
$config = Get-Content "config.json" -Raw | ConvertFrom-Json
|
||||||
$server = Read-Host "Enter remote server address (IP:PORT)"
|
$server = Read-Host "Server address (host:port)"
|
||||||
if ($server) { $config.server = $server }
|
if ($server) { $config.server = $server }
|
||||||
|
|
||||||
$key = Read-Host "Enter access key (leave blank to generate automatically)"
|
$key = Read-Host "Access key (blank to generate)"
|
||||||
if (-not $key) {
|
if (-not $key) {
|
||||||
$key = & .\ostp.exe -g
|
$key = & .\ostp.exe -g
|
||||||
Write-Host "Automatically generated client access key: $key"
|
Write-Host "Generated key: $key"
|
||||||
}
|
}
|
||||||
$config.access_key = $key.Trim()
|
$config.access_key = $key.Trim()
|
||||||
|
|
||||||
$socks = Read-Host "Enter SOCKS5 listening address [default: 127.0.0.1:1088]"
|
$socks = Read-Host "Local proxy address [default: 127.0.0.1:1088]"
|
||||||
if ($socks) { $config.socks5_bind = $socks }
|
if ($socks) { $config.socks5_bind = $socks }
|
||||||
|
|
||||||
$config | ConvertTo-Json -Depth 10 | Set-Content "config.json"
|
$config | ConvertTo-Json -Depth 10 | Set-Content "config.json"
|
||||||
Write-Host "Client configuration completed. Config written to $(Join-Path $InstallDir 'config.json')"
|
Write-Host "Client configuration saved: $(Join-Path $InstallDir 'config.json')"
|
||||||
} else {
|
} else {
|
||||||
Write-Error "Invalid configuration choice."
|
Write-Error "Invalid selection."
|
||||||
Pop-Location
|
Pop-Location
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|
||||||
# 7. Environment PATH Registration
|
# 7. PATH registration
|
||||||
Write-Host "--------------------------------------------------------"
|
Write-Host "--------------------------------------------------------"
|
||||||
Write-Host "Registering binary route in Environment PATH..."
|
Write-Host "Registering in system PATH..."
|
||||||
$targetScope = if ($isAdmin) { [EnvironmentVariableTarget]::Machine } else { [EnvironmentVariableTarget]::User }
|
$targetScope = if ($isAdmin) { [EnvironmentVariableTarget]::Machine } else { [EnvironmentVariableTarget]::User }
|
||||||
$sysPath = [Environment]::GetEnvironmentVariable("Path", $targetScope)
|
$sysPath = [Environment]::GetEnvironmentVariable("Path", $targetScope)
|
||||||
if ($sysPath -notlike "*$InstallDir*") {
|
if ($sysPath -notlike "*$InstallDir*") {
|
||||||
$newPath = "$sysPath;$InstallDir"
|
$newPath = "$sysPath;$InstallDir"
|
||||||
[Environment]::SetEnvironmentVariable("Path", $newPath, $targetScope)
|
[Environment]::SetEnvironmentVariable("Path", $newPath, $targetScope)
|
||||||
Write-Host "Environment PATH updated successfully ($($targetScope.ToString()) scope)."
|
Write-Host "PATH updated ($($targetScope.ToString()) scope)."
|
||||||
} else {
|
} else {
|
||||||
Write-Host "$InstallDir is already registered in PATH."
|
Write-Host "$InstallDir already in PATH."
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "--------------------------------------------------------"
|
Write-Host "--------------------------------------------------------"
|
||||||
Write-Host "Deployment completed successfully!"
|
Write-Host "Installation complete."
|
||||||
Write-Host "Binary can be executed globally by typing: ostp"
|
Write-Host " Binary: ostp"
|
||||||
Write-Host "Config location: $(Join-Path $InstallDir 'config.json')"
|
Write-Host " Config: $(Join-Path $InstallDir 'config.json')"
|
||||||
Write-Host "--------------------------------------------------------"
|
Write-Host "--------------------------------------------------------"
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,41 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Official repository settings
|
|
||||||
GITHUB_REPO="ospab/ostp"
|
GITHUB_REPO="ospab/ostp"
|
||||||
INSTALL_DIR="/opt/ostp"
|
INSTALL_DIR="/opt/ostp"
|
||||||
|
|
||||||
echo "========================================================"
|
echo "========================================================"
|
||||||
echo " Installing Ospab Stealth Transport Protocol (OSTP)"
|
echo " OSTP Installer"
|
||||||
echo "========================================================"
|
echo "========================================================"
|
||||||
|
|
||||||
# Verify superuser privileges
|
# Verify root
|
||||||
if [ "$EUID" -ne 0 ]; then
|
if [ "$EUID" -ne 0 ]; then
|
||||||
echo "[Error] This script must be run with root privileges (sudo)."
|
echo "[error] Root privileges required. Run with sudo."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create target directory
|
|
||||||
mkdir -p "$INSTALL_DIR"
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# Architecture detection
|
||||||
# System Architecture Detection
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
ARCH=$(uname -m)
|
ARCH=$(uname -m)
|
||||||
case "$ARCH" in
|
case "$ARCH" in
|
||||||
x86_64) ARCH="amd64" ;;
|
x86_64) ARCH="amd64" ;;
|
||||||
aarch64|arm64) ARCH="arm64" ;;
|
aarch64|arm64) ARCH="arm64" ;;
|
||||||
i386|i686) ARCH="386" ;;
|
i386|i686) ARCH="386" ;;
|
||||||
armv7l) ARCH="armv7" ;;
|
armv7l) ARCH="armv7" ;;
|
||||||
*)
|
*)
|
||||||
echo "[Warning] Unknown architecture $ARCH, falling back to amd64."
|
echo "[warn] Unknown architecture $ARCH, defaulting to amd64."
|
||||||
ARCH="amd64"
|
ARCH="amd64"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Fetch execution binary
|
# Fetch latest release
|
||||||
echo "Fetching the latest stable version from the repository..."
|
echo "Fetching latest release..."
|
||||||
LATEST_RELEASE=$(curl -s "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
LATEST_RELEASE=$(curl -s "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||||
|
|
||||||
if [ -z "$LATEST_RELEASE" ] || [[ "$LATEST_RELEASE" == *"null"* ]]; then
|
if [ -z "$LATEST_RELEASE" ] || [[ "$LATEST_RELEASE" == *"null"* ]]; then
|
||||||
echo "[Notice] Failed to automatically retrieve release tag for ${GITHUB_REPO}."
|
echo "[notice] Could not determine latest release automatically."
|
||||||
echo "Enter a direct URL to the compiled .tar.gz archive"
|
echo "Enter a direct URL to the .tar.gz archive,"
|
||||||
echo "or press Enter if the binary is already in $INSTALL_DIR/ostp."
|
echo "or press Enter if the binary is already in $INSTALL_DIR/ostp."
|
||||||
read -p "URL: " DIRECT_URL
|
read -p "URL: " DIRECT_URL
|
||||||
if [ -n "$DIRECT_URL" ]; then
|
if [ -n "$DIRECT_URL" ]; then
|
||||||
|
|
@ -51,18 +47,18 @@ if [ -z "$LATEST_RELEASE" ] || [[ "$LATEST_RELEASE" == *"null"* ]]; then
|
||||||
else
|
else
|
||||||
ARCHIVE_NAME="ostp-linux-${ARCH}.tar.gz"
|
ARCHIVE_NAME="ostp-linux-${ARCH}.tar.gz"
|
||||||
DOWNLOAD_URL="https://github.com/${GITHUB_REPO}/releases/download/${LATEST_RELEASE}/${ARCHIVE_NAME}"
|
DOWNLOAD_URL="https://github.com/${GITHUB_REPO}/releases/download/${LATEST_RELEASE}/${ARCHIVE_NAME}"
|
||||||
echo "Downloading archive for linux-$ARCH: $DOWNLOAD_URL ..."
|
echo "Downloading: $ARCHIVE_NAME ($LATEST_RELEASE)"
|
||||||
|
|
||||||
TEMP_TAR="/tmp/ostp_temp.tar.gz"
|
TEMP_TAR="/tmp/ostp_temp.tar.gz"
|
||||||
# Fetch archive with basic error handling
|
|
||||||
HTTP_CODE=$(curl -sL -w "%{http_code}" "$DOWNLOAD_URL" -o "$TEMP_TAR")
|
HTTP_CODE=$(curl -sL -w "%{http_code}" "$DOWNLOAD_URL" -o "$TEMP_TAR")
|
||||||
|
|
||||||
if [ "$HTTP_CODE" -eq 200 ]; then
|
if [ "$HTTP_CODE" -eq 200 ]; then
|
||||||
tar -xzf "$TEMP_TAR" -C "$INSTALL_DIR" ostp
|
tar -xzf "$TEMP_TAR" -C "$INSTALL_DIR" ostp
|
||||||
rm -f "$TEMP_TAR"
|
rm -f "$TEMP_TAR"
|
||||||
else
|
else
|
||||||
echo "[Error] Failed to download the file (HTTP status $HTTP_CODE)."
|
echo "[error] Download failed (HTTP $HTTP_CODE)."
|
||||||
echo "Verify that the version $LATEST_RELEASE is published and fully compiled on GitHub."
|
echo "Verify that $LATEST_RELEASE is published at:"
|
||||||
|
echo " https://github.com/$GITHUB_REPO/releases"
|
||||||
rm -f "$TEMP_TAR"
|
rm -f "$TEMP_TAR"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
@ -70,97 +66,93 @@ fi
|
||||||
|
|
||||||
if [ -f "$INSTALL_DIR/ostp" ]; then
|
if [ -f "$INSTALL_DIR/ostp" ]; then
|
||||||
chmod +x "$INSTALL_DIR/ostp"
|
chmod +x "$INSTALL_DIR/ostp"
|
||||||
echo "Executable configured successfully at $INSTALL_DIR/ostp."
|
echo "Binary installed: $INSTALL_DIR/ostp"
|
||||||
else
|
else
|
||||||
echo "[Error] Binary file not found in $INSTALL_DIR/ostp. Aborting setup."
|
echo "[error] Binary not found at $INSTALL_DIR/ostp."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# Update detection
|
||||||
# Automatic Update Detection (Preserves Settings)
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
if [ -f "$INSTALL_DIR/config.json" ]; then
|
if [ -f "$INSTALL_DIR/config.json" ]; then
|
||||||
echo "--------------------------------------------------------"
|
echo "--------------------------------------------------------"
|
||||||
echo "[Update] Existing configuration detected at $INSTALL_DIR/config.json."
|
echo "Existing configuration found. Binary updated to ${LATEST_RELEASE:-latest}."
|
||||||
echo "[Update] Binary successfully updated to version ${LATEST_RELEASE:-latest}."
|
|
||||||
|
|
||||||
if systemctl is-active --quiet ostp.service 2>/dev/null; then
|
if systemctl is-active --quiet ostp.service 2>/dev/null; then
|
||||||
echo "[Update] Restarting service ostp to apply the new version..."
|
echo "Restarting ostp service..."
|
||||||
systemctl restart ostp.service
|
systemctl restart ostp.service
|
||||||
echo "[Update] Service ostp restarted successfully."
|
echo "Service restarted."
|
||||||
else
|
elif systemctl is-enabled --quiet ostp.service 2>/dev/null; then
|
||||||
echo "[Update] Service ostp is registered but not currently running."
|
echo "Service registered but not running."
|
||||||
echo "Start the service manually to apply changes: systemctl start ostp"
|
echo "Start manually: systemctl start ostp"
|
||||||
fi
|
fi
|
||||||
echo "--------------------------------------------------------"
|
echo "--------------------------------------------------------"
|
||||||
echo "Update completed successfully!"
|
echo "Update complete."
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Interactive Setup Menu
|
# Interactive setup
|
||||||
echo "--------------------------------------------------------"
|
echo "--------------------------------------------------------"
|
||||||
echo "Select configuration mode:"
|
echo "Select mode:"
|
||||||
echo "1) Configure Server"
|
echo " 1) Server"
|
||||||
echo "2) Configure Client"
|
echo " 2) Client"
|
||||||
echo "--------------------------------------------------------"
|
echo "--------------------------------------------------------"
|
||||||
read -p "Enter choice [1-2]: " NODE_MODE
|
read -p "Choice [1-2]: " NODE_MODE
|
||||||
|
|
||||||
cd "$INSTALL_DIR"
|
cd "$INSTALL_DIR"
|
||||||
|
|
||||||
if [ "$NODE_MODE" == "1" ]; then
|
if [ "$NODE_MODE" == "1" ]; then
|
||||||
echo "Initializing server configuration..."
|
echo "Initializing server configuration..."
|
||||||
./ostp --init server --config config.json
|
./ostp --init server --config config.json
|
||||||
|
|
||||||
read -p "Enter IP and port to accept incoming traffic [default: 0.0.0.0:50000]: " LISTEN_ADDR
|
read -p "Listen address [default: 0.0.0.0:50000]: " LISTEN_ADDR
|
||||||
if [ -n "$LISTEN_ADDR" ]; then
|
if [ -n "$LISTEN_ADDR" ]; then
|
||||||
sed -i "s/\"listen\": \"0.0.0.0:50000\"/\"listen\": \"$LISTEN_ADDR\"/g" config.json
|
sed -i "s/\"listen\": \".*\"/\"listen\": \"$LISTEN_ADDR\"/g" config.json
|
||||||
fi
|
fi
|
||||||
|
|
||||||
read -p "How many access keys to generate? [default: 1]: " KEYS_COUNT
|
read -p "Number of access keys [default: 1]: " KEYS_COUNT
|
||||||
KEYS_COUNT=${KEYS_COUNT:-1}
|
KEYS_COUNT=${KEYS_COUNT:-1}
|
||||||
|
|
||||||
if [ "$KEYS_COUNT" -gt 1 ]; then
|
if [ "$KEYS_COUNT" -gt 1 ]; then
|
||||||
echo "Generating additional security keys..."
|
echo "Generating $KEYS_COUNT access keys..."
|
||||||
NEW_KEYS=$(./ostp -g -c "$KEYS_COUNT" | sed 's/^/ "/;s/$/",/' | sed '$ s/,$//')
|
NEW_KEYS=$(./ostp -g -c "$KEYS_COUNT" | sed 's/^/ "/;s/$/",/' | sed '$ s/,$//')
|
||||||
sed -i '/"access_keys": \[/,/\]/c\ "access_keys": [\n'"$NEW_KEYS"'\n ],' config.json
|
sed -i '/\"access_keys\": \[/,/\]/c\ "access_keys": [\n'"$NEW_KEYS"'\n ],' config.json
|
||||||
echo "Successfully generated and wrote $KEYS_COUNT keys."
|
|
||||||
fi
|
fi
|
||||||
echo "Server configuration completed. Config file: $INSTALL_DIR/config.json"
|
echo "Server configuration saved: $INSTALL_DIR/config.json"
|
||||||
|
|
||||||
elif [ "$NODE_MODE" == "2" ]; then
|
elif [ "$NODE_MODE" == "2" ]; then
|
||||||
echo "Initializing client configuration..."
|
echo "Initializing client configuration..."
|
||||||
./ostp --init client --config config.json
|
./ostp --init client --config config.json
|
||||||
|
|
||||||
read -p "Enter remote server address (IP:PORT): " REMOTE_SERVER
|
read -p "Server address (host:port): " REMOTE_SERVER
|
||||||
if [ -n "$REMOTE_SERVER" ]; then
|
if [ -n "$REMOTE_SERVER" ]; then
|
||||||
sed -i "s/\"server\": \"127.0.0.1:50000\"/\"server\": \"$REMOTE_SERVER\"/g" config.json
|
sed -i "s/\"server\": \"127.0.0.1:50000\"/\"server\": \"$REMOTE_SERVER\"/g" config.json
|
||||||
else
|
else
|
||||||
echo "[Warning] No remote address provided, keeping default (127.0.0.1:50000)."
|
echo "[warn] No server address provided. Using default (127.0.0.1:50000)."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
read -p "Enter access key (leave blank to generate automatically via ostp -g): " ACCESS_KEY
|
read -p "Access key (blank to generate): " ACCESS_KEY
|
||||||
if [ -z "$ACCESS_KEY" ]; then
|
if [ -z "$ACCESS_KEY" ]; then
|
||||||
ACCESS_KEY=$(./ostp -g)
|
ACCESS_KEY=$(./ostp -g)
|
||||||
echo "Automatically generated client key: $ACCESS_KEY"
|
echo "Generated key: $ACCESS_KEY"
|
||||||
fi
|
fi
|
||||||
sed -i "s/\"access_key\": \"[^\"]*\"/\"access_key\": \"$ACCESS_KEY\"/g" config.json
|
sed -i "s/\"access_key\": \"[^\"]*\"/\"access_key\": \"$ACCESS_KEY\"/g" config.json
|
||||||
|
|
||||||
read -p "Enter local SOCKS5 listening address [default: 127.0.0.1:1088]: " SOCKS_BIND
|
read -p "Local proxy address [default: 127.0.0.1:1088]: " SOCKS_BIND
|
||||||
if [ -n "$SOCKS_BIND" ]; then
|
if [ -n "$SOCKS_BIND" ]; then
|
||||||
sed -i "s/\"socks5_bind\": \"127.0.0.1:1088\"/\"socks5_bind\": \"$SOCKS_BIND\"/g" config.json
|
sed -i "s/\"socks5_bind\": \"127.0.0.1:1088\"/\"socks5_bind\": \"$SOCKS_BIND\"/g" config.json
|
||||||
fi
|
fi
|
||||||
echo "Client configuration completed. Config file: $INSTALL_DIR/config.json"
|
echo "Client configuration saved: $INSTALL_DIR/config.json"
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "[Error] Invalid selection choice."
|
echo "[error] Invalid selection."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Register Systemd daemon
|
# Register systemd service
|
||||||
echo "Registering system service..."
|
echo "Registering systemd service..."
|
||||||
cat <<EOF > /etc/systemd/system/ostp.service
|
cat <<EOF > /etc/systemd/system/ostp.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Ospab Stealth Transport Protocol Service
|
Description=OSTP Service
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
|
|
@ -180,8 +172,7 @@ systemctl daemon-reload
|
||||||
systemctl enable ostp.service >/dev/null 2>&1
|
systemctl enable ostp.service >/dev/null 2>&1
|
||||||
|
|
||||||
echo "--------------------------------------------------------"
|
echo "--------------------------------------------------------"
|
||||||
echo "Installation completed successfully."
|
echo "Installation complete."
|
||||||
echo "Configuration file saved at $INSTALL_DIR/config.json"
|
echo " Config: $INSTALL_DIR/config.json"
|
||||||
echo "Service 'ostp' has been registered but not started."
|
echo " Start: systemctl start ostp"
|
||||||
echo "Start the service manually using: systemctl start ostp"
|
|
||||||
echo "--------------------------------------------------------"
|
echo "--------------------------------------------------------"
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ if [ ! -z "$EXT_SERVER" ]; then
|
||||||
echo -e "2. Awaiting Cryptographic Handshake (Noise_NNpsk0)..."
|
echo -e "2. Awaiting Cryptographic Handshake (Noise_NNpsk0)..."
|
||||||
HANDSHAKE_OK=0
|
HANDSHAKE_OK=0
|
||||||
for i in {1..10}; do
|
for i in {1..10}; do
|
||||||
if grep -q "Bridge connection established" cli.log; then
|
if grep -q "Connection established" cli.log; then
|
||||||
HANDSHAKE_OK=1
|
HANDSHAKE_OK=1
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
@ -91,8 +91,8 @@ if [ ! -z "$EXT_SERVER" ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RTT=$(grep "rtt_ms=" cli.log | tail -n 1 | awk -F'rtt_ms=' '{print $2}' | awk '{print $1}')
|
RTT=$(grep "rtt=" cli.log | tail -n 1 | sed -E 's/.*rtt=([0-9.]+)ms.*/\1/')
|
||||||
echo -e "${GREEN}✓ Handshake Successful!${NC} Estimated Tunnel RTT: \033[0;33m${RTT}ms${NC}\n"
|
echo -e "${GREEN}Handshake successful.${NC} RTT: ${RTT}ms\n"
|
||||||
|
|
||||||
echo -e "3. Executing End-to-End HTTP Proxy Ping..."
|
echo -e "3. Executing End-to-End HTTP Proxy Ping..."
|
||||||
PING_OUTPUT=$(curl -s -o /dev/null -w "DNS: %{time_namelookup}s | Connect: %{time_connect}s | TTFB: %{time_starttransfer}s | Total: %{time_total}s" -x socks5h://127.0.0.1:$SOCKS_PORT -I $HTTP_TEST_URL)
|
PING_OUTPUT=$(curl -s -o /dev/null -w "DNS: %{time_namelookup}s | Connect: %{time_connect}s | TTFB: %{time_starttransfer}s | Total: %{time_total}s" -x socks5h://127.0.0.1:$SOCKS_PORT -I $HTTP_TEST_URL)
|
||||||
|
|
@ -224,8 +224,8 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Validate log patterns
|
# Validate log patterns
|
||||||
grep -q "Starting in SERVER mode" server_run.log
|
grep -q "Starting server" server_run.log
|
||||||
print_result "server dynamic mode logging" $? "Expected starting sequence omitted in log"
|
print_result "server startup log" $? "Expected startup log missing"
|
||||||
|
|
||||||
# Clean up server
|
# Clean up server
|
||||||
kill $SRV_PID 2>/dev/null
|
kill $SRV_PID 2>/dev/null
|
||||||
|
|
@ -255,8 +255,8 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Verify local proxy init logging
|
# Verify local proxy init logging
|
||||||
grep -q "Starting in CLIENT mode" client_run.log
|
grep -q "Starting client" client_run.log
|
||||||
print_result "client local proxy pipeline logging" $? "Starting logs missing"
|
print_result "client startup log" $? "Expected startup log missing"
|
||||||
|
|
||||||
# Verify network bindings (checking if SOCKS5 port opened)
|
# Verify network bindings (checking if SOCKS5 port opened)
|
||||||
# Try both ss and netstat, or fallback to /proc parsing
|
# Try both ss and netstat, or fallback to /proc parsing
|
||||||
|
|
@ -317,8 +317,8 @@ CLI_CONN_PID=$!
|
||||||
sleep 3
|
sleep 3
|
||||||
|
|
||||||
# 4. Validate active handshake in client logs
|
# 4. Validate active handshake in client logs
|
||||||
grep -q "Bridge connection established" client_conn.log
|
grep -q "Connection established" client_conn.log
|
||||||
print_result "client-server secure handshake completion" $? "Handshake signatures missing in log. Log output: $(cat client_conn.log)"
|
print_result "client-server secure handshake" $? "Handshake failed. Log: $(cat client_conn.log)"
|
||||||
|
|
||||||
# 5. Teardown integration run
|
# 5. Teardown integration run
|
||||||
kill $CLI_CONN_PID 2>/dev/null
|
kill $CLI_CONN_PID 2>/dev/null
|
||||||
|
|
@ -391,7 +391,7 @@ SEC_UNAUTH_PID=$!
|
||||||
sleep 3
|
sleep 3
|
||||||
|
|
||||||
# Verify client remained unauthorized
|
# Verify client remained unauthorized
|
||||||
grep -q "Bridge connection established" client_unauth.log
|
grep -q "Connection established" client_unauth.log
|
||||||
HAS_ESTABLISHED=$?
|
HAS_ESTABLISHED=$?
|
||||||
|
|
||||||
if [ $HAS_ESTABLISHED -ne 0 ]; then
|
if [ $HAS_ESTABLISHED -ne 0 ]; then
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue