Add Docker Scout CVE scanning and switch CI to gmake
- Add `scout` Makefile target that scans all 5 pushed images with `docker scout quickview` and writes a summary to _out/scout-report.md - Switch all CI workflow steps from `make` to `gmake` for GNU Make 4.x - Add brew dependency step for make, gnu-sed, and crane - Include CVE summary in Gitea release notes via jq JSON escaping - Update `clean` target to remove _out/ directory Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
623c5d3694
commit
e98c573bae
@ -28,6 +28,13 @@ jobs:
|
|||||||
- name: Verify Docker is running
|
- name: Verify Docker is running
|
||||||
run: docker info
|
run: docker info
|
||||||
|
|
||||||
|
- name: Install build dependencies
|
||||||
|
run: |
|
||||||
|
for pkg in make gnu-sed crane; do
|
||||||
|
brew list --formula "$pkg" &>/dev/null || brew install "$pkg"
|
||||||
|
done
|
||||||
|
gmake --version | head -1
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
run: |
|
run: |
|
||||||
docker buildx version
|
docker buildx version
|
||||||
@ -42,22 +49,25 @@ jobs:
|
|||||||
run: echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
run: echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Clone upstream sources
|
- name: Clone upstream sources
|
||||||
run: make checkouts
|
run: gmake checkouts
|
||||||
|
|
||||||
- name: Apply patches
|
- name: Apply patches
|
||||||
run: make patches
|
run: gmake patches
|
||||||
|
|
||||||
- name: Build kernel
|
- name: Build kernel
|
||||||
run: make kernel
|
run: gmake kernel
|
||||||
|
|
||||||
- name: Build SBC overlay
|
- name: Build SBC overlay
|
||||||
run: make overlay
|
run: gmake overlay
|
||||||
|
|
||||||
- name: Build installer and disk image
|
- name: Build installer and disk image
|
||||||
run: make installer
|
run: gmake installer
|
||||||
|
|
||||||
- name: Tag release images
|
- name: Tag release images
|
||||||
run: make release TAG=${{ steps.version.outputs.tag }}
|
run: gmake release TAG=${{ steps.version.outputs.tag }}
|
||||||
|
|
||||||
|
- name: Run Docker Scout CVE scan
|
||||||
|
run: gmake scout
|
||||||
|
|
||||||
- name: Compress disk image
|
- name: Compress disk image
|
||||||
run: |
|
run: |
|
||||||
@ -81,21 +91,38 @@ jobs:
|
|||||||
REPO="${GITHUB_REPOSITORY}"
|
REPO="${GITHUB_REPOSITORY}"
|
||||||
API="${GITEA_URL}/api/v1"
|
API="${GITEA_URL}/api/v1"
|
||||||
|
|
||||||
# Create release
|
SCOUT_SECTION=""
|
||||||
|
if [ -f _out/scout-report.md ]; then
|
||||||
|
SCOUT_SECTION=$(cat _out/scout-report.md)
|
||||||
|
fi
|
||||||
|
|
||||||
|
RELEASE_BODY="Custom Talos Linux image for Raspberry Pi 5 / CM5 (Compute Blade)
|
||||||
|
|
||||||
|
**Talos version**: ${TAG}
|
||||||
|
**Kernel**: RPi downstream (CM5/RP1 support)
|
||||||
|
**Extensions**: iscsi-tools, util-linux-tools
|
||||||
|
**Overclock**: 2.6GHz (arm_freq=2600)
|
||||||
|
|
||||||
|
## Artifacts
|
||||||
|
- \`metal-arm64.raw.zst\` — Raw disk image for eMMC flashing
|
||||||
|
- \`docker.io/svrnty/talos-rpi5:${TAG}\` — Installer image for talosctl upgrade
|
||||||
|
|
||||||
|
## Security Scan
|
||||||
|
${SCOUT_SECTION}"
|
||||||
|
|
||||||
|
# Strip leading whitespace from heredoc-style indentation
|
||||||
|
RELEASE_BODY=$(echo "$RELEASE_BODY" | sed 's/^ //')
|
||||||
|
|
||||||
|
RELEASE_BODY_JSON=$(jq -Rs '.' <<< "$RELEASE_BODY")
|
||||||
|
|
||||||
RELEASE_ID=$(curl -sf -X POST \
|
RELEASE_ID=$(curl -sf -X POST \
|
||||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{
|
-d "{\"tag_name\":\"${TAG}\",\"name\":\"Talos RPi5 ${TAG}\",\"body\":${RELEASE_BODY_JSON},\"prerelease\":true}" \
|
||||||
\"tag_name\": \"${TAG}\",
|
|
||||||
\"name\": \"Talos RPi5 ${TAG}\",
|
|
||||||
\"body\": \"Custom Talos Linux image for Raspberry Pi 5 / CM5 (Compute Blade)\n\n**Talos version**: ${TAG}\n**Kernel**: RPi downstream (CM5/RP1 support)\n**Extensions**: iscsi-tools, util-linux-tools\n**Overclock**: 2.6GHz (arm_freq=2600)\n\n## Artifacts\n- \`metal-arm64.raw.zst\` — Raw disk image for eMMC flashing\n- \`docker.io/svrnty/talos-rpi5:${TAG}\` — Installer image for talosctl upgrade\",
|
|
||||||
\"prerelease\": true
|
|
||||||
}" \
|
|
||||||
"${API}/repos/${REPO}/releases" | jq -r '.id')
|
"${API}/repos/${REPO}/releases" | jq -r '.id')
|
||||||
|
|
||||||
echo "Created release ID: ${RELEASE_ID}"
|
echo "Created release ID: ${RELEASE_ID}"
|
||||||
|
|
||||||
# Upload disk image
|
|
||||||
curl -sf -X POST \
|
curl -sf -X POST \
|
||||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
-F "attachment=@metal-arm64.raw.zst" \
|
-F "attachment=@metal-arm64.raw.zst" \
|
||||||
@ -105,4 +132,4 @@ jobs:
|
|||||||
|
|
||||||
- name: Clean up
|
- name: Clean up
|
||||||
if: always()
|
if: always()
|
||||||
run: make clean
|
run: gmake clean
|
||||||
|
|||||||
125
Makefile
125
Makefile
@ -8,17 +8,27 @@
|
|||||||
# make kernel # Build RPi kernel (~15-30 min on ARM64)
|
# make kernel # Build RPi kernel (~15-30 min on ARM64)
|
||||||
# make overlay # Build U-Boot + firmware + DTBs
|
# make overlay # Build U-Boot + firmware + DTBs
|
||||||
# make installer # Build installer image + raw disk image
|
# make installer # Build installer image + raw disk image
|
||||||
# make release # Tag images for release
|
# make release # Tag and push release images
|
||||||
|
# make clean # Remove checkouts and build artifacts
|
||||||
|
|
||||||
PKG_VERSION = v1.12.0
|
PKG_VERSION = v1.12.0
|
||||||
TALOS_VERSION = v1.12.3
|
TALOS_VERSION = v1.12.3
|
||||||
SBCOVERLAY_VERSION = main
|
SBCOVERLAY_VERSION = main
|
||||||
|
|
||||||
|
# Prefer GNU coreutils (macOS: brew install gnu-sed coreutils)
|
||||||
|
export PATH := /opt/homebrew/opt/gnu-sed/libexec/gnubin:$(PATH)
|
||||||
|
|
||||||
REGISTRY ?= docker.io
|
REGISTRY ?= docker.io
|
||||||
REGISTRY_USERNAME ?= svrnty
|
REGISTRY_USERNAME ?= svrnty
|
||||||
|
|
||||||
TAG ?= $(shell git describe --tags --exact-match 2>/dev/null || echo dev)
|
TAG ?= $(shell git describe --tags --exact-match 2>/dev/null || echo dev)
|
||||||
|
|
||||||
|
# Docker Hub image names (project-specific)
|
||||||
|
KERNEL_IMAGE = $(REGISTRY)/$(REGISTRY_USERNAME)/talos-rpi5-kernel
|
||||||
|
OVERLAY_IMAGE = $(REGISTRY)/$(REGISTRY_USERNAME)/talos-rpi5-overlay
|
||||||
|
IMAGER_IMAGE = $(REGISTRY)/$(REGISTRY_USERNAME)/talos-rpi5-imager
|
||||||
|
INSTALLER_IMAGE = $(REGISTRY)/$(REGISTRY_USERNAME)/talos-rpi5-installer
|
||||||
|
|
||||||
# Public image name on Docker Hub (used by talosctl upgrade)
|
# Public image name on Docker Hub (used by talosctl upgrade)
|
||||||
IMAGE_NAME ?= talos-rpi5
|
IMAGE_NAME ?= talos-rpi5
|
||||||
|
|
||||||
@ -40,6 +50,13 @@ SBCOVERLAY_TAG = $(shell cd $(CHECKOUTS_DIRECTORY)/sbc-raspberrypi5 && git descr
|
|||||||
# Build the --system-extension-image flags from the EXTENSIONS list
|
# Build the --system-extension-image flags from the EXTENSIONS list
|
||||||
EXTENSION_FLAGS = $(foreach ext,$(EXTENSIONS),--system-extension-image=$(ext))
|
EXTENSION_FLAGS = $(foreach ext,$(EXTENSIONS),--system-extension-image=$(ext))
|
||||||
|
|
||||||
|
# Common imager flags for overlay and extensions
|
||||||
|
IMAGER_COMMON_FLAGS = \
|
||||||
|
--overlay-name="rpi5" \
|
||||||
|
--overlay-image="$(OVERLAY_IMAGE):$(SBCOVERLAY_TAG)" \
|
||||||
|
--overlay-option="configTxtAppend=$$(cat $(PWD)/config/config.txt.append)" \
|
||||||
|
$(EXTENSION_FLAGS)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Help
|
# Help
|
||||||
#
|
#
|
||||||
@ -54,6 +71,7 @@ help:
|
|||||||
@echo " overlay — Build SBC overlay (U-Boot, firmware, DTBs)"
|
@echo " overlay — Build SBC overlay (U-Boot, firmware, DTBs)"
|
||||||
@echo " installer — Build Talos installer image + raw disk image"
|
@echo " installer — Build Talos installer image + raw disk image"
|
||||||
@echo " release — Tag and push release images"
|
@echo " release — Tag and push release images"
|
||||||
|
@echo " scout — Run Docker Scout CVE scan on all images"
|
||||||
@echo " clean — Remove checkouts and build artifacts"
|
@echo " clean — Remove checkouts and build artifacts"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Variables:"
|
@echo "Variables:"
|
||||||
@ -61,6 +79,12 @@ help:
|
|||||||
@echo " PKG_VERSION = $(PKG_VERSION)"
|
@echo " PKG_VERSION = $(PKG_VERSION)"
|
||||||
@echo " REGISTRY = $(REGISTRY)"
|
@echo " REGISTRY = $(REGISTRY)"
|
||||||
@echo " REGISTRY_USERNAME = $(REGISTRY_USERNAME)"
|
@echo " REGISTRY_USERNAME = $(REGISTRY_USERNAME)"
|
||||||
|
@echo ""
|
||||||
|
@echo "Images:"
|
||||||
|
@echo " KERNEL_IMAGE = $(KERNEL_IMAGE)"
|
||||||
|
@echo " OVERLAY_IMAGE = $(OVERLAY_IMAGE)"
|
||||||
|
@echo " IMAGER_IMAGE = $(IMAGER_IMAGE)"
|
||||||
|
@echo " INSTALLER_IMAGE = $(INSTALLER_IMAGE)"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Checkouts
|
# Checkouts
|
||||||
@ -91,63 +115,116 @@ patches-talos:
|
|||||||
patches: patches-pkgs patches-talos
|
patches: patches-pkgs patches-talos
|
||||||
|
|
||||||
#
|
#
|
||||||
# Kernel
|
# Kernel — build and push the RPi downstream kernel
|
||||||
#
|
#
|
||||||
.PHONY: kernel
|
.PHONY: kernel
|
||||||
kernel:
|
kernel:
|
||||||
cd "$(CHECKOUTS_DIRECTORY)/pkgs" && \
|
cd "$(CHECKOUTS_DIRECTORY)/pkgs" && \
|
||||||
$(MAKE) \
|
$(MAKE) docker-kernel \
|
||||||
REGISTRY=$(REGISTRY) USERNAME=$(REGISTRY_USERNAME) PUSH=true \
|
TARGET_ARGS="--tag=$(KERNEL_IMAGE):$(PKGS_TAG) --push=true" \
|
||||||
PLATFORM=linux/arm64 \
|
PLATFORM=linux/arm64
|
||||||
kernel
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Overlay
|
# Overlay — build U-Boot + firmware + DTBs
|
||||||
|
#
|
||||||
|
# The overlay's pkg.yaml references the kernel as PKGS_PREFIX/kernel:PKGS.
|
||||||
|
# We rewrite it to point to our project-specific kernel image name.
|
||||||
#
|
#
|
||||||
.PHONY: overlay
|
.PHONY: overlay
|
||||||
overlay:
|
overlay:
|
||||||
@echo "SBCOVERLAY_TAG = $(SBCOVERLAY_TAG)"
|
@echo "SBCOVERLAY_TAG = $(SBCOVERLAY_TAG)"
|
||||||
|
@sed -i.bak 's|{{ .BUILD_ARG_PKGS_PREFIX }}/kernel:{{ .BUILD_ARG_PKGS }}|$(KERNEL_IMAGE):$(PKGS_TAG)|' \
|
||||||
|
"$(CHECKOUTS_DIRECTORY)/sbc-raspberrypi5/internal/base/pkg.yaml" && \
|
||||||
|
rm -f "$(CHECKOUTS_DIRECTORY)/sbc-raspberrypi5/internal/base/pkg.yaml.bak"
|
||||||
cd "$(CHECKOUTS_DIRECTORY)/sbc-raspberrypi5" && \
|
cd "$(CHECKOUTS_DIRECTORY)/sbc-raspberrypi5" && \
|
||||||
$(MAKE) \
|
$(MAKE) docker-sbc-raspberrypi5 \
|
||||||
REGISTRY=$(REGISTRY) USERNAME=$(REGISTRY_USERNAME) IMAGE_TAG=$(SBCOVERLAY_TAG) PUSH=true \
|
TARGET_ARGS="--tag=$(OVERLAY_IMAGE):$(SBCOVERLAY_TAG) --push=true" \
|
||||||
PKGS_PREFIX=$(REGISTRY)/$(REGISTRY_USERNAME) PKGS=$(PKGS_TAG) \
|
INSTALLER_ARCH=arm64 PLATFORM=linux/arm64
|
||||||
INSTALLER_ARCH=arm64 PLATFORM=linux/arm64 \
|
|
||||||
sbc-raspberrypi5
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Installer / Disk Image
|
# Installer / Disk Image
|
||||||
#
|
#
|
||||||
|
# Builds the imager, installer-base, and installer images step by step,
|
||||||
|
# pushing each to our project-specific Docker Hub repos.
|
||||||
|
#
|
||||||
.PHONY: installer
|
.PHONY: installer
|
||||||
installer:
|
installer:
|
||||||
cd "$(CHECKOUTS_DIRECTORY)/talos" && \
|
cd "$(CHECKOUTS_DIRECTORY)/talos" && \
|
||||||
$(MAKE) \
|
$(MAKE) \
|
||||||
REGISTRY=$(REGISTRY) USERNAME=$(REGISTRY_USERNAME) PUSH=true \
|
REGISTRY=$(REGISTRY) USERNAME=$(REGISTRY_USERNAME) \
|
||||||
PKG_KERNEL=$(REGISTRY)/$(REGISTRY_USERNAME)/kernel:$(PKGS_TAG) \
|
PKG_KERNEL=$(KERNEL_IMAGE):$(PKGS_TAG) \
|
||||||
INSTALLER_ARCH=arm64 PLATFORM=linux/arm64 \
|
INSTALLER_ARCH=arm64 PLATFORM=linux/arm64 \
|
||||||
IMAGER_ARGS="--overlay-name=rpi5 --overlay-image=$(REGISTRY)/$(REGISTRY_USERNAME)/sbc-raspberrypi5:$(SBCOVERLAY_TAG) $(EXTENSION_FLAGS)" \
|
kernel initramfs && \
|
||||||
kernel initramfs imager installer-base installer && \
|
$(MAKE) \
|
||||||
|
REGISTRY=$(REGISTRY) USERNAME=$(REGISTRY_USERNAME) \
|
||||||
|
PKG_KERNEL=$(KERNEL_IMAGE):$(PKGS_TAG) \
|
||||||
|
INSTALLER_ARCH=arm64 PLATFORM=linux/arm64 \
|
||||||
|
target-imager \
|
||||||
|
TARGET_ARGS="--output type=image,name=$(IMAGER_IMAGE):$(TALOS_TAG),push=true" && \
|
||||||
|
$(MAKE) \
|
||||||
|
REGISTRY=$(REGISTRY) USERNAME=$(REGISTRY_USERNAME) \
|
||||||
|
PKG_KERNEL=$(KERNEL_IMAGE):$(PKGS_TAG) \
|
||||||
|
INSTALLER_ARCH=arm64 PLATFORM=linux/arm64 \
|
||||||
|
target-installer-base \
|
||||||
|
TARGET_ARGS="--output type=image,name=$(INSTALLER_IMAGE):base-$(TALOS_TAG),push=true" && \
|
||||||
|
docker pull $(IMAGER_IMAGE):$(TALOS_TAG) && \
|
||||||
|
docker run --rm -t -v ./_out:/out --privileged --network=host \
|
||||||
|
$(IMAGER_IMAGE):$(TALOS_TAG) \
|
||||||
|
installer --arch arm64 \
|
||||||
|
--base-installer-image="$(INSTALLER_IMAGE):base-$(TALOS_TAG)" \
|
||||||
|
$(IMAGER_COMMON_FLAGS) && \
|
||||||
|
crane push ./_out/installer-arm64.tar $(INSTALLER_IMAGE):$(TALOS_TAG) && \
|
||||||
docker \
|
docker \
|
||||||
run --rm -t -v ./_out:/out -v /dev:/dev --privileged \
|
run --rm -t -v ./_out:/out -v /dev:/dev --privileged \
|
||||||
$(REGISTRY)/$(REGISTRY_USERNAME)/imager:$(TALOS_TAG) \
|
$(IMAGER_IMAGE):$(TALOS_TAG) \
|
||||||
metal --arch arm64 \
|
metal --arch arm64 \
|
||||||
--base-installer-image="$(REGISTRY)/$(REGISTRY_USERNAME)/installer:$(TALOS_TAG)" \
|
--base-installer-image="$(INSTALLER_IMAGE):$(TALOS_TAG)" \
|
||||||
--overlay-name="rpi5" \
|
$(IMAGER_COMMON_FLAGS)
|
||||||
--overlay-image="$(REGISTRY)/$(REGISTRY_USERNAME)/sbc-raspberrypi5:$(SBCOVERLAY_TAG)" \
|
|
||||||
--overlay-option="configTxtAppend=$$(cat $(PWD)/config/config.txt.append)" \
|
|
||||||
$(EXTENSION_FLAGS)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Release — tag images with the Git tag for stable references
|
# Release — tag images with the Git tag for stable references
|
||||||
#
|
#
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
release:
|
release:
|
||||||
docker pull $(REGISTRY)/$(REGISTRY_USERNAME)/installer:$(TALOS_TAG) && \
|
docker pull $(INSTALLER_IMAGE):$(TALOS_TAG) && \
|
||||||
docker tag $(REGISTRY)/$(REGISTRY_USERNAME)/installer:$(TALOS_TAG) $(REGISTRY)/$(REGISTRY_USERNAME)/$(IMAGE_NAME):$(TAG) && \
|
docker tag $(INSTALLER_IMAGE):$(TALOS_TAG) $(REGISTRY)/$(REGISTRY_USERNAME)/$(IMAGE_NAME):$(TAG) && \
|
||||||
docker push $(REGISTRY)/$(REGISTRY_USERNAME)/$(IMAGE_NAME):$(TAG)
|
docker push $(REGISTRY)/$(REGISTRY_USERNAME)/$(IMAGE_NAME):$(TAG)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Scout — Docker Scout CVE scan on all pushed images
|
||||||
|
#
|
||||||
|
SCOUT_REPORT := _out/scout-report.md
|
||||||
|
SCOUT_IMAGES := \
|
||||||
|
$(KERNEL_IMAGE):$(PKGS_TAG) \
|
||||||
|
$(OVERLAY_IMAGE):$(SBCOVERLAY_TAG) \
|
||||||
|
$(IMAGER_IMAGE):$(TALOS_TAG) \
|
||||||
|
$(INSTALLER_IMAGE):base-$(TALOS_TAG) \
|
||||||
|
$(INSTALLER_IMAGE):$(TALOS_TAG)
|
||||||
|
|
||||||
|
.PHONY: scout
|
||||||
|
scout:
|
||||||
|
@mkdir -p _out
|
||||||
|
@if ! docker scout version >/dev/null 2>&1; then \
|
||||||
|
echo "Docker Scout not available -- skipping CVE scan." > $(SCOUT_REPORT); \
|
||||||
|
exit 0; \
|
||||||
|
fi
|
||||||
|
@echo "# Docker Scout CVE Summary" > $(SCOUT_REPORT)
|
||||||
|
@echo "" >> $(SCOUT_REPORT)
|
||||||
|
@for image in $(SCOUT_IMAGES); do \
|
||||||
|
echo "Scanning $$image ..."; \
|
||||||
|
echo "### $${image##*/}" >> $(SCOUT_REPORT); \
|
||||||
|
echo '```' >> $(SCOUT_REPORT); \
|
||||||
|
docker scout quickview "$$image" --platform linux/arm64 2>&1 >> $(SCOUT_REPORT) || \
|
||||||
|
echo "Scout scan failed for $$image" >> $(SCOUT_REPORT); \
|
||||||
|
echo '```' >> $(SCOUT_REPORT); \
|
||||||
|
echo "" >> $(SCOUT_REPORT); \
|
||||||
|
done
|
||||||
|
@echo "Scout report written to $(SCOUT_REPORT)"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Clean
|
# Clean
|
||||||
#
|
#
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean: checkouts-clean
|
clean: checkouts-clean
|
||||||
|
rm -rf _out
|
||||||
rm -rf checkouts/_out
|
rm -rf checkouts/_out
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user