Skip to content

Conversation

@jakkra
Copy link

@jakkra jakkra commented Dec 6, 2025

Summary by CodeRabbit

  • Chores
    • New build-time option to select which SDK toolchains are installed for smaller images.
    • SDK installation now uses the configured toolchain list instead of installing all toolchains.
    • Added extra cleanup to remove unused toolchains, docs, and heavy sysroot artifacts, reducing image size.
    • CI changes: switched to a slimmer base image, added early disk cleanup, pruned build cache, and expanded CI watch paths.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings December 6, 2025 14:25
@coderabbitai
Copy link

coderabbitai bot commented Dec 6, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a slim base Dockerfile and a CI Dockerfile that parameterizes Zephyr SDK toolchains via ZSDK_TOOLCHAINS (generating repeated -t flags), adds extensive image cleanup, and updates the GitHub Actions workflow to build the new images and run disk/cache pruning steps.

Changes

Cohort / File(s) Summary
CI Dockerfile
Dockerfile.zswatch-ci
Added ARG ZSDK_TOOLCHAINS="arm-zephyr-eabi,x86_64-zephyr-elf" and ENV ZSDK_TOOLCHAINS=$ZSDK_TOOLCHAINS. Replaced single -t all with dynamically generated repeated -t flags from ZSDK_TOOLCHAINS for Zephyr SDK setup. Added post-install cleanup to remove docs/sysroot artifacts and a CI cleanup block to purge multilib/32-bit tooling, debug/coverage/doc packages, and run apt cleanup to reduce image size.
Base Dockerfile
Dockerfile.zswatch-base
Introduces a new slim Ubuntu 24.04 base image tailored for nRF5340/native_sim: trimmed apt package set, Python venv at /opt/python/venv, Zephyr-related Python deps, locale and sudo/non-root user setup, and apt/cache cleanup logic.
Workflow & CI steps
.github/workflows/zswatch-ci-image.yml
Added Dockerfile.zswatch-base and Dockerfile.zswatch-ci to workflow path filters. Replaced base image references/tags to use the slim base (ci-base-slim). Inserted an early "Free disk space" step to report disk usage and remove caches/prune docker resources, added a "Prune buildx cache" step (keep 5GB), and updated build steps to use the new Dockerfile paths and build-args.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify correct shell splitting/quoting when converting ZSDK_TOOLCHAINS into multiple -t flags and ensure no word-splitting bugs.
  • Confirm default ZSDK_TOOLCHAINS includes all toolchains required by CI jobs.
  • Review cleanup sequences to ensure they don't remove artifacts needed later in the build or test stages.
  • Check workflow timing/order: disk cleanup and buildx prune placement relative to cache usage and image builds.
  • Inspect new base Dockerfile for hardcoded mirrors, UID/GID handling, and permission/sudo security implications.

Poem

🐰 I nibble bytes and toolchains bright,

I shuffle docs into the night,
I prune the cache, I sweep the tray,
CI hops lighter, on its way. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is vague and generic, using non-descriptive terms like 'stuff we don't need' without conveying specific information about what changes were made or why. Replace with a more specific title that describes the concrete optimization (e.g., 'Optimize Docker images by removing unused toolchains and documentation' or 'Reduce image size with selective Zephyr SDK toolchain installation').
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch zswatch_size_optimize

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af33da7 and 219bac2.

📒 Files selected for processing (3)
  • .github/workflows/zswatch-ci-image.yml (4 hunks)
  • Dockerfile.zswatch-base (1 hunks)
  • Dockerfile.zswatch-ci (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-push-ci
🔇 Additional comments (11)
Dockerfile.zswatch-base (4)

1-18: ARG/FROM/SHELL setup looks good.

Base image selection, build arguments, and shell configuration are appropriate for a minimal image.


21-75: APT setup and cleanup are well-structured.

The trimmed package set with --no-install-recommends, mirror substitution, and thorough cleanup (apt-get autoremove/clean, rm /var/lib/apt/lists) are appropriate for a minimal base image. The mirror backup/restore approach works for the stated purpose.


84-110: Python venv setup and Zephyr dependency installation look appropriate.

The venv is properly initialized, dependencies are pinned where needed, and PATH is correctly updated. Remote URL installs (lines 91-92) are acceptable for CI environments where temporary GitHub outages are unlikely to be the limiting factor.


113-122: User creation and final setup are correct.

The non-root user is properly configured with sudo access (appropriate for CI), and the final USER root ensures the image build context is root.

Dockerfile.zswatch-ci (3)

15-17: ZSDK_TOOLCHAINS parameterization is well-designed.

The ability to specify toolchains at build time reduces image size by avoiding unnecessary SDKs. The default matches documented use cases.


64-70: SDL2 reinstall is appropriately placed and necessary.

Reinstalling libsdl2-dev after the cleanup block ensures native_sim has access to sdl2.pc, with proper cleanup applied to minimize image size impact.


78-84: Dynamic toolchain flag generation is correct.

The conversion of ZSDK_TOOLCHAINS (comma-separated) into multiple -t flags is properly implemented, with appropriate quoting and parameter expansion. The final -h -c flags are correctly appended.

.github/workflows/zswatch-ci-image.yml (4)

9-10: Path watching for new Dockerfiles is correct.

The workflow now triggers on changes to both Dockerfile.zswatch-base and Dockerfile.zswatch-ci, ensuring changes propagate to CI.


28-34: Disk cleanup step is well-placed and comprehensive.

Running before Buildx setup provides maximum available space for builds. The cleanup targets (dotnet, ghc, android, CodeQL) are typical space consumers on GitHub Actions runners, and before/after df -h output aids troubleshooting.


46-54: Base image build updates are consistent and well-named.

Switching to Dockerfile.zswatch-base with ci-base-slim tags clearly indicates the slim variant. The tag strategy (branch-specific + latest) supports both CI and release workflows.


56-69: Buildx cache management and CI build updates are well-orchestrated.

The new cache prune step prevents unbounded disk growth while preserving recent build artifacts (5GB), and the BASE_IMAGE update ensures the CI image uses the new slim base. Placement between base and CI builds is optimal.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR optimizes the ZSWatch CI Docker image by removing unnecessary components to reduce image size. The changes focus on three main areas: limiting Zephyr SDK toolchains to only those needed by ZSWatch, removing unused development tools inherited from the base image, and cleaning up documentation directories.

Key changes:

  • Limits Zephyr SDK installation to only arm-zephyr-eabi and x86_64-zephyr-elf toolchains instead of installing all toolchains
  • Removes 32-bit support packages and unused debugging/coverage/documentation tools (valgrind, lcov, gcovr, doxygen)
  • Removes documentation directories (doc, man, info) from the installed SDK to save space

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +41 to +46
apt-get purge --auto-remove -y \
valgrind \
lcov \
gcovr \
doxygen \
thrift-compiler || true
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

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

The apt-get purge command is executed without first running apt-get update. When running in a fresh Docker layer, the package manager's cache may be stale or empty, which could cause the purge operation to fail or behave unexpectedly. Although the commands have || true as a safeguard, it's better practice to run apt-get update before package operations.

Consider adding:

apt-get update -y
apt-get purge --auto-remove -y \
    valgrind \
    ...

Copilot uses AI. Check for mistakes.
Comment on lines +36 to +37
libc6-dbg:i386 libfuse-dev:i386 libsdl2-dev:i386 || true
dpkg --remove-architecture i386 || true
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

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

Removing i386 architecture may cause issues with the existing PKG_CONFIG_PATH environment variable on line 79, which points to /usr/lib/i386-linux-gnu/pkgconfig. After this change, that directory will no longer exist, potentially causing package config lookups to fail.

Consider verifying whether i386 package config support is needed, and if not, update the PKG_CONFIG_PATH in a subsequent change to remove the i386 reference.

Copilot uses AI. Check for mistakes.
zephyr-sdk-${ZSDK_VERSION}/setup.sh -t all -h -c
zephyr-sdk-${ZSDK_VERSION}/setup.sh -t "${ZSDK_TOOLCHAINS}" -h -c
rm zephyr-sdk-${ZSDK_VERSION}_linux-${HOSTTYPE}.tar.xz
find zephyr-sdk-${ZSDK_VERSION}/sysroots -maxdepth 4 -type d \( -name doc -o -name man -o -name info \) -exec rm -rf '{}' +
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

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

The find command with -exec rm -rf '{}' + may fail when removing parent directories before their children are processed. When multiple directories match (e.g., nested doc folders), removing a parent doc directory will cause subsequent attempts to remove its child directories to fail because they no longer exist.

Consider using -prune instead or changing + to \; to process one directory at a time:

find zephyr-sdk-${ZSDK_VERSION}/sysroots -maxdepth 4 -type d \( -name doc -o -name man -o -name info \) -exec rm -rf '{}' \;

or use -prune to avoid descending into matched directories:

find zephyr-sdk-${ZSDK_VERSION}/sysroots -maxdepth 4 \( -name doc -o -name man -o -name info \) -prune -exec rm -rf '{}' +
Suggested change
find zephyr-sdk-${ZSDK_VERSION}/sysroots -maxdepth 4 -type d \( -name doc -o -name man -o -name info \) -exec rm -rf '{}' +
find zephyr-sdk-${ZSDK_VERSION}/sysroots -maxdepth 4 -type d \( -name doc -o -name man -o -name info \) -exec rm -rf '{}' \;

Copilot uses AI. Check for mistakes.
@jakkra jakkra force-pushed the zswatch_size_optimize branch from 65b3993 to 4437214 Compare December 6, 2025 14:43
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
Dockerfile.zswatch-ci (2)

32-50: Add apt-get update before purge operations to ensure package cache is fresh.

In a fresh Docker layer, the package manager cache may be stale. Although || true mitigates failures, it's best practice to update the cache first. This mirrors the apt-get update in the earlier block (line 21).

 RUN <<'EOF'
 	if [ "${HOSTTYPE}" = "x86_64" ]; then
 		# Drop 32-bit support and multilib toolchains not needed for nRF/native_sim_64
+		apt-get update -y
 		apt-get purge --auto-remove -y \
 			gcc-multilib g++-multilib \
 			libc6-dbg:i386 libfuse-dev:i386 libsdl2-dev:i386 || true

66-66: Consider using -prune or -maxdepth 1 in find command to avoid nested directory removal risks.

The current find ... -exec rm -rf '{}' + batches deletions, which can fail if a parent directory is removed before its children are processed (e.g., nested doc folders). Using -prune prevents descending into matched directories, or changing + to \; processes one at a time.

-	find zephyr-sdk-${ZSDK_VERSION}/sysroots -maxdepth 4 -type d \( -name doc -o -name man -o -name info \) -exec rm -rf '{}' +
+	find zephyr-sdk-${ZSDK_VERSION}/sysroots -maxdepth 4 -type d \( -name doc -o -name man -o -name info \) -exec rm -rf '{}' \;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 65b3993 and 4437214.

📒 Files selected for processing (2)
  • .github/workflows/zswatch-ci-image.yml (1 hunks)
  • Dockerfile.zswatch-ci (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-push-ci
🔇 Additional comments (4)
Dockerfile.zswatch-ci (3)

15-17: Well-designed configurability for SDK toolchains.

The new ZSDK_TOOLCHAINS argument provides flexibility to customize which toolchains are installed, reducing image size for users who need fewer toolchains.


58-64: Shell loop correctly converts comma-separated toolchains into repeated -t flags.

The logic properly parses ZSDK_TOOLCHAINS and constructs the required arguments for setup.sh. The positional parameter manipulation (set -- "$@" ...) is idiomatic and correct.


85-85: Verify PKG_CONFIG_PATH references valid paths after removing i386 architecture.

Line 37 removes the i386 architecture, so /usr/lib/i386-linux-gnu/pkgconfig (referenced on line 85) will no longer exist. Confirm whether i386 package config support is needed, and update or remove this path reference if it's no longer applicable.

.github/workflows/zswatch-ci-image.yml (1)

9-9: Correctly added Dockerfile.zswatch-ci to push-triggered path filters.

This ensures the CI workflow re-runs whenever the Dockerfile.zswatch-ci file changes, which is essential now that this file is being actively modified and built as part of the pipeline.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
.github/workflows/zswatch-ci-image.yml (1)

55-56: Buildx cache pruning strategically placed.

Pruning the buildx cache after the base image build but before the larger CI image build is well-timed to reclaim space. The 5GB --keep-storage threshold provides a reasonable safety margin while supporting the size reduction goal.

Consider documenting the rationale behind the 5GB threshold if this value may need adjustment in the future as build patterns evolve.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4437214 and ec233cc.

📒 Files selected for processing (1)
  • .github/workflows/zswatch-ci-image.yml (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-push-ci
🔇 Additional comments (2)
.github/workflows/zswatch-ci-image.yml (2)

9-9: Correct addition of Dockerfile.zswatch-ci to trigger paths.

Adding the new Dockerfile to the paths trigger ensures the workflow runs whenever the CI image definition changes, maintaining proper CI/CD integration.


27-33: Good disk cleanup strategy with proper error handling.

The "Free disk space" step removes hosted tool caches (dotnet, ghc, android, CodeQL) and prunes Docker resources before the build, which aligns well with the PR objective to reduce image size. The || true guards prevent step failures from cleanup command errors, and the df -h calls provide useful visibility into freed space.

@jakkra jakkra force-pushed the zswatch_size_optimize branch from ec233cc to e350be5 Compare December 6, 2025 19:49
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec233cc and e350be5.

📒 Files selected for processing (2)
  • .github/workflows/zswatch-ci-image.yml (3 hunks)
  • Dockerfile.zswatch-ci (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/zswatch-ci-image.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-push-ci
🔇 Additional comments (2)
Dockerfile.zswatch-ci (2)

15-17: Good use of build-time configuration to tailor SDK installation.

The ZSDK_TOOLCHAINS arg allows selective installation of only required toolchains, directly supporting the goal of image size reduction. The arg and env var declaration are clean.


67-73: Dynamic toolchain flag generation looks correct.

The logic correctly splits the comma-separated ZSDK_TOOLCHAINS list, generates repeated -t flags, and appends -h -c. This approach is cleaner than the previous -t all and should integrate seamlessly with the Zephyr SDK setup script.

Please verify that the SDK setup script accepts this flag format and that the selected toolchains are installed correctly. You can test locally with: docker build --build-arg ZSDK_TOOLCHAINS="arm-zephyr-eabi" -f Dockerfile.zswatch-ci . and confirm that only the specified toolchain is present in the final image.

Comment on lines 32 to 37
if [ "${HOSTTYPE}" = "x86_64" ]; then
# Drop 32-bit support and multilib toolchains not needed for nRF/native_sim_64
apt-get purge --auto-remove -y \
gcc-multilib g++-multilib \
libc6-dbg:i386 libfuse-dev:i386 libsdl2-dev:i386 || true
dpkg --remove-architecture i386 || true
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -name "Dockerfile.zswatch-ci" --type f

Repository: ZSWatch/docker-image

Length of output: 294


🏁 Script executed:

fd "Dockerfile.zswatch-ci"

Repository: ZSWatch/docker-image

Length of output: 85


🏁 Script executed:

cat -n Dockerfile.zswatch-ci | sed -n '30,40p;90,100p'

Repository: ZSWatch/docker-image

Length of output: 815


🏁 Script executed:

grep -n "i386\|PKG_CONFIG_PATH" Dockerfile.zswatch-ci

Repository: ZSWatch/docker-image

Length of output: 228


Resolve mismatch between i386 architecture removal and PKG_CONFIG_PATH.

Lines 37 removes the i386 architecture on x86_64 hosts, but line 94 still sets PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig. After the i386 removal, this path will not exist, resulting in an unused or stale environment variable.

Either update PKG_CONFIG_PATH to remove the i386 reference, or remove the i386 purge if the path is actually needed for the build.

🤖 Prompt for AI Agents
In Dockerfile.zswatch-ci around lines 32 to 37, the script purges the i386
architecture and removes i386 packages but later (line ~94) PKG_CONFIG_PATH is
set to include /usr/lib/i386-linux-gnu/pkgconfig, creating a mismatch; either
stop removing the i386 architecture and i386 packages if that path is required,
or update the PKG_CONFIG_PATH assignment to exclude the i386 path (and remove
any references to /usr/lib/i386-linux-gnu/pkgconfig) so no stale/nonexistent
i386 pkgconfig path is left in the environment.

@jakkra jakkra force-pushed the zswatch_size_optimize branch from e350be5 to af33da7 Compare December 6, 2025 20:36
@jakkra jakkra force-pushed the zswatch_size_optimize branch from bf8d9b9 to 219bac2 Compare December 6, 2025 22:39
@jakkra jakkra merged commit 86c655c into zswatch_v0.28.4 Dec 7, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants