Files
wakey/scripts/dev_push.ps1
T

122 lines
4.8 KiB
PowerShell
Executable File

#!/usr/bin/env pwsh
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidDefaultValueSwitchParameter', "",
Justification = 'Default true is intentional for fast dev loop')]
param(
[ValidateSet("cargo", "cross")]
[string]$Cargo = "cargo",
[ValidateSet("wakey", "wakey-agent")]
[ValidateNotNullOrEmpty()]
[string[]]$Package = @("wakey", "wakey-agent"),
[string]$Pass,
[string]$HostName = "192.168.100.1",
[int]$Port = 22,
[string]$User = "root",
[string]$RemotePath = "/root/.bin/wakey",
[string]$AgentRemotePath = "/root/.bin/wakey-agent",
[string]$RemoteInitPath = "/etc/init.d/wakey",
[string]$Target = "armv7-unknown-linux-musleabihf",
[string]$BinName = "wakey",
[string]$AgentBinName = "wakey-agent",
[string]$HostKey,
[switch]$ForcePassword,
[switch]$SkipInitScript,
[switch]$BinariesOnly,
[switch]$Restart = $true,
[switch]$Quiet = $true
)
$ErrorActionPreference = 'Stop'
try { $PSStyle.OutputRendering = 'Host' } catch {}
. "$PSScriptRoot/lib.ps1"
function Build-Packages {
param([string[]]$Packages)
$buildArgs = @('build', '--release', '--target', $Target)
foreach ($pkg in $Packages) { $buildArgs += @('-p', $pkg) }
Write-Host "[build] $Cargo $($buildArgs -join ' ')" -ForegroundColor Cyan
& $Cargo @buildArgs
if ($LASTEXITCODE -ne 0) { throw "$Cargo build failed ($LASTEXITCODE)" }
}
function New-DeploymentPlan {
param([string[]]$Packages)
# Keep CLI first so replacing both binaries restarts the service only once.
$binaries = @(
@{ Package = 'wakey'; Name = $BinName; Destination = $RemotePath }
@{ Package = 'wakey-agent'; Name = $AgentBinName; Destination = $AgentRemotePath }
) | Where-Object { $_.Package -in $Packages } | ForEach-Object {
[pscustomobject]@{
Local = Join-Path $repoRoot "target/$Target/release/$($_.Name)"
Temp = "$($_.Destination).tmp"
Destination = $_.Destination
}
}
$support = @(
if (-not $BinariesOnly) {
if (-not $SkipInitScript) {
@{ Source = 'init/openwrt/wakey'; Temp = '/var/tmp/wakey.init.tmp'; Destination = $RemoteInitPath }
}
@{ Source = 'hotplug/openwrt/dhcp/95-wakey'; Temp = '/var/tmp/wakey.hotplug.dhcp.tmp'; Destination = '/etc/hotplug.d/dhcp/95-wakey' }
@{ Source = 'hotplug/openwrt/neigh/95-wakey'; Temp = '/var/tmp/wakey.hotplug.neigh.tmp'; Destination = '/etc/hotplug.d/neigh/95-wakey' }
}
) | ForEach-Object {
$local = Join-Path $PSScriptRoot $_.Source
if (Test-Path -LiteralPath $local) {
[pscustomobject]@{ Local = $local; Temp = $_.Temp; Destination = $_.Destination }
}
}
foreach ($binary in $binaries) {
if (-not (Test-Path -LiteralPath $binary.Local)) { throw "binary not found: $($binary.Local)" }
}
[pscustomobject]@{ Binaries = @($binaries); Support = @($support) }
}
function Get-RemoteDeployment {
param($Plan)
$deployArgs = @('--batch')
for ($i = 0; $i -lt $Plan.Binaries.Count; $i++) {
$binary = $Plan.Binaries[$i]
$restartFlag = if ($Restart -and $i -eq $Plan.Binaries.Count - 1) { '1' } else { '0' }
$deployArgs += @('--binary', $binary.Temp, $binary.Destination, $restartFlag)
}
foreach ($file in $Plan.Support) {
$deployArgs += @('--install', $file.Temp, $file.Destination)
}
# Only data needs shell quoting; the checked-in shell program travels as stdin.
$command = 'sh -s -- ' + (($deployArgs | ForEach-Object { Quote-ShArg $_ }) -join ' ')
if ($Quiet) { $command += ' >/dev/null 2>&1' }
[pscustomobject]@{
Script = Get-Content -Raw -LiteralPath "$PSScriptRoot/remote_deploy_wakey.sh"
Command = $command
}
}
function Send-DeploymentFiles {
param($Plan)
foreach ($file in @($Plan.Binaries) + @($Plan.Support)) {
Invoke-Scp -Local $file.Local -Dest "$User@${HostName}:$($file.Temp)" -Pass $Pass -HostKey $HostKey -Port $Port -Quiet:$Quiet -ForcePassword:$ForcePassword
}
}
$Pass = Get-DefaultPassword $Pass
# Backward compatibility: allow HostName in the form host:port.
$hostPort = Split-HostPort -HostName $HostName -DefaultPort $Port
$HostName = $hostPort.Host
$Port = $hostPort.Port
$repoRoot = Split-Path -Parent $PSScriptRoot
Push-Location $repoRoot
try {
Build-Packages ($Package | Select-Object -Unique)
$plan = New-DeploymentPlan $Package
# Prepare before uploading so missing local helpers fail without remote changes.
$deployment = Get-RemoteDeployment $plan
Send-DeploymentFiles $plan
Invoke-Ssh -Cmd $deployment.Command -Stdin $deployment.Script -User $User -Remote $HostName -Pass $Pass -Port $Port -Quiet:$Quiet -ForcePassword:$ForcePassword
Write-Host "done ✔" -ForegroundColor Green
}
finally {
Pop-Location
}