Skip to content

Enhancement: Parallelize plugin builds, use docker layer caching#115

Open
prasadlohakpure wants to merge 1 commit into
mainfrom
enhancement/parallelize_plugin_builds
Open

Enhancement: Parallelize plugin builds, use docker layer caching#115
prasadlohakpure wants to merge 1 commit into
mainfrom
enhancement/parallelize_plugin_builds

Conversation

@prasadlohakpure

@prasadlohakpure prasadlohakpure commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Speeds up and modernizes the Heimdall build pipeline: parallelized Go/plugin compilation, a flag-driven build.sh, a multi-stage Dockerfile that builds the Go binaries and the web UI in parallel on purpose-built base images, and CI tuned for layer-cache reuse and "build only when needed".

Changes

build.sh

  • Parallelized builds — both commands (cmd/*) and plugins (plugins/*.so) now compile via xargs instead of a serial for loop.
  • Bounded parallelism (default 4) — replaced -P 0 (unlimited). -P 0 compiled all ~15 binaries at once; each go build -buildmode=plugin is memory-hungry and OOM-killed the compiler (signal: killed) inside memory-limited environments (Docker Desktop VM, CI). JOBS is overridable for beefier machines.
  • Flag-driven, no defaults--go, --ui, --test build only what is requested (combine freely; unknown flags fail fast). Lets each Docker stage build just its part.
  • Injectable BUILD_VERSION — honors a CI-provided value and falls back to git describe, then dev (previously it ignored the injected value and broke silently when .git was absent in Docker).

Dockerfile (multi-stage)

  • Split into go-builder (golang:1.24.6, runs ./build.sh --go) and web-builder (node:20-bookworm, runs ./build.sh --ui) stages that BuildKit runs in parallel, plus a slim node:20-bookworm-slim runtime.
  • Why: parallel Go + UI builds; cache isolation (a Go change no longer rebuilds the UI and vice-versa); smaller runtime without the Go toolchain/build tooling; runtime glibc matches the builder so the .so plugins load; Node 20 for next start (fixes the latent Next 16 / Debian Node 18 mismatch).
  • Layer-cache-friendly orderinggo.mod/go.sum -> go mod download and pnpm-lock.yaml -> pnpm fetch are isolated dependency layers (only re-run when manifests change); source is copied last; ARG BUILD_VERSION sits right before its consuming RUN.
  • Runtime keeps only real runtime deps (awscli — sparkeks execs aws, jq, ca-certificates) and pins pnpm via corepack.

CI — .github/workflows/build.yml

  • Runs ./build.sh --go --ui --test.
  • Added a docker-build job that builds the image end-to-end without pushing (type=gha cache) so Dockerfile breakage is caught on PRs.
  • Added a pnpm store cache and paths-ignore so docs-only changes don't trigger the build.

CI — .github/workflows/docker-image.yml

  • Metric based multi runner approach, to build arch native image digests and avoid QEMU to speed up the process.
  • Passes BUILD_VERSION as a build-arg; keeps registry layer cache (mode=max, which also caches the builder stages); paths-ignore for docs.

Results / time improvement

  • Go build (benchmark, UI disabled) — measured ~40% faster from parallelism:
    • Before: ./build.sh 41.18s user 13.05s system 89% cpu 1:00.64 total
    • After: ./build.sh 55.11s user 19.25s system 198% cpu 37.42 total (≈198% CPU → multiple cores utilized)
  • Reliability: bounding JOBS eliminates the OOM (signal: killed) failures that -P 0 caused in the memory-limited Docker/CI builds.
  • Docker/CI: the two builder stages now run concurrently (UI build overlaps the Go compile), and isolated dependency + builder layers are reused across runs via mode=max, so unchanged-dependency builds skip re-downloading/re-resolving Go modules and pnpm packages.

Testing:

Tested by generating image based on multi manifest stitching (Ref. CI action: https://github.com/patterninc/heimdall/actions/runs/29012384485, )
Docker image used for local testing: patternoss/heimdall:ci-115

Steps:

  • Open docker-compose file, modify heimdall-server service config as
  heimdall:
    image: patternoss/heimdall:ci-115
    ports:
      - "9090:9090"
    container_name: heimdall_server_ci-115
  • Run docker-compose up
  • Visit http://localhost:9090/jobs to do E2E tesing
image

Build time dropped from ~1hr 15 mins -> 12 mins

Test plan

  • ./build.sh --go --ui --test passes locally
  • PR build + docker-build jobs green
  • docker compose up -d --build serves the UI at http://localhost:9090

Copilot AI review requested due to automatic review settings July 2, 2026 04:36

Copilot AI left a comment

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.

Pull request overview

This PR updates the repository’s build.sh build pipeline to speed up plugin compilation by running plugin builds in parallel and adding per-plugin logging to improve build output clarity.

Changes:

  • Parallelized plugin builds using xargs -P 0 to utilize multiple CPU cores.
  • Added a log line (building plugin: ...) for each plugin build invocation.

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

Comment thread build.sh Outdated
Comment thread build.sh Outdated
@prasadlohakpure prasadlohakpure changed the title Enhancement: Parallelize plugin builds Enhancement: Parallelize plugin builds, use docker layer caching Jul 2, 2026
Speed up CI/CD by parallelizing Go command/plugin builds and moving
image builds off QEMU emulation.

- build.sh: parallelize command + plugin builds via xargs with a bounded
  JOBS cap (avoids OOM on memory-limited runners); flag-driven steps
  (--go, --ui, --test) so each build stage runs independently.
- Dockerfile: multi-stage build (native Go builder, web builder, slim
  runtime) with dependency-only cache layers for go mod + pnpm.
- docker-image.yml: build each arch on its own native runner (no QEMU),
  push by digest, and stitch into one multi-arch tag with
  `docker buildx imagetools create`; GHA layer cache scoped per arch.
- build.yml: native build + test on PRs with pnpm store caching.
- README: document build.sh flags and env vars.
@prasadlohakpure prasadlohakpure force-pushed the enhancement/parallelize_plugin_builds branch from a339d12 to 909573e Compare July 10, 2026 09:57
@prasadlohakpure prasadlohakpure requested a review from a team July 10, 2026 13:34
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.

3 participants