distribute prebuilt channel images via GHCR instead of building on pilots
Pilots behind the inspecting proxy cannot reliably build the frontend from source; npm's many small fetches get reset mid-install. Build the image once in CI on the clean runners and have pilots pull the finished channel image. One resumable image pull survives the proxy where hundreds of npm requests do not, and a pilot now needs only Docker.
This commit is contained in:
@@ -11,12 +11,15 @@
|
||||
silently). Python is optional and only checked when -CheckPython is
|
||||
passed, because the app itself runs entirely in the container.
|
||||
2. Picks a channel:
|
||||
stable -> builds from the 'main' branch, no DEV badge.
|
||||
edge -> builds from the 'dev-be' branch, red DEV badge in the UI.
|
||||
stable -> pulls the 'stable' image (built from main), no DEV badge.
|
||||
edge -> pulls the 'edge' image (built from dev-be), red DEV badge.
|
||||
The two channels use different compose project names, host ports, and
|
||||
named volumes, so they run side by side without colliding.
|
||||
3. Generates a .env for the channel (dev-grade secrets, NOT for production)
|
||||
if one does not already exist, then builds and brings up the stack.
|
||||
if one does not already exist, then PULLS the prebuilt channel image
|
||||
from GHCR and brings up the stack. Nothing is built on the host: the
|
||||
image is produced by CI, so a pilot needs only Docker (no Node/npm and
|
||||
no source compile behind the corporate proxy).
|
||||
|
||||
Windows-only by design: pre-release audience is Windows. Not a production
|
||||
installer - see deploy/windows/installer/shopdb-install.ps1 for that.
|
||||
@@ -26,7 +29,8 @@
|
||||
|
||||
.PARAMETER Ref
|
||||
Override the git ref to build. Defaults to 'main' for stable, 'dev-be' for
|
||||
edge. Useful for testing a feature branch through the edge plumbing.
|
||||
edge. Retained for compatibility; the pull flow selects the image by channel
|
||||
tag, so this now only affects which branch the working tree is prepared on.
|
||||
|
||||
.PARAMETER CheckPython
|
||||
Also verify a local Python 3.11+ (only needed if you run tests/tooling on
|
||||
@@ -67,6 +71,7 @@ $channels = @{
|
||||
ApiPort = 5001
|
||||
MysqlPort = 3306
|
||||
EnvLabel = ''
|
||||
ImageTag = 'stable'
|
||||
}
|
||||
edge = @{
|
||||
Ref = 'dev-be'
|
||||
@@ -74,9 +79,15 @@ $channels = @{
|
||||
ApiPort = 5011
|
||||
MysqlPort = 3316
|
||||
EnvLabel = 'DEV'
|
||||
ImageTag = 'edge'
|
||||
}
|
||||
}
|
||||
|
||||
# GHCR repository that CI (.github/workflows/publish-images.yml) publishes the
|
||||
# per-channel images to. Pilots PULL this instead of building from source,
|
||||
# because building behind an inspecting proxy is unreliable.
|
||||
$imageRepo = 'ghcr.io/ge-aero/shopdb-flask'
|
||||
|
||||
function Write-Step {
|
||||
param([string]$Message)
|
||||
Write-Host ''
|
||||
@@ -259,6 +270,15 @@ try {
|
||||
$envPath = Join-Path $repoRoot ".env.$($config.Project)"
|
||||
if (Test-Path $envPath) {
|
||||
Write-Ok "Reusing existing $([System.IO.Path]::GetFileName($envPath))."
|
||||
# A .env written before the pull-based flow existed will not carry a
|
||||
# SHOPDB_IMAGE line, and the pull compose file requires it. Top it up in
|
||||
# place rather than force the pilot to delete and re-key the file.
|
||||
$image = "$imageRepo`:$($config.ImageTag)"
|
||||
$envText = Get-Content -Path $envPath
|
||||
if (-not ($envText | Where-Object { $_ -match '^SHOPDB_IMAGE=' })) {
|
||||
Add-Content -Path $envPath -Value "SHOPDB_IMAGE=$image" -Encoding ASCII
|
||||
Write-Ok "Added SHOPDB_IMAGE=$image to the existing .env."
|
||||
}
|
||||
} else {
|
||||
# Dev-grade secrets: generated locally, never for production. A real
|
||||
# deploy fills .env from the wiki runbook, not from this script.
|
||||
@@ -268,6 +288,7 @@ try {
|
||||
$rootPass = [Convert]::ToBase64String((1..18 | ForEach-Object { Get-Random -Maximum 256 })) -replace '[^A-Za-z0-9]', 'x'
|
||||
$apiPort = $config.ApiPort
|
||||
$mysqlPort = $config.MysqlPort
|
||||
$image = "$imageRepo`:$($config.ImageTag)"
|
||||
|
||||
$lines = @(
|
||||
"# Auto-generated by scripts/dev-bootstrap.ps1 for the $Channel channel.",
|
||||
@@ -283,28 +304,29 @@ try {
|
||||
"MYSQL_PASSWORD=$dbPass",
|
||||
"MYSQL_PORT=$mysqlPort",
|
||||
"API_PORT=$apiPort",
|
||||
"SHOPDB_IMAGE=$image",
|
||||
"SHOPDB_ENV_LABEL=$($config.EnvLabel)"
|
||||
)
|
||||
Set-Content -Path $envPath -Value $lines -Encoding ASCII
|
||||
Write-Ok "Wrote $([System.IO.Path]::GetFileName($envPath)) (API on $apiPort, MySQL on $mysqlPort)."
|
||||
}
|
||||
|
||||
# --- 4. Build and start ---------------------------------------------------
|
||||
# --- 4. Pull and start ----------------------------------------------------
|
||||
|
||||
Write-Step 'Detecting corporate TLS-inspection CA for the Docker build'
|
||||
Set-CorpRootCa -RepoRoot $repoRoot
|
||||
|
||||
Write-Step "Building and starting the '$($config.Project)' stack"
|
||||
# No local build: the image is produced by CI and published to GHCR (see
|
||||
# .github/workflows/publish-images.yml). Pilots may have only Docker
|
||||
# installed, and building the frontend from source behind an inspecting
|
||||
# proxy is unreliable, so we pull the finished channel image instead.
|
||||
Write-Step "Pulling and starting the '$($config.Project)' stack"
|
||||
$composeArgs = @(
|
||||
'compose',
|
||||
'-p', $config.Project,
|
||||
'--env-file', $envPath,
|
||||
'-f', 'docker-compose.yml',
|
||||
'-f', 'docker-compose.channel.yml'
|
||||
'-f', 'docker-compose.pull.yml'
|
||||
)
|
||||
|
||||
& docker @composeArgs build api
|
||||
if ($LASTEXITCODE -ne 0) { throw "docker compose build failed ($LASTEXITCODE)." }
|
||||
& docker @composeArgs pull
|
||||
if ($LASTEXITCODE -ne 0) { throw "docker compose pull failed ($LASTEXITCODE). If this is an auth error, run: docker login ghcr.io" }
|
||||
|
||||
& docker @composeArgs up -d
|
||||
if ($LASTEXITCODE -ne 0) { throw "docker compose up failed ($LASTEXITCODE)." }
|
||||
|
||||
Reference in New Issue
Block a user