feat(cloud-api): bake cloud-console SPA into the image and serve at /console
Multi-stage Dockerfile: stage 1 (node:20-bookworm-slim) builds cloud-console with vite base "/console/"; stage 2 (uv) copies dist/ to /app/console-static. Cloud API mounts the SPA at /console via SpaStaticFiles (StaticFiles subclass that falls back to index.html for deep-link refreshes) when the new CLOUD_CONSOLE_STATIC_DIR env is set, and 307-redirects / to /console/. Static files bypass bearer auth (the SPA shell is public; tokens are still required for /v1/*). Compose enables the mount by default; local dev still uses npm run dev + CLOUD_CONSOLE_CORS_ORIGINS. Jenkinsfile passes mirror overrides (NODE_IMAGE, NPM_REGISTRY, UV_IMAGE, APT_MIRROR, UV_INDEX_URL) as --build-arg, defaulting to CN mirrors (registry.jerryyan.net, registry.npmmirror.com, registry-ghcr.jerryyan.top, mirrors.aliyun.com) so CN builds don't time out; Dockerfile ARGs default to official upstreams so `docker build .` still works anywhere. Backend suite: 443 passed (-m "not integration"); cloud-console typecheck and production build succeed with the new base path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Vendored
+20
-1
@@ -20,6 +20,15 @@ pipeline {
|
||||
string(name: 'UV_INDEX_URL', defaultValue: 'https://mirrors.aliyun.com/pypi/simple', description: 'Optional PyPI mirror index URL for uv sync (empty = uv default)')
|
||||
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: 'Skip the uv sync/pytest stage (faster builds when only packaging)')
|
||||
booleanParam(name: 'PUSH', defaultValue: true, description: 'Push the image to REGISTRY after a successful build')
|
||||
|
||||
// Mirror overrides passed to `docker build` as --build-arg. Defaults target
|
||||
// CN networks so Jenkins builds don't time out pulling from Docker Hub /
|
||||
// ghcr.io / npmjs.org / deb.debian.org. Override or blank any of these to
|
||||
// build against the official upstreams.
|
||||
string(name: 'NODE_IMAGE', defaultValue: 'registry.jerryyan.net/library/node:20-bookworm-slim', description: 'Stage 1 base image (Docker Hub library/node proxy)')
|
||||
string(name: 'NPM_REGISTRY', defaultValue: 'https://registry.npmmirror.com', description: 'npm registry URL used by `npm ci`')
|
||||
string(name: 'UV_IMAGE', defaultValue: 'registry-ghcr.jerryyan.top/astral-sh/uv:python3.14-bookworm-slim', description: 'Stage 2 base image (ghcr.io/astral-sh/uv proxy)')
|
||||
string(name: 'APT_MIRROR', defaultValue: 'mirrors.aliyun.com', description: 'Debian apt mirror host (e.g. mirrors.aliyun.com). Empty = deb.debian.org')
|
||||
}
|
||||
|
||||
environment {
|
||||
@@ -79,7 +88,17 @@ pipeline {
|
||||
stage('Build image') {
|
||||
steps {
|
||||
script {
|
||||
def img = docker.build("${FULL_IMAGE}:${IMAGE_TAG}", '.')
|
||||
// Pass every mirror override through as --build-arg. Empty values
|
||||
// are skipped so the Dockerfile ARG default applies.
|
||||
def buildArgs = []
|
||||
["NODE_IMAGE", "NPM_REGISTRY", "UV_IMAGE", "APT_MIRROR", "UV_INDEX_URL"].each { name ->
|
||||
def v = params[name]?.toString()?.trim()
|
||||
if (v) {
|
||||
buildArgs << "--build-arg ${name}=${v}"
|
||||
}
|
||||
}
|
||||
def dockerArgs = (buildArgs.join(' ') + ' .').trim()
|
||||
def img = docker.build("${FULL_IMAGE}:${IMAGE_TAG}", dockerArgs)
|
||||
img.tag('latest')
|
||||
env.BUILT_IMAGE = "${FULL_IMAGE}:${IMAGE_TAG}"
|
||||
echo "Built ${env.BUILT_IMAGE} (+ :latest)"
|
||||
|
||||
Reference in New Issue
Block a user