Skip to content

fix(ci): add workflow_dispatch to execute-release; fix if guard #1140

fix(ci): add workflow_dispatch to execute-release; fix if guard

fix(ci): add workflow_dispatch to execute-release; fix if guard #1140

Workflow file for this run

name: Build Bluefin dakota
on:
pull_request:
branches: [main, next, testing]
merge_group:
branches: [main, next, testing]
push:
branches: [main, next]
workflow_dispatch:
# WARNING: Do not manually dispatch immediately after auto/track-* ref bumps
# (e.g. Renovate PRs updating gnome-build-meta.bst). Cold builds of GNOME
# require gbm.gnome.org to have built the new ref first — dispatch too early
# and you get a cold build that times out.
permissions: read-all
env:
IMAGE_NAME: dakota
IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
# Concurrency: per-ref isolation for all events.
# - PRs: cancel-in-progress: true drops stale validate runs when a new
# push arrives. Safe for other events — merge_group/schedule/dispatch
# each use distinct refs and are unaffected by this flag.
# - merge_group / schedule / dispatch: per-ref queuing, never cancelled.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
# ── Fast PR validation ───────────────────────────────────────────────────
# Fires only on pull_request. Runs bst show on the full element graph for
# both variants. Zero remote-execution — does not touch cache.projectbluefin.io.
# Expected runtime: <15 min (BST cache hit), <30 min (cold start).
validate:
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04
timeout-minutes: 30
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-validate-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check bst2 image pin consistency
uses: ./.github/actions/check-bst2-pin
- name: Setup Just
uses: taiki-e/install-action@873c7452cadb7c034694a1282227095d93fbdf92 # v2
with:
tool: just
# Cache the BST workspace (junction git sources + bst2 container layers).
# Key includes junction element refs so junction bumps start fresh.
# Without this, bst show must clone gnome-build-meta + freedesktop-sdk
# from scratch on every PR run (~15-25 min extra).
- name: Restore BST cache
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: ~/.cache/buildstream
key: bst-show-${{ github.base_ref || github.ref_name }}-${{ hashFiles('elements/gnome-build-meta.bst', 'elements/freedesktop-sdk.bst', 'Justfile') }}
restore-keys: |
bst-show-${{ github.base_ref || github.ref_name }}-
bst-show-
- name: Validate BST element graph (default)
env:
BST_FLAGS: -o x86_64_v3 true --no-interactive
run: just bst show --deps all oci/bluefin.bst
- name: Validate BST element graph (nvidia)
env:
BST_FLAGS: -o x86_64_v3 true --no-interactive
run: just bst show --deps all oci/bluefin-nvidia.bst
# ── Full OCI build ────────────────────────────────────────────────────────
# Fires on merge_group, schedule, and workflow_dispatch — NOT on pull_request.
# PRs are validated by the validate job above; the full build is the
# merge-queue gate. This keeps cache.projectbluefin.io free from PR traffic.
build:
if: github.event_name != 'pull_request'
runs-on: ubuntu-24.04
timeout-minutes: 360
# Both variants build in parallel. NVIDIA is continue-on-error so its
# failure does not block the default image's merge or publication.
strategy:
fail-fast: false
max-parallel: 2
matrix:
include:
- variant: default
element: oci/bluefin.bst
image_suffix: ''
publish: true
continue: false
- variant: nvidia
element: oci/bluefin-nvidia.bst
image_suffix: '-nvidia'
publish: true
continue: true
continue-on-error: ${{ matrix.continue }}
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check bst2 image pin consistency
uses: ./.github/actions/check-bst2-pin
# FIXME: Make the build with JWT work
# - name: Get JWT token
# previously used actions/github-script (kept disabled)
# with:
# script: |
# const fs = require('fs');
# const token = await core.getIDToken('cache.projectbluefin.io')
# fs.writeFileSync('bluefin.token', token, { mode: 0o600 });
- name: Capture build timestamp
id: timestamp
run: echo "created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT"
# ── Disk and storage setup ────────────────────────────────────────
# Runs before any podman call (BST uses rootful podman to pull bst2;
# storage backend must be stable before first use).
# update-podman: true — newer podman from Ubuntu resolute for bst2 pull.
# Note: setup-runner btrfs does not pass loopback-free; watch for disk
# pressure and upstream the option if needed.
- name: Setup runner
uses: projectbluefin/actions/bootc-build/setup-runner@2a09e72e9be15b137392dde15f8587f35587e8eb # v1.1.0
with:
storage-backend: btrfs
update-podman: true
install-tools: '["just"]'
# ── Generate CI-specific BuildStream config ───────────────────────
# Tuned per gnome-build-meta CI patterns:
# - on-error: continue -> find ALL failures, don't stop at first
# - fetchers: 32 -> parallel downloads from upstream caches
# - builders: 4 -> Concurrent builds are controlled in the casd server
# - retry-failed: True -> auto-retry flaky builds
# - error-lines: 80 -> generous error context in logs
# - cache-buildtrees: never -> save disk (we only need final artifacts)
#
- name: Generate BuildStream CI config
env:
CASD_CLIENT_CERT: ${{ vars.CASD_CLIENT_CERT }}
CASD_CLIENT_KEY: ${{ secrets.CASD_CLIENT_KEY }}
uses: ./.github/actions/generate-bst-ci-config
with:
enable-remote-execution: 'true'
# ── BuildStream build ─────────────────────────────────────────────
# Uses the Justfile's `bst` wrapper to run BuildStream inside the
# bst2 container. CI-specific flags (--no-interactive, --config)
# are injected via BST_FLAGS env var.
- name: Build OCI image with BuildStream
env:
BST_FLAGS: -o x86_64_v3 true --no-interactive --config /src/buildstream-ci.conf
run: |
just bst build ${{ matrix.element }}
timeout-minutes: 330
# Push the built artifact to the remote CAS so the export job can pull it.
# Remote execution may populate the artifact cache implicitly, but an
# explicit push guarantees the artifact is there regardless of BST internals.
# Push both variants so publish.yml can fetch each from CAS.
- name: Push OCI artifact to remote CAS
env:
BST_FLAGS: -o x86_64_v3 true --no-interactive --config /src/buildstream-ci.conf
run: |
just bst artifact push --deps none ${{ matrix.element }}
# ── Upload build logs ─────────────────────────────────────────────
# Always upload, even on failure, so build failures can be diagnosed.
- name: Upload build logs
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: buildstream-logs-x86_64-${{ matrix.variant }}
path: logs/
retention-days: 7
if-no-files-found: ignore
# ── aarch64 native build ──────────────────────────────────────────────────
# Mirrors the x86_64 build job. ARM failures do not fail the workflow or
# block x86_64 publication — this is an experimental parallel build.
# Only runs on the daily cron and manual dispatch — not on PRs or merge
# queue — to avoid burning ARM runner time on code that nobody is using yet.
# WebKit aarch64 artifacts are available from gbm.gnome.org (gnome-build-meta
# builds aarch64 natively), so cold-build OOM/timeout should no longer occur.
build-aarch64:
if: false # temporarily disabled — aarch64 needs further investigation
runs-on: ubuntu-24.04-arm
continue-on-error: true
outputs:
pushed: ${{ steps.push-aarch64.outputs.pushed }}
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup runner
uses: projectbluefin/actions/bootc-build/setup-runner@2a09e72e9be15b137392dde15f8587f35587e8eb # v1.1.0
with:
storage-backend: btrfs
update-podman: true
install-tools: '["just"]'
- name: Capture build timestamp
id: timestamp
run: echo "created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT"
- name: Generate BuildStream CI config
env:
CASD_CLIENT_CERT: ${{ vars.CASD_CLIENT_CERT }}
CASD_CLIENT_KEY: ${{ secrets.CASD_CLIENT_KEY }}
uses: ./.github/actions/generate-bst-ci-config
with:
enable-remote-execution: 'false'
- name: Build OCI image with BuildStream (aarch64)
env:
BST_FLAGS: --no-interactive --config /src/buildstream-ci.conf --option arch aarch64
run: |
just bst build oci/bluefin.bst
timeout-minutes: 420
- name: Export OCI image from BuildStream
id: export
env:
BST_FLAGS: --no-interactive --config /src/buildstream-ci.conf --option arch aarch64
BUILD_IMAGE_NAME: ${{ env.IMAGE_NAME }}
OCI_IMAGE_CREATED: ${{ steps.timestamp.outputs.created }}
OCI_IMAGE_REVISION: ${{ github.sha }}
OCI_IMAGE_VERSION: aarch64
run: |
just export
echo "image_ref=${{ env.IMAGE_NAME }}:aarch64" >> "$GITHUB_OUTPUT"
- name: Verify image loaded
run: sudo podman images
- name: Validate with bootc container lint
run: |
just lint
- name: Upload build logs
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: buildstream-logs-aarch64
path: logs/
retention-days: 7
if-no-files-found: ignore
- name: Login to GHCR
if: >-
github.event_name == 'merge_group' ||
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch'
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | \
sudo podman login ghcr.io --username ${{ github.actor }} --password-stdin
- name: Tag image for GHCR
if: >-
github.event_name == 'merge_group' ||
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch'
run: |
sudo podman tag "localhost/${{ steps.export.outputs.image_ref }}" \
"${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:aarch64"
sudo podman tag "localhost/${{ steps.export.outputs.image_ref }}" \
"${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:aarch64-${{ github.sha }}"
- name: Push to GHCR
id: push-aarch64
if: >-
github.event_name == 'merge_group' ||
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch'
run: |
for tag in aarch64 "aarch64-${{ github.sha }}"; do
for i in 1 2 3; do
# Plain zstd required — see x86_64 push step comment above.
sudo podman push --compression-format=zstd \
"${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${tag}" && break
echo "Push attempt $i failed for tag ${tag}, retrying..."
sleep 5
done
done
echo "pushed=true" >> "$GITHUB_OUTPUT"
# ── Multi-arch manifest ───────────────────────────────────────────────────
# Combines :latest (x86_64) and :aarch64 into a single multi-arch manifest.
# Only runs when :aarch64 was actually pushed this run (not just when the
# job completed — continue-on-error makes needs.result == 'success' even on
# failure, so we gate on the step output instead).
# ARM failures skip this job without affecting x86_64 publication.
create-manifest:
runs-on: ubuntu-24.04
needs: [build, build-aarch64]
if: >-
(github.event_name == 'merge_group' ||
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch') &&
needs.build-aarch64.outputs.pushed == 'true'
permissions:
packages: write
steps:
- name: Login to GHCR
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | \
sudo podman login ghcr.io --username ${{ github.actor }} --password-stdin
- name: Create and push multi-arch manifest
run: |
sudo podman manifest create "${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:latest" \
"${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:latest" \
"${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:aarch64"
sudo podman manifest push "${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:latest"