#!/usr/bin/env bash # # build-image: one-shot build of the ZStack AIOS control-plane image from the # workspace root. Builds the rebranded frontend, overlays it plus our patched # backend sources onto the matching official release image, then (by default) # smoke tests the result. # # It requires both forks to sit on the *same* v-lofyer branch, so a # build can never mix a frontend and backend from different upstream releases. # # Usage: # scripts/build-image # build + verify # scripts/build-image --no-verify # build only # scripts/build-image --skip-ui-build # reuse existing frontend dist/ # scripts/build-image --push # push after a successful build # scripts/build-image --dry-run # show what would happen # # Env knobs (also see gpustack-lofyer/hack/package-lofyer): # NAMESPACE / REPOSITORY / TAG / IMAGE / BASE_IMAGE # SMOKE_PORT host port used by the smoke test (default 18080) # set -o errexit set -o nounset set -o pipefail source "$(dirname "${BASH_SOURCE[0]}")/lib/common.sh" UI_BUILD=1 VERIFY=1 PUSH=0 DRY_RUN=0 SMOKE_PORT="${SMOKE_PORT:-18080}" while [[ $# -gt 0 ]]; do case "${1}" in --skip-ui-build) UI_BUILD=0 ;; --no-verify) VERIFY=0 ;; --verify) VERIFY=1 ;; --push) PUSH=1 ;; --dry-run) DRY_RUN=1 ;; -h|--help) sed -n '2,26p' "${0}"; exit 0 ;; *) fail "unknown argument: ${1}" ;; esac shift done require_cmd docker git require_repos VERSION="$(resolve_workspace_version)" TAG="${TAG:-${VERSION}}" IMAGE="${IMAGE:-${NAMESPACE}/${REPOSITORY}:${TAG}}" log "workspace version : ${VERSION}" log "target image : ${IMAGE}" # 1. Frontend. step "Building frontend" if [[ "${UI_BUILD}" == "1" ]]; then require_cmd npm if [[ "${DRY_RUN}" == "1" ]]; then echo "(dry-run) (cd ${UI_REPO} && GPUSTACK_UI_VERSION=${VERSION} npm run build)" else (cd "${UI_REPO}" && GPUSTACK_UI_VERSION="${VERSION}" npm run build) fi else log "skipping frontend build (--skip-ui-build)" [[ -f "${UI_REPO}/dist/index.html" ]] \ || fail "no existing frontend dist at ${UI_REPO}/dist (drop --skip-ui-build)" fi # 2. Image. Delegates to the backend packaging script, which stages the dist # and only the python files that differ from the upstream tag. step "Building image ${IMAGE}" PACK_ENV=( "NAMESPACE=${NAMESPACE}" "REPOSITORY=${REPOSITORY}" "TAG=${TAG}" "IMAGE=${IMAGE}" "UI_REPO=${UI_REPO}" "PUSH=${PUSH}" "DRY_RUN=${DRY_RUN}" ) [[ -n "${BASE_IMAGE:-}" ]] && PACK_ENV+=("BASE_IMAGE=${BASE_IMAGE}") env "${PACK_ENV[@]}" "${BACKEND_REPO}/hack/package-lofyer" if [[ "${DRY_RUN}" == "1" ]]; then log "dry-run complete" exit 0 fi # 3. Verify. if [[ "${VERIFY}" == "1" ]]; then step "Verifying ${IMAGE}" IMAGE="${IMAGE}" SMOKE_PORT="${SMOKE_PORT}" "$(dirname "${BASH_SOURCE[0]}")/verify-image" fi step "Done" log "image: ${IMAGE}" log "run it with:" echo " docker run -d --name zstack-aios -p 80:80 -v /var/run/docker.sock:/var/run/docker.sock ${IMAGE}"