ci: rebuild prop-base weekly to pull Debian security patches

Adds a Sunday 06:00 UTC schedule trigger to build-base.yaml plus a
CACHE_BUST=<ISO year+week> build-arg keyed off `date -u +%G-W%V`. The
apt RUN steps in Dockerfile.base reference the arg in their command
line so BuildKit's layer hash changes when the week rolls over,
forcing apt-get update + install to re-execute and pull fresh
security updates.

The wgrib2-builder stage doesn't see CACHE_BUST so the ~5-min wgrib2
compile keeps hitting layer cache across weeks; only the apt layers
rebuild. Effective cost of the weekly job: ~2 min for the cdo /
gdal-bin reinstall.
This commit is contained in:
Graham McIntire 2026-05-03 11:51:08 -05:00
parent dbd4a78502
commit 0711d9af11
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
2 changed files with 33 additions and 7 deletions

View file

@ -1,9 +1,13 @@
name: Build base image
# Path-filtered so this only fires when the base Dockerfile (or this
# workflow) changes — typically a wgrib2 / g2c version bump or apt-dep
# tweak. `workflow_dispatch` lets us rebuild on demand without touching
# the file (e.g. to refresh CVE patches in the apt layer).
# Path-filtered so it fires when the base Dockerfile (or this workflow)
# changes, weekly via cron so Debian security updates land without us
# remembering to bump anything, and on-demand via workflow_dispatch.
#
# The weekly cron passes CACHE_BUST=<ISO week> as a build-arg so the
# apt layers in Dockerfile.base re-execute (otherwise BuildKit's layer
# cache would short-circuit `apt-get update` on a deterministic input
# and silently skip security patches).
on:
push:
branches:
@ -11,6 +15,11 @@ on:
paths:
- 'Dockerfile.base'
- '.forgejo/workflows/build-base.yaml'
schedule:
# Sundays 06:00 UTC — runs on a quiet day-of-week so a long base
# rebuild doesn't collide with mid-week deploys, and matches the
# cadence that Debian security advisories typically aggregate at.
- cron: '0 6 * * 0'
workflow_dispatch:
env:
@ -106,12 +115,19 @@ jobs:
run: |
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
TAG="${{ steps.tag.outputs.tag }}"
# ISO year+week (e.g. 2026-W18). Same value all week, so a
# cron-triggered rebuild on day 1 vs day 7 reuses the layer
# cache; the next ISO week boundary forces apt-get update +
# install to re-execute and pull fresh security patches.
CACHE_BUST=$(date -u +%G-W%V)
echo "CACHE_BUST=${CACHE_BUST}"
attempt=1
max_attempts=3
while : ; do
if docker buildx build \
-f Dockerfile.base \
--build-arg CACHE_BUST="${CACHE_BUST}" \
-t "${IMAGE}:${TAG}" \
-t "${IMAGE}:latest" \
--push \

View file

@ -70,12 +70,21 @@ RUN wget -q --content-disposition "https://github.com/NOAA-EMC/wgrib2/archive/re
# ---- Final runtime base ----
FROM ${RUNNER_IMAGE} AS base
# Weekly cron passes CACHE_BUST=<iso year+week> so the apt layers below
# re-execute and pick up Debian security patches. Source-controlled
# pushes leave the value at its `none` default, so day-to-day base
# rebuilds (Dockerfile.base edits) don't pay the apt-update cost
# unless the week has rolled over.
ARG CACHE_BUST=none
# Runtime apt deps. cdo + gdal-bin are split into a second RUN so a
# transient cdo install failure doesn't invalidate the smaller base
# layer above.
# layer above. Referencing `${CACHE_BUST}` in the RUN line changes the
# layer hash week-to-week without altering the install set.
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
rm -f /etc/apt/apt.conf.d/docker-clean \
echo "cache-bust=${CACHE_BUST}" \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
libstdc++6 openssl libncurses6 locales ca-certificates snmp \
@ -83,7 +92,8 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
rm -f /etc/apt/apt.conf.d/docker-clean \
echo "cache-bust=${CACHE_BUST}" \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
&& apt-get update \
&& apt-get install -y --no-install-recommends cdo gdal-bin