This commit is contained in:
ponzischeme89
2026-08-22 20:01:49 +12:00
parent 7d77700c7b
commit d2f7f84cbf
24 changed files with 395 additions and 117 deletions
+51 -11
View File
@@ -28,6 +28,11 @@ by this script.
This deploys the current local working tree, including uncommitted server changes.
Use -SkipAppRelease for an admin/server-only deployment: no APK is built or published.
Use -Fast for a quicker full deployment. It skips Android unit and screenshot tests and
reuses cached Docker dependency/base images when available. The signed APK build and
verification, container builds, activation, rollback, release publishing and health checks
still run.
Use -AdminOnly (or --Admin) to replace the operations console and nothing else. The
console is its own container with its own health check and nothing depends on it, so
only admin-ui/ is uploaded, only the memby-admin image is rebuilt and only that one
@@ -57,6 +62,9 @@ deployment and refuses to create one.
.EXAMPLE
.\deploy-server.ps1 -SkipAppRelease
.EXAMPLE
.\deploy-server.ps1 -Fast
.EXAMPLE
.\deploy-server.ps1 --Admin
@@ -98,6 +106,9 @@ param(
[Parameter()]
[switch] $SkipAppTests,
[Parameter()]
[switch] $Fast,
[Parameter()]
[switch] $SkipAppRelease,
@@ -137,7 +148,7 @@ Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$trailingFlags = @($TrailingFlag0, $TrailingFlag1) | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
$unknownFlags = @($trailingFlags | Where-Object {
$_ -notin @('--m', '--Quiet', '--quiet', '--Admin', '--admin')
$_ -notin @('--m', '--Quiet', '--quiet', '--Admin', '--admin', '--Fast', '--fast')
})
if ($unknownFlags.Count -gt 0) {
throw "Unknown deployment option: $($unknownFlags -join ', ')"
@@ -145,6 +156,15 @@ if ($unknownFlags.Count -gt 0) {
$mandatoryRelease = $MandatoryUpdate -or $trailingFlags -contains '--m'
$quietDeployment = $Quiet -or $trailingFlags -contains '--Quiet' -or $trailingFlags -contains '--quiet'
$consoleOnly = $AdminOnly -or $trailingFlags -contains '--Admin' -or $trailingFlags -contains '--admin'
$fastDeployment = $Fast -or $trailingFlags -contains '--Fast' -or $trailingFlags -contains '--fast'
if ($fastDeployment) {
# Screenshot tests are ordinary testDebugUnitTest classes in this repository, so the
# only reliable way to keep them out of a deployment build is to omit that Gradle task.
# assembleRelease still compiles the production app and the checks below still prove
# that the APK is signed and carries the requested version.
$SkipAppTests = $true
}
if ($mandatoryRelease -and ($SkipAppRelease -or $consoleOnly)) {
throw '--m cannot be combined with -SkipAppRelease or --Admin because no update would be published.'
@@ -164,7 +184,7 @@ if ($consoleOnly) {
# measured twice: a console run rebuilds one small image and a full one swaps the whole
# stack. Averaged together, each estimate would be wrong for both. A record written before
# this existed carries no kind and is read as 'full', which is what all of them were.
$script:DeploymentKind = if ($consoleOnly) { 'console' } else { 'full' }
$script:DeploymentKind = if ($consoleOnly) { 'console' } elseif ($fastDeployment) { 'fast' } else { 'full' }
$script:CurrentStep = 0
$script:LocalStepCount = if ($SkipAppRelease) { 4 } else { 5 }
@@ -184,11 +204,11 @@ $script:FallbackSeconds = @{
'prerequisites' = 3
'source' = 2
'payload' = 4
'android-release' = 230
'android-release' = if ($fastDeployment) { 150 } else { 230 }
'packaging' = 12
# A console deployment uploads one small build context and rebuilds one image, where a
# full one ships the Go tree as well and rebuilds the whole stack.
'remote-deployment' = if ($consoleOnly) { 90 } else { 330 }
'remote-deployment' = if ($consoleOnly) { 90 } elseif ($fastDeployment) { 270 } else { 330 }
}
$script:PhaseDurations = [ordered]@{}
$script:CurrentPhaseKey = $null
@@ -435,7 +455,7 @@ function Show-DeploymentEstimate {
'prerequisites' = 'Local prerequisites'
'source' = 'Source selection'
'payload' = 'Compose validation'
'android-release' = 'Android build and tests'
'android-release' = if ($fastDeployment) { 'Android release build' } else { 'Android build and tests' }
'packaging' = 'Release packaging'
'remote-deployment' = 'Upload, remote build and activation'
}
@@ -471,6 +491,9 @@ function Write-Banner {
if ($quietDeployment) {
Write-Styled -Message '│ NOTICE quiet (no advance television announcement)' -Colour Gray
}
if ($fastDeployment) {
Write-Styled -Message '│ MODE fast (tests and forced image refresh skipped)' -Colour Yellow
}
$initialEstimate = ($script:PhaseOrder | ForEach-Object { (Get-PhaseEstimate -Key $_).Seconds } |
Measure-Object -Sum).Sum
$sampleCounts = @($script:PhaseOrder | ForEach-Object { (Get-PhaseEstimate -Key $_).Samples })
@@ -901,6 +924,10 @@ try {
$gradleArguments = @('--console=plain')
if (-not $SkipAppTests) {
$gradleArguments += 'testDebugUnitTest'
} elseif ($fastDeployment) {
Write-Detail 'Fast mode: skipping Android unit and screenshot tests'
} else {
Write-Detail 'Android tests skipped by -SkipAppTests'
}
$gradleArguments += @(
'assembleRelease',
@@ -1188,6 +1215,7 @@ health_timeout=__HEALTH_TIMEOUT__
publish_release=__PUBLISH_RELEASE__
mandatory_update=__MANDATORY_UPDATE__
quiet_deployment=__QUIET_DEPLOYMENT__
fast_deployment=__FAST_DEPLOYMENT__
colour_output=__COLOUR_OUTPUT__
remote_step_offset=__REMOTE_STEP_OFFSET__
total_steps=__TOTAL_STEPS__
@@ -1423,11 +1451,15 @@ else
fi
step 'Pulling PostgreSQL and Redis'
(
cd "$staging"
docker compose pull postgres redis
)
success 'Dependency images are ready'
if [ "$fast_deployment" -eq 1 ]; then
detail 'Fast mode; reusing cached dependency images when available'
else
(
cd "$staging"
docker compose pull postgres redis
)
success 'Dependency images are ready'
fi
step 'Building the gateway and admin console'
(
@@ -1435,7 +1467,11 @@ step 'Building the gateway and admin console'
# `up` reuses an existing image when one is present. Build both local contexts here,
# otherwise a new React/nginx console can be packaged and activated while the NAS
# continues to serve the previous console image (and its old route configuration).
docker compose build --pull server memby-admin
if [ "$fast_deployment" -eq 1 ]; then
docker compose build server memby-admin
else
docker compose build --pull server memby-admin
fi
)
success 'Gateway and admin console images built'
@@ -1568,6 +1604,10 @@ success 'Memby gateway: https://mserver.sublogue.com'
'__QUIET_DEPLOYMENT__',
$(if ($quietDeployment) { '1' } else { '0' })
)
$remoteCommand = $remoteCommand.Replace(
'__FAST_DEPLOYMENT__',
$(if ($fastDeployment) { '1' } else { '0' })
)
$remoteCommand = $remoteCommand.Replace(
'__COLOUR_OUTPUT__',
$(if ($script:UseColour -and -not [Console]::IsOutputRedirected) { '1' } else { '0' })