Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions .github/workflows/build-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ on:
- linux/amd64
- linux/arm64
default: 'all'
embed_web:
description: 'Embed web client assets in the scion binary baked into scion-base'
type: boolean
default: false

workflow_call:
inputs:
Expand All @@ -61,6 +65,10 @@ on:
description: 'Target platform(s) (all, linux/amd64, linux/arm64)'
type: string
default: 'all'
embed_web:
description: 'Embed web client assets in the scion binary baked into scion-base'
type: boolean
default: false

permissions:
contents: read
Expand All @@ -87,9 +95,14 @@ jobs:

- name: Build and push images
run: |
image-build/scripts/build-images.sh \
--registry "${{ inputs.registry }}" \
--target "${{ inputs.target }}" \
--tag "${{ inputs.tag }}" \
--platform "${{ inputs.platform }}" \
args=(
--registry "${{ inputs.registry }}"
--target "${{ inputs.target }}"
--tag "${{ inputs.tag }}"
--platform "${{ inputs.platform }}"
--push
)
if [[ "${{ inputs.embed_web }}" == "true" ]]; then
args+=(--embed-web)
fi
image-build/scripts/build-images.sh "${args[@]}"
14 changes: 13 additions & 1 deletion image-build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ All image-related scripts live under `scripts/`. GitHub Actions workflows remain

The orchestrator owns target sequencing, tag computation, and BASE_IMAGE threading. Each builder only knows how to execute one image build (per-image mode) or one target submission (target mode).

`--embed-web` is available for local Docker and Podman builds when you want
the `scion` binary inside `scion-base` to include the built web client assets.
Cloud Build does not support this flag because it submits static YAML configs.

### Targets

| Target | What gets built | Notes |
Expand Down Expand Up @@ -72,6 +76,12 @@ image-build/scripts/build-images.sh --builder local-podman --target all
# Build and push to your registry (default builder: local-docker)
image-build/scripts/build-images.sh --registry ghcr.io/myorg --push

# Build scion-base with embedded web assets in the scion binary
image-build/scripts/build-images.sh --target scion-base --embed-web

# Build the common image set with embedded web assets in scion-base
image-build/scripts/build-images.sh --target common --embed-web

# Submit to Cloud Build (--registry is required here)
image-build/scripts/build-images.sh --builder cloud-build \
--registry us-central1-docker.pkg.dev/myproj/scion --target all
Expand Down Expand Up @@ -103,7 +113,9 @@ The legacy `trigger-cloudbuild.sh` script still works as a deprecation shim and
1. Fork the repo.
2. Go to **Actions** > **Build Scion Images** > **Run workflow**.
3. Enter `ghcr.io/<your-username>` as the registry.
4. Run `scion config set image_registry ghcr.io/<your-username>`.
4. Optionally enable **embed_web** to bake web client assets into the `scion`
binary in `scion-base`.
5. Run `scion config set image_registry ghcr.io/<your-username>`.

The workflow shells out to `build-images.sh --builder local-docker`. It is also available as a reusable workflow via `workflow_call` for use in downstream repos.

Expand Down
15 changes: 14 additions & 1 deletion image-build/scion-base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ ENV CGO_ENABLED=1
# Build arguments for version info
ARG GIT_COMMIT
ARG BUILD_TIME
ARG EMBED_WEB=false

# Copy go.mod and go.sum first for better layer caching
COPY go.mod go.sum ./
Expand All @@ -36,6 +37,14 @@ RUN go mod download
COPY cmd/ ./cmd/
COPY pkg/ ./pkg/
COPY web/*.go ./web/
COPY web/package.json web/package-lock.json web/vite.config.ts web/tsconfig.json web/tsconfig.client.json web/index.html ./web/
COPY web/scripts/ ./web/scripts/
COPY web/public/ ./web/public/
COPY web/src/ ./web/src/

RUN if [ "${EMBED_WEB}" = "true" ]; then \
cd web && npm ci && npm run build; \
fi
Comment on lines +40 to +47
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current structure of the web asset build process has two significant efficiency issues:

  1. Layer Caching for Dependencies: By copying all web source files (including src/) before running npm ci, any change to a source file will invalidate the cache for the dependency installation step. npm ci is typically slow and should only be re-run when package.json or package-lock.json changes.
  2. Go Build Invalidation: Because the Go build step (line 52) follows the web asset COPY and RUN commands, any change to a frontend file (e.g., a CSS or TS file) will invalidate the cache for the Go build, even if EMBED_WEB is set to false. This causes unnecessary full rebuilds of the scion and sciontool binaries during local development.

To optimize this, split the dependency installation from the build step. For a more robust fix to the Go build invalidation, consider using a separate build stage for the web assets and copying the results back into the main builder stage only if EMBED_WEB is true.

COPY web/package.json web/package-lock.json ./web/
RUN if [ "${EMBED_WEB}" = "true" ]; then \
        cd web && npm ci; \
    fi

COPY web/vite.config.ts web/tsconfig.json web/tsconfig.client.json web/index.html ./web/
COPY web/scripts/ ./web/scripts/
COPY web/public/ ./web/public/
COPY web/src/ ./web/src/

RUN if [ "${EMBED_WEB}" = "true" ]; then \
        cd web && npm run build; \
    fi


# Build with version info injected via ldflags
# VCS stamping is disabled since .git is not in the build context;
Expand All @@ -49,7 +58,11 @@ RUN BUILD_TIME="${BUILD_TIME:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}" && \
SCION_LDFLAGS="${SCION_LDFLAGS} -X ${SCION_PKG}.Commit=${GIT_COMMIT}"; \
SCIONTOOL_LDFLAGS="${SCIONTOOL_LDFLAGS} -X ${SCIONTOOL_PKG}.Commit=${GIT_COMMIT}"; \
fi && \
go build -buildvcs=false -tags no_embed_web -ldflags="${SCION_LDFLAGS}" -o /usr/local/bin/scion ./cmd/scion/ && \
if [ "${EMBED_WEB}" = "true" ]; then \
go build -buildvcs=false -ldflags="${SCION_LDFLAGS}" -o /usr/local/bin/scion ./cmd/scion/; \
else \
go build -buildvcs=false -tags no_embed_web -ldflags="${SCION_LDFLAGS}" -o /usr/local/bin/scion ./cmd/scion/; \
fi && \
go build -buildvcs=false -tags no_embed_web -ldflags="${SCIONTOOL_LDFLAGS}" -o /usr/local/bin/sciontool ./cmd/sciontool/

# Final stage
Expand Down
14 changes: 13 additions & 1 deletion image-build/scripts/build-images.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ TAG="latest"
PLATFORM=""
PUSH="false"
DRY_RUN="false"
EMBED_WEB="false"

# shellcheck source=lib/targets.sh
source "${SCRIPT_DIR}/lib/targets.sh"
Expand Down Expand Up @@ -74,6 +75,9 @@ Options:
--push Push images after building.
Auto-enabled for multi-arch builds (buildx limitation).
Ignored by --builder cloud-build (YAMLs always push).
--embed-web Build scion-base with web client assets embedded in
the scion binary. Supported for local Docker/Podman
image builds; not supported with --builder cloud-build.
--dry-run Print the steps and the exact builder commands without executing.
-h, --help Show this help message.

Expand All @@ -91,6 +95,7 @@ while [[ $# -gt 0 ]]; do
--tag) TAG="$2"; shift 2 ;;
--platform) PLATFORM="$2"; shift 2 ;;
--push) PUSH="true"; shift ;;
--embed-web) EMBED_WEB="true"; shift ;;
--dry-run) DRY_RUN="true"; shift ;;
-h|--help) usage 0 ;;
*) echo "Unknown option: $1" >&2; usage 1 ;;
Expand All @@ -113,6 +118,12 @@ if [[ "${builder_ok}" != "true" ]]; then
exit 1
fi

if [[ "${EMBED_WEB}" == "true" && "${BUILDER}" == "cloud-build" ]]; then
echo "Error: --embed-web is not supported with --builder cloud-build." >&2
echo "Cloud Build uses static YAML definitions; use local-docker or local-podman for embedded web image builds." >&2
exit 1
fi

# Validate target.
if ! resolve_targets "${TARGET}" >/dev/null; then
echo "Error: unknown --target '${TARGET}'" >&2
Expand Down Expand Up @@ -192,6 +203,7 @@ echo "Tag: ${TAG}${SHORT_SHA:+ (+ :${SHORT_SHA})}"
if [[ "${BUILDER_MODE}" == "per-image" ]]; then
echo "Platforms: ${PLATFORMS:-<native>}"
echo "Push: ${PUSH}"
echo "Embed web: ${EMBED_WEB}"
fi
echo "Steps: ${STEPS[*]}"
if [[ "${DRY_RUN}" == "true" ]]; then
Expand Down Expand Up @@ -260,7 +272,7 @@ else
tags="$(compute_tags "${image_name}")"

BASE_TAG="$(resolve_base_tag "${step}")"
export BASE_TAG REGISTRY TAG SHORT_SHA COMMIT_SHA
export BASE_TAG REGISTRY TAG SHORT_SHA COMMIT_SHA EMBED_WEB

# Collect build-args for this step.
build_arg_flags=()
Expand Down
3 changes: 3 additions & 0 deletions image-build/scripts/lib/targets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ step_build_args() {
;;
scion-base)
echo "BASE_IMAGE=${prefix}core-base:${BASE_TAG}"
if [[ "${EMBED_WEB:-false}" == "true" ]]; then
echo "EMBED_WEB=true"
fi
if [[ -n "${COMMIT_SHA:-}" ]]; then
echo "GIT_COMMIT=${COMMIT_SHA}"
fi
Expand Down