diff --git a/.gitea/workflows/build-image.yaml b/.gitea/workflows/build-image.yaml index f718323..5ad4be2 100644 --- a/.gitea/workflows/build-image.yaml +++ b/.gitea/workflows/build-image.yaml @@ -13,35 +13,21 @@ on: default: minimal options: [minimal, workstation, both] -jobs: - # Which variants to build. Pushes and PRs build minimal only — it is the fast - # one and it exercises the entire pipeline. Tags build everything. - prepare: - runs-on: metal - outputs: - variants: ${{ steps.pick.outputs.variants }} - steps: - - id: pick - run: | - if [ "${{ startsWith(github.ref, 'refs/tags/') }}" = "true" ]; then - variants='["minimal","workstation"]' - else - case "${{ inputs.variant }}" in - both) variants='["minimal","workstation"]' ;; - workstation) variants='["workstation"]' ;; - *) variants='["minimal"]' ;; - esac - fi - echo "variants=$variants" | tee -a "$GITHUB_OUTPUT" +# Deliberately no strategy.matrix here. +# +# The obvious shape for this is a `prepare` job emitting a JSON list and a +# matrix built from `fromJSON(needs.prepare.outputs.variants)`. Gitea's runner +# evaluates strategy.matrix when it plans the workflow — before `needs` has run +# — so that expression resolves to an empty string and you get exactly one job +# leg with an empty variant. The prepare job succeeds and sets its output +# correctly; the matrix simply never sees it. +# +# Looping in shell is less elegant and entirely reliable. +jobs: build: - needs: prepare runs-on: metal timeout-minutes: 600 - strategy: - fail-fast: false - matrix: - variant: ${{ fromJSON(needs.prepare.outputs.variants) }} steps: - uses: actions/checkout@v4 @@ -79,39 +65,65 @@ jobs: # that has not built before starts cold. - name: Prepare persistent build state run: | - echo "CACHE_DIR=/var/tmp/c630-build/dnf" >> "$GITHUB_ENV" - echo "WORK_DIR=/var/tmp/c630-build/work" >> "$GITHUB_ENV" - mkdir -p /var/tmp/c630-build/{dnf,work} + echo "CACHE_DIR=/var/tmp/c630-build/dnf" >> "$GITHUB_ENV" + echo "WORK_DIR=/var/tmp/c630-build/work" >> "$GITHUB_ENV" + mkdir -p /var/tmp/c630-build/dnf /var/tmp/c630-build/work # Keep it bounded: drop cached rpms nothing has touched in a month. find /var/tmp/c630-build/dnf -type f -atime +30 -delete 2>/dev/null || true du -sh /var/tmp/c630-build/* 2>/dev/null || true + - name: Select variants + run: | + if [ "${{ startsWith(github.ref, 'refs/tags/') }}" = "true" ]; then + variants="minimal workstation" + else + case "${{ inputs.variant }}" in + both) variants="minimal workstation" ;; + workstation) variants="workstation" ;; + *) variants="minimal" ;; + esac + fi + echo "VARIANTS=$variants" | tee -a "$GITHUB_ENV" + - name: Build run: | - case "${{ matrix.variant }}" in - workstation) size=16384 ;; - *) size=8192 ;; - esac - # No --fresh: the stamp in stage2.sh hashes the package lists, so a - # change there invalidates the staged base on its own. Checkout is - # shallow here anyway, so diffing against HEAD~1 would not be reliable. - ./build/build-image.sh \ - --variant "${{ matrix.variant }}" \ - --size "$size" \ - --cache "$CACHE_DIR" \ - --work "$WORK_DIR" + rc=0 + for variant in $VARIANTS; do + case "$variant" in + workstation) size=16384 ;; + *) size=8192 ;; + esac + echo "::group::build $variant (${size} MiB)" + # No --fresh: the stamp in stage2.sh hashes the package lists, so a + # change there invalidates the staged base on its own. + if ./build/build-image.sh \ + --variant "$variant" \ + --size "$size" \ + --cache "$CACHE_DIR" \ + --work "$WORK_DIR"; then + echo "$variant ok" + else + echo "::error::build failed for $variant" + rc=1 + fi + echo "::endgroup::" + done + exit $rc - name: Checksums - run: cat output/*.sha256 + if: always() + run: cat output/*.sha256 2>/dev/null || echo "no images produced" - uses: actions/upload-artifact@v4 + if: always() with: - name: fedora-${{ matrix.variant }}-lenovo-yoga-c630 + name: fedora-lenovo-yoga-c630 path: | output/*.img.zst output/*.sha256 retention-days: 14 compression-level: 0 # already zstd + if-no-files-found: warn - name: Attach to release if: startsWith(github.ref, 'refs/tags/')