From 0054c46d28548842e2969b4b33fa5641906303f3 Mon Sep 17 00:00:00 2001 From: Mikhail Malyshev Date: Wed, 25 Mar 2026 13:35:35 +0000 Subject: [PATCH 1/5] Makefile.eve: flexible linuxkit acquisition, drop manual builder setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the single release-download-only linuxkit path with a two-mode acquisition mechanism: 1. LINUXKIT_GIT_URL + LINUXKIT_GIT_REF (commit hash) — clone the repo at the pinned commit and build the binary. The short SHA is used as the versioned binary name (/tmp/linuxkit-) so make skips the clone+build if the binary already exists. 2. LINUXKIT_GIT_URL unset (default) — download the upstream release binary, same as before. Both LINUXKIT_GIT_URL and LINUXKIT_GIT_REF default to empty so existing CI behaviour is unchanged until the pin commit is added on top. Drop the manual buildkit builder management: remove BUILD_KIT_VERSION, BUILD_KIT_BUILDER, and the ensure-builder target entirely. Current linuxkit creates and manages the builder container automatically when needed, so pre-creating it is no longer required. Remove the --builder= flag from docker buildx build and the | ensure-builder order-only prerequisite from kernel-build-%. Signed-off-by: Mikhail Malyshev --- Makefile.eve | 55 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/Makefile.eve b/Makefile.eve index 16f440def4d88..e8e9e6c96d3b9 100644 --- a/Makefile.eve +++ b/Makefile.eve @@ -9,12 +9,29 @@ BUILD_USER:=$(shell id -un) IMAGE_REPOSITORY?=lfedge/eve-kernel -LINUXKIT_VERSION=58c36c9eb0c32acf66ae7877d18a9ad24d59d73e -GOBIN=/tmp/linuxkit-$(LINUXKIT_VERSION) -LK=$(GOBIN)/linuxkit - -BUILD_KIT_VERSION=v0.12.5 -BUILD_KIT_BUILDER=eve-kernel-builder-$(BUILD_KIT_VERSION) +HOSTARCH:=$(subst aarch64,arm64,$(subst x86_64,amd64,$(shell uname -m))) +UNAME_OS_LCASE:=$(shell uname -s | tr '[A-Z]' '[a-z]') + +# linuxkit version. This **must** be a published semver version so it can be +# downloaded already compiled from the release page at +# https://github.com/linuxkit/linuxkit/releases +LINUXKIT_VERSION ?= v1.7.0 +LINUXKIT_SOURCE ?= https://github.com/linuxkit/linuxkit + +# Set LINUXKIT_GIT_URL to build linuxkit from a pinned commit instead of +# downloading a release binary. LINUXKIT_GIT_REF must be a commit hash +# (reproducible, no network call at parse time). +# Update the hash by running: git ls-remote https://github.com/linuxkit/linuxkit master +# Leave LINUXKIT_GIT_URL unset (default) to use the release binary. +LINUXKIT_GIT_URL ?= +LINUXKIT_GIT_REF ?= + +ifneq ($(LINUXKIT_GIT_URL),) +_LK_VERSION := $(shell printf '%s' '$(LINUXKIT_GIT_REF)' | cut -c1-12) +LK := /tmp/linuxkit-$(_LK_VERSION) +else +LK := /tmp/linuxkit-$(LINUXKIT_VERSION) +endif SOURCE_DATE_EPOCH=$(shell git log -1 --format=%ct) BRANCH=eve-kernel-$(ARCHITECTURE)-$(KERNEL_TAG)-$(EVE_FLAVOR) @@ -50,23 +67,31 @@ help: Makefile @echo " clean: remove generated files" @echo -.PHONY: ensure-builder -ensure-builder: - docker buildx inspect $(BUILD_KIT_BUILDER) 2>/dev/null || \ - docker buildx create --name $(BUILD_KIT_BUILDER) \ - --driver docker-container --bootstrap --driver-opt=image=moby/buildkit:$(BUILD_KIT_VERSION) - .PHONY: linuxkit linuxkit: $(LK) + +ifneq ($(LINUXKIT_GIT_URL),) +# ── Case 1: build from pinned commit ───────────────────────────────────────── +# The hash is used as the binary name — make skips the recipe if already built. +$(LK): + @echo "Building linuxkit from $(LINUXKIT_GIT_URL) at $(LINUXKIT_GIT_REF)" + @tmp=$$(mktemp -d) && \ + git clone --filter=blob:none $(LINUXKIT_GIT_URL) $$tmp && \ + git -C $$tmp checkout $(LINUXKIT_GIT_REF) && \ + $(MAKE) -C $$tmp local-build LOCAL_TARGET=$(abspath $@) && \ + rm -rf $$tmp +else +# ── Case 2: download upstream release binary ────────────────────────────────── $(LK): - GOBIN=$(GOBIN) go install github.com/linuxkit/linuxkit/src/cmd/linuxkit@$(LINUXKIT_VERSION) + @echo "Downloading linuxkit release $(LINUXKIT_VERSION)" + curl -fsSL -o $@ $(LINUXKIT_SOURCE)/releases/download/$(LINUXKIT_VERSION)/linuxkit-$(UNAME_OS_LCASE)-$(HOSTARCH) && chmod +x $@ +endif KERNEL_OCI_FILE:=$(shell mktemp -u)-kernel.tar -kernel-build-%: Makefile.eve linuxkit | ensure-builder +kernel-build-%: Makefile.eve $(LK) @echo "Building kernel version $(BRANCH):$(VERSION)-$* with compiler $*" docker buildx build \ - --builder=$(BUILD_KIT_BUILDER) \ --build-arg="SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH)" \ --build-arg="KBUILD_BUILD_TIMESTAMP=$(KBUILD_BUILD_TIMESTAMP)" \ --build-arg="LOCALVERSION=$(VERSION)$(DIRTY)" \ From 4add327b17119653b7354e0d9666a3a16e37bd36 Mon Sep 17 00:00:00 2001 From: Mikhail Malyshev Date: Wed, 25 Mar 2026 13:35:48 +0000 Subject: [PATCH 2/5] Makefile.eve: pin linuxkit to upstream master tip Set LINUXKIT_GIT_URL and LINUXKIT_GIT_REF to build linuxkit from a pinned upstream commit rather than downloading a release binary. Pinned to the same commit used by the EVE repo (mk/linuxkit.mk): https://github.com/linuxkit/linuxkit @ 3bf33c3a11fc Update by running: git ls-remote https://github.com/linuxkit/linuxkit master Signed-off-by: Mikhail Malyshev --- Makefile.eve | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.eve b/Makefile.eve index e8e9e6c96d3b9..243ca9e51bb6d 100644 --- a/Makefile.eve +++ b/Makefile.eve @@ -15,7 +15,7 @@ UNAME_OS_LCASE:=$(shell uname -s | tr '[A-Z]' '[a-z]') # linuxkit version. This **must** be a published semver version so it can be # downloaded already compiled from the release page at # https://github.com/linuxkit/linuxkit/releases -LINUXKIT_VERSION ?= v1.7.0 +LINUXKIT_VERSION ?= v1.8.1 LINUXKIT_SOURCE ?= https://github.com/linuxkit/linuxkit # Set LINUXKIT_GIT_URL to build linuxkit from a pinned commit instead of @@ -23,8 +23,8 @@ LINUXKIT_SOURCE ?= https://github.com/linuxkit/linuxkit # (reproducible, no network call at parse time). # Update the hash by running: git ls-remote https://github.com/linuxkit/linuxkit master # Leave LINUXKIT_GIT_URL unset (default) to use the release binary. -LINUXKIT_GIT_URL ?= -LINUXKIT_GIT_REF ?= +LINUXKIT_GIT_URL ?= https://github.com/linuxkit/linuxkit +LINUXKIT_GIT_REF ?= 3bf33c3a11fc20b459195294a7d8980cbca4195b ifneq ($(LINUXKIT_GIT_URL),) _LK_VERSION := $(shell printf '%s' '$(LINUXKIT_GIT_REF)' | cut -c1-12) From d1dc8d4c5ef526d4985b779432791ffae4d138bd Mon Sep 17 00:00:00 2001 From: Mikhail Malyshev Date: Wed, 25 Mar 2026 14:11:25 +0000 Subject: [PATCH 3/5] Makefile.eve: use linuxkit pkg build for kernel build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch kernel-build-% from docker buildx build to linuxkit pkg build. linuxkit pkg build manages its own moby/buildkit builder container automatically, avoiding the docker-driver limitation that prevented --sbom=true from working after ensure-builder was removed. The OCI tarball intermediate file is also eliminated — linuxkit pkg build writes directly to the linuxkit content-addressable cache, from which the existing push-image-% target already reads. Add build.yml with org/image descriptor required by linuxkit pkg build. Signed-off-by: Mikhail Malyshev --- Makefile.eve | 22 +++++++++++++--------- build.yml | 3 +++ 2 files changed, 16 insertions(+), 9 deletions(-) create mode 100644 build.yml diff --git a/Makefile.eve b/Makefile.eve index 243ca9e51bb6d..367bad447dd96 100644 --- a/Makefile.eve +++ b/Makefile.eve @@ -87,18 +87,22 @@ $(LK): curl -fsSL -o $@ $(LINUXKIT_SOURCE)/releases/download/$(LINUXKIT_VERSION)/linuxkit-$(UNAME_OS_LCASE)-$(HOSTARCH) && chmod +x $@ endif -KERNEL_OCI_FILE:=$(shell mktemp -u)-kernel.tar +KERNEL_BUILD_ARGS_FILE := $(shell mktemp -u)-kernel-build-args kernel-build-%: Makefile.eve $(LK) @echo "Building kernel version $(BRANCH):$(VERSION)-$* with compiler $*" - docker buildx build \ - --build-arg="SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH)" \ - --build-arg="KBUILD_BUILD_TIMESTAMP=$(KBUILD_BUILD_TIMESTAMP)" \ - --build-arg="LOCALVERSION=$(VERSION)$(DIRTY)" \ - --platform $(PLATFORM) -t $(IMAGE_REPOSITORY):$(BRANCH)-$(VERSION)$(DIRTY)-$* \ - --sbom=true --output=type=oci,dest=$(KERNEL_OCI_FILE) -f Dockerfile.$* . - $(LK) cache import $(KERNEL_OCI_FILE) - rm -f $(KERNEL_OCI_FILE) + @printf 'SOURCE_DATE_EPOCH=%s\nKBUILD_BUILD_TIMESTAMP=%s\nLOCALVERSION=%s\n' \ + '$(SOURCE_DATE_EPOCH)' '$(KBUILD_BUILD_TIMESTAMP)' \ + '$(VERSION)$(DIRTY)' \ + > $(KERNEL_BUILD_ARGS_FILE) + $(LK) pkg build \ + --force \ + --dockerfile Dockerfile.$* \ + --platforms linux/$(ARCHITECTURE) \ + --tag $(BRANCH)-$(VERSION)$(DIRTY)-$* \ + --build-arg-file $(KERNEL_BUILD_ARGS_FILE) \ + . + @rm -f $(KERNEL_BUILD_ARGS_FILE) # we need these intermediate targets to make .PHONY work for pattern rules diff --git a/build.yml b/build.yml new file mode 100644 index 0000000000000..5d98437d6da61 --- /dev/null +++ b/build.yml @@ -0,0 +1,3 @@ +org: lfedge +image: eve-kernel +network: yes From 1ff8be9f20ed627fd97787d523e5cdc8b1d397b4 Mon Sep 17 00:00:00 2001 From: Mikhail Malyshev Date: Tue, 31 Mar 2026 10:32:50 +0000 Subject: [PATCH 4/5] GHA: pin actions to commit SHAs and bump to latest versions - actions/checkout: v3 -> v6.0.2 (de0fac2e4500dabe0009e67214ff5f5447ce83dd) - docker/login-action: v3 -> v4.0.0 (b45d80f862d83dbcd57f89517bcf500b2ab88fb2) Signed-off-by: Mikhail Malyshev --- .github/workflows/publish.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f8873eeb01f4d..054fea890d7ea 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -20,17 +20,24 @@ jobs: if: ${{ github.event.review.state == 'approved' }} || github.ref == env.branch_name steps: - name: Get eve-kernel - uses: actions/checkout@v3 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.head_ref }} + - name: Login to Docker Hub + if: ${{ github.event.repository.full_name }}== 'lf-edge/eve-kernel' + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + with: + username: ${{ secrets.DOCKERHUB_PULL_USER }} + password: ${{ secrets.DOCKERHUB_PULL_TOKEN }} + - name: Build eve-kernel-riscv64 run: | make -f Makefile.eve BRANCH?=${GITHUB_REF##*/} kernel-gcc - name: Log in to Docker Hub if: ${{ github.ref == env.branch_name }} - uses: docker/login-action@v3 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: username: ${{ secrets.RELEASE_DOCKERHUB_ACCOUNT }} password: ${{ secrets.RELEASE_DOCKERHUB_TOKEN }} From cdf6d3f090c3b633158ecb84f5cb13fc8d50373e Mon Sep 17 00:00:00 2001 From: Mikhail Malyshev Date: Tue, 31 Mar 2026 10:33:33 +0000 Subject: [PATCH 5/5] =?UTF-8?q?GHA:=20targeted=20cleanup=20=E2=80=94=20pre?= =?UTF-8?q?serve=20BuildKit=20ccache=20across=20runs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace nuclear 'docker system prune -af' and 'docker volume prune -af' with targeted removal of only the image we just built - Add clean-gcc/clean-clang Makefile targets that remove specific image from both linuxkit cache and docker - Add BuildKit cache pruning with configurable quota via BUILDKIT_KEEP_STORAGE_MB env var (defaults to 32000 MB) to prevent unbounded disk growth - Print BuildKit disk usage before pruning for diagnostics - Use buildctl inside linuxkit-builder container for cache management - Add pr-build.yml for PR builds (on: pull_request) - Restructure publish.yml for push-only trigger - Remove unnecessary Docker Hub login from PR builds Signed-off-by: Mikhail Malyshev --- .github/workflows/pr-build.yml | 53 ++++++++++++++++++ .github/workflows/publish.yml | 98 +++++++++++++++++++--------------- Makefile.eve | 10 +++- 3 files changed, 117 insertions(+), 44 deletions(-) create mode 100644 .github/workflows/pr-build.yml diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml new file mode 100644 index 0000000000000..72c8c440e24b2 --- /dev/null +++ b/.github/workflows/pr-build.yml @@ -0,0 +1,53 @@ +name: PR Build + +on: # yamllint disable-line rule:truthy + pull_request: + branches: + - "eve-kernel-riscv64-v6.1.38-generic" + paths-ignore: + - ".github/**" + +concurrency: + group: pr-build-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + build: + runs-on: [runner-xl, Linux] + + steps: + - name: Set sanitized branch name + id: branch-setter + run: | + BRANCH_NAME="${{ github.event.pull_request.head.ref }}" + SAFE_BRANCH="${BRANCH_NAME//\//-}" + echo "SAFE_BRANCH=$SAFE_BRANCH" >> $GITHUB_ENV + - name: Checkout PR code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + repository: ${{ github.event.pull_request.head.repo.full_name }} + fetch-depth: 1 + + - name: Build kernel + run: | + make -f Makefile.eve \ + BRANCH=$SAFE_BRANCH \ + kernel-gcc + + - name: Clean + if: always() + run: | + make -f Makefile.eve \ + BRANCH=$SAFE_BRANCH \ + clean-gcc + if docker ps -q -f name=linuxkit-builder | grep -q .; then + echo "=== BuildKit disk usage before prune ===" + docker exec linuxkit-builder buildctl du | tail -n 2 + echo "=== Reclaiming ===" + docker exec linuxkit-builder buildctl prune --keep-storage "${BUILDKIT_KEEP_STORAGE_MB:-32000}" | tail -n 1 + echo "=== BuildKit disk usage after prune ===" + docker exec linuxkit-builder buildctl du | tail -n 2 + else + echo "linuxkit-builder container not running; skipping BuildKit cleanup." + fi diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 054fea890d7ea..9e95839ca3a3a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,48 +1,62 @@ -name: eve-kernel build +name: Building and pushing Eve kernel images on: - workflow_dispatch: - pull_request_review: - types: [ submitted ] - push: - branches: - - "eve-kernel-riscv64-v6.1.38-generic" -env: - branch_name: "refs/heads/eve-kernel-riscv64-v6.1.38-generic" + push: + branches: + - "eve-kernel-riscv64-v6.1.38-generic" concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + group: main-build-${{ github.ref }} + cancel-in-progress: true jobs: - packages: - runs-on: self-hosted - if: ${{ github.event.review.state == 'approved' }} || github.ref == env.branch_name - steps: - - name: Get eve-kernel - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: ${{ github.head_ref }} - - - name: Login to Docker Hub - if: ${{ github.event.repository.full_name }}== 'lf-edge/eve-kernel' - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 - with: - username: ${{ secrets.DOCKERHUB_PULL_USER }} - password: ${{ secrets.DOCKERHUB_PULL_TOKEN }} - - - name: Build eve-kernel-riscv64 - run: | - make -f Makefile.eve BRANCH?=${GITHUB_REF##*/} kernel-gcc - - - name: Log in to Docker Hub - if: ${{ github.ref == env.branch_name }} - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 - with: - username: ${{ secrets.RELEASE_DOCKERHUB_ACCOUNT }} - password: ${{ secrets.RELEASE_DOCKERHUB_TOKEN }} - - - name: Push eve-kernel-riscv64-v6.1.38-generic if PR approved or pushed - if: ${{ github.ref == env.branch_name }} - run: | - make -f Makefile.eve BRANCH?=${GITHUB_REF##*/} push-gcc + build: + runs-on: [runner-xl, Linux] + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.ref }} + fetch-depth: 1 + + - name: Login to Docker Hub (pull) + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + with: + username: ${{ secrets.DOCKERHUB_PULL_USER }} + password: ${{ secrets.DOCKERHUB_PULL_TOKEN }} + + - name: Build kernel from ${{ github.ref_name }} + run: | + make -f Makefile.eve \ + BRANCH=${{ github.ref_name }} \ + kernel-gcc + + - name: Login to Docker Hub (push) + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + with: + username: ${{ secrets.RELEASE_DOCKERHUB_ACCOUNT }} + password: ${{ secrets.RELEASE_DOCKERHUB_TOKEN }} + + - name: Push from ${{ github.ref_name }} + run: | + make -f Makefile.eve \ + BRANCH=${{ github.ref_name }} \ + push-gcc + + - name: Clean + if: always() + run: | + make -f Makefile.eve \ + BRANCH=${{ github.ref_name }} \ + clean-gcc + if docker ps -q -f name=linuxkit-builder | grep -q .; then + echo "=== BuildKit disk usage before prune ===" + docker exec linuxkit-builder buildctl du | tail -n 2 + echo "=== Reclaiming ===" + docker exec linuxkit-builder buildctl prune --keep-storage "${BUILDKIT_KEEP_STORAGE_MB:-32000}" | tail -n 1 + echo "=== BuildKit disk usage after prune ===" + docker exec linuxkit-builder buildctl du | tail -n 2 + else + echo "linuxkit-builder container not running; skipping BuildKit cleanup." + fi diff --git a/Makefile.eve b/Makefile.eve index 367bad447dd96..56488e2cbf238 100644 --- a/Makefile.eve +++ b/Makefile.eve @@ -112,8 +112,10 @@ docker-tag-gcc: docker-tag-generate-gcc docker-tag-clang: docker-tag-generate-clang push-gcc: push-image-gcc push-clang: push-image-clang +clean-gcc: clean-image-gcc +clean-clang: clean-image-clang -.PHONY: kernel-gcc kernel-clang docker-tag-gcc docker-tag-clang push-gcc push-clang +.PHONY: kernel-gcc kernel-clang docker-tag-gcc docker-tag-clang push-gcc push-clang clean-gcc clean-clang docker-tag-generate-%: @echo "docker.io/$(IMAGE_REPOSITORY):$(BRANCH)-$(VERSION)$(DIRTY)-$*" @@ -122,6 +124,10 @@ push-image-%: $(if $(DIRTY), $(error "Not pushing since the repo is dirty")) $(LK) cache push $(IMAGE_REPOSITORY):$(BRANCH)-$(VERSION)-$* +clean-image-%: + $(LK) cache rm $(IMAGE_REPOSITORY):$(BRANCH)-$(VERSION)$(DIRTY)-$* 2>/dev/null || true + docker rmi $(IMAGE_REPOSITORY):$(BRANCH)-$(VERSION)$(DIRTY)-$* 2>/dev/null || true + .PHONY: clean clean: - echo "Cleaning" + $(LK) cache clean