From fdc1441c32928be4f1a5bbec5459a948b7abd822 Mon Sep 17 00:00:00 2001 From: Wesley van Tilburg Date: Sun, 27 Sep 2026 22:59:02 +0200 Subject: [PATCH] ci: only rebuild images whose files changed Add a changes job that diffs the pushed range (or PR base) and emits a matrix via ci-matrix.sh. Shared files or build tooling changes rebuild all images. Also fix the upstream package trim to drop top-level keys left empty (e.g. packages-x86_64 when every entry is excluded), which broke fedora-remote. --- .gitea/workflows/build.yaml | 53 +++++++++++++++++++++++-------------- build.sh | 21 ++++++++++++++- ci-matrix.sh | 33 +++++++++++++++++++++++ 3 files changed, 86 insertions(+), 21 deletions(-) create mode 100755 ci-matrix.sh diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index b129dd1..cdc7a16 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -11,28 +11,42 @@ on: - cron: "0 4 * * 1" jobs: + # Work out which images actually changed, so a push only rebuilds those. + changes: + name: Compute build matrix + runs-on: job-v2 + outputs: + matrix: ${{ steps.matrix.outputs.matrix }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Compute matrix + id: matrix + shell: bash + run: | + set -euo pipefail + if [[ "${{ github.event_name }}" == "push" \ + && -n "${{ github.event.before }}" \ + && "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]]; then + changed="$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}" || true)" + elif [[ "${{ github.event_name }}" == "pull_request" ]]; then + changed="$(git diff --name-only "origin/${{ github.base_ref }}...HEAD" || true)" + else + changed="" + fi + matrix="$(printf '%s\n' "${changed}" | ./ci-matrix.sh)" + echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" + build: name: ${{ matrix.image }} (${{ matrix.distro }}) + needs: changes runs-on: ${{ matrix.runner }} strategy: fail-fast: false - # To build another image, add images//{manifest.yaml,build.conf} - # and a matching matrix entry here. - matrix: - include: - - image: fedora-cosmic - distro: "44" - arch: x86_64 - runner: job-v2 - - image: fedora-cosmic - distro: rawhide - arch: x86_64 - runner: job-v2 - - image: fedora-remote - distro: "44" - arch: x86_64 - runner: job-v2 + matrix: ${{ fromJson(needs.changes.outputs.matrix) }} container: image: "quay.io/fedora-ostree-desktops/buildroot:${{ matrix.distro }}" @@ -125,11 +139,10 @@ jobs: ./release.sh "${IMAGE}" "${DISTRO}" "${buildid}" "${pkgs}" prune: - name: Prune old releases + name: Prune old releases and tags runs-on: job-v2 - needs: build - # Run even if some matrix builds failed (e.g. rawhide churn), so their old - # releases still get cleaned up. + needs: [changes, build] + # Run even if some matrix builds failed (e.g. rawhide churn). if: ${{ always() && github.event_name != 'pull_request' }} container: image: "quay.io/fedora-ostree-desktops/buildroot:44" diff --git a/build.sh b/build.sh index f126bec..feaa812 100755 --- a/build.sh +++ b/build.sh @@ -111,7 +111,26 @@ trim_upstream_packages() { print } ' "${blocklist}" "${f}" > "${f}.tmp" - mv "${f}.tmp" "${f}" + # Drop top-level keys that were left with no list items (e.g. if every + # entry under packages-x86_64: was removed). + awk ' + { lines[NR] = $0 } + END { + for (i = 1; i <= NR; i++) { + if (lines[i] ~ /^[A-Za-z0-9_.-]+:$/) { + keep = 0 + for (j = i + 1; j <= NR; j++) { + if (lines[j] ~ /^[[:space:]]+-[[:space:]]/) { keep = 1; break } + if (lines[j] ~ /^[A-Za-z0-9_.-]+:/) break + } + if (!keep) continue + } + print lines[i] + } + } + ' "${f}.tmp" > "${f}.tmp2" + mv "${f}.tmp2" "${f}" + rm -f "${f}.tmp" done } diff --git a/ci-matrix.sh b/ci-matrix.sh new file mode 100755 index 0000000..30e34db --- /dev/null +++ b/ci-matrix.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Print the CI build matrix (JSON) for the images affected by the paths on +# stdin (one per line). Any change to shared files or the build tooling +# rebuilds every image. Empty input (e.g. schedule/manual runs) rebuilds all. +set -euo pipefail + +changed="$(cat || true)" + +all=0 +[[ -z "${changed}" ]] && all=1 +grep -qE '^(build\.sh|release\.sh|prune-releases\.sh|prune-registry\.sh|ci-matrix\.sh|\.gitea/)' <<< "${changed}" && all=1 +grep -qE '^images/shared/' <<< "${changed}" && all=1 + +cosmic=0 +remote=0 +if [[ "${all}" == 1 ]]; then + cosmic=1 + remote=1 +fi +grep -qE '^images/fedora-cosmic/' <<< "${changed}" && cosmic=1 +grep -qE '^images/fedora-remote/' <<< "${changed}" && remote=1 + +entries=() +if [[ "${cosmic}" == 1 ]]; then + entries+=('{"image":"fedora-cosmic","distro":"44","arch":"x86_64","runner":"job-v2"}') + entries+=('{"image":"fedora-cosmic","distro":"rawhide","arch":"x86_64","runner":"job-v2"}') +fi +if [[ "${remote}" == 1 ]]; then + entries+=('{"image":"fedora-remote","distro":"44","arch":"x86_64","runner":"job-v2"}') +fi + +joined="$(IFS=,; printf '%s' "${entries[*]:-}")" +printf '{"include":[%s]}\n' "${joined}"