From cc3683ae13c4676d25c51fd3f9b027ab2976e881 Mon Sep 17 00:00:00 2001 From: Artem Nikitin Date: Sun, 7 Jun 2026 17:49:13 +0200 Subject: [PATCH 1/2] docs: correct overlay selection description in CI pipeline section The build-images workflow selects exactly one overlay directory (tenant-specific if it exists, otherwise shared) rather than applying both in layers. Update the README to match the actual either/or behavior. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index de28b57..3014c25 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The `build-images` workflow does the following on relevant pushes: 2. Iterates over `tenants/*/*.yaml`. 3. Reads `source_image` and optional `rootfs_size_mb` from each tenant file. 4. Builds `--rootfs.ext4` via `scripts/docker-to-rootfs.sh`. -5. Applies config overlays with precedence: - - `configs/-/` (tenant-specific) - - then `configs//` (shared) +5. Selects one config overlay directory (if present): + - `configs/-/` (tenant-specific, checked first) + - `configs//` (shared, used as fallback when no tenant-specific overlay exists) 6. Uploads resulting `*-rootfs.ext4` artifacts to S3. From b27830c68d6599679267a463182c20695c89ec27 Mon Sep 17 00:00:00 2001 From: Artem Nikitin Date: Sun, 7 Jun 2026 17:55:44 +0200 Subject: [PATCH 2/2] fix: apply shared and tenant-specific config overlays in layers Previously the workflow selected only one overlay directory (tenant-specific if present, otherwise shared), so shared configs were silently skipped whenever a tenant-specific overlay existed. Change docker-to-rootfs.sh to accept a colon-separated list of overlay directories and apply them in order (later entries override earlier ones). Update the workflow to build the colon-separated path when both a shared and a tenant-specific overlay exist, so shared configs serve as the baseline and tenant-specific configs override them. Also update the README to reflect the correct layered behavior. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/build-images.yaml | 7 +++++-- README.md | 6 +++--- scripts/docker-to-rootfs.sh | 23 +++++++++++++++-------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-images.yaml b/.github/workflows/build-images.yaml index 3387359..885350f 100644 --- a/.github/workflows/build-images.yaml +++ b/.github/workflows/build-images.yaml @@ -82,9 +82,12 @@ jobs: size_mb="$(yq '.rootfs_size_mb // 512' "$svc_file")" output="${tenant_id}-${base_name}-rootfs.ext4" - # Config overlay: tenant-specific overlay takes precedence. + # Config overlays: shared baseline applied first, tenant-specific on top. + # Pass as a colon-separated list so docker-to-rootfs.sh applies them in order. overlay_arg="" - if [ -d "configs/${tenant_id}-${base_name}" ]; then + if [ -d "configs/${base_name}" ] && [ -d "configs/${tenant_id}-${base_name}" ]; then + overlay_arg="configs/${base_name}:configs/${tenant_id}-${base_name}" + elif [ -d "configs/${tenant_id}-${base_name}" ]; then overlay_arg="configs/${tenant_id}-${base_name}" elif [ -d "configs/${base_name}" ]; then overlay_arg="configs/${base_name}" diff --git a/README.md b/README.md index 3014c25..5960363 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The `build-images` workflow does the following on relevant pushes: 2. Iterates over `tenants/*/*.yaml`. 3. Reads `source_image` and optional `rootfs_size_mb` from each tenant file. 4. Builds `--rootfs.ext4` via `scripts/docker-to-rootfs.sh`. -5. Selects one config overlay directory (if present): - - `configs/-/` (tenant-specific, checked first) - - `configs//` (shared, used as fallback when no tenant-specific overlay exists) +5. Applies config overlays in order (shared baseline first, tenant-specific on top): + - `configs//` (shared baseline, applied first if present) + - `configs/-/` (tenant-specific, applied on top if present, overrides shared) 6. Uploads resulting `*-rootfs.ext4` artifacts to S3. diff --git a/scripts/docker-to-rootfs.sh b/scripts/docker-to-rootfs.sh index 8ea19f7..04dc4ce 100755 --- a/scripts/docker-to-rootfs.sh +++ b/scripts/docker-to-rootfs.sh @@ -4,10 +4,11 @@ # # Usage: ./scripts/docker-to-rootfs.sh [size_mb] [overlay_dir] [fc_init_bin] # -# overlay_dir Optional directory whose contents are copied into the rootfs, -# mirroring the guest filesystem layout. For example, placing a -# file at overlay_dir/usr/share/elasticsearch/config/elasticsearch.yml -# overwrites that path in the rootfs. +# overlay_dir Optional colon-separated list of directories whose contents are +# copied into the rootfs in order, mirroring the guest filesystem +# layout. Later directories override earlier ones, so pass the shared +# baseline first and tenant-specific overlay second. For example: +# configs/elasticsearch:configs/tenant-1-elasticsearch # fc_init_bin Optional path to a prebuilt linux/arm64 fc-init binary. # If omitted, the script tries: # 1) FC_INIT_BIN env var @@ -164,10 +165,16 @@ RUNTIME_WRITABLE_PATHS_JSON="$(jq -cn \ | unique ')" -# Apply config overlay if provided. -if [ -n "$OVERLAY_DIR" ] && [ -d "$OVERLAY_DIR" ]; then - echo "==> Applying config overlay from $OVERLAY_DIR" - cp -r "$OVERLAY_DIR/." "$ROOTFS/" +# Apply config overlays in order. OVERLAY_DIR may be a colon-separated list; +# later entries override earlier ones (shared baseline first, tenant-specific second). +if [ -n "$OVERLAY_DIR" ]; then + IFS=: read -ra overlay_dirs <<< "$OVERLAY_DIR" + for dir in "${overlay_dirs[@]}"; do + [ -n "$dir" ] || continue + [ -d "$dir" ] || continue + echo "==> Applying config overlay from $dir" + cp -r "$dir/." "$ROOTFS/" + done fi # Some upstream images carry runtime-generated files that should not be baked