name: Build containers on: workflow_dispatch: inputs: image: description: Image to build type: choice options: [all, fedora-cosmic, fedora-remote, fedora-intune] default: all pull_request: branches: ["main"] push: branches: ["main"] schedule: # Weekly, Mondays 04:00 UTC. - cron: "0 4 * * 1" jobs: # Work out which images actually changed, so a push only rebuilds those. changes: name: Compute changes runs-on: job-v2 # The runner has no git: without it actions/checkout falls back to a # tarball with no history, `git diff` fails and every image is rebuilt. container: image: "quay.io/fedora-ostree-desktops/buildroot:44" outputs: cosmic: ${{ steps.changes.outputs.cosmic }} remote: ${{ steps.changes.outputs.remote }} intune: ${{ steps.changes.outputs.intune }} steps: - name: Install tools run: dnf install -y nodejs git - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Detect changed images id: changes shell: bash env: EVENT: ${{ github.event_name }} BEFORE: ${{ github.event.before }} SHA: ${{ github.sha }} BASE_REF: ${{ github.base_ref }} DISPATCH_IMAGE: ${{ inputs.image }} run: | set -euo pipefail # Diff the event's commits; any failure rebuilds everything, but # say so instead of hiding it. diff_or_all() { if ! changed="$(git diff --name-only "$@")"; then echo "::warning::git diff $* failed; rebuilding every image" changed="" elif [[ -z "${changed}" ]]; then # Nothing changed (e.g. an empty merge): build nothing rather # than everything. changed="(none)" fi } case "${EVENT}" in push) if [[ -n "${BEFORE}" && "${BEFORE}" != 0000000000000000000000000000000000000000 ]]; then diff_or_all "${BEFORE}" "${SHA}" else echo "::warning::push without a previous commit; rebuilding every image" changed="" fi ;; pull_request) diff_or_all "origin/${BASE_REF}...HEAD" ;; workflow_dispatch) # Pretend the chosen image's directory changed; "all" (or no # input) rebuilds everything. if [[ -n "${DISPATCH_IMAGE}" && "${DISPATCH_IMAGE}" != all ]]; then changed="images/${DISPATCH_IMAGE}/" else changed="" fi ;; *) # schedule: the weekly rebuild picks up package updates for all. changed="" ;; esac printf 'Changed paths:\n%s\n' "${changed:-(all)}" eval "$(printf '%s\n' "${changed}" | ./ci-changes.sh)" echo "cosmic=${cosmic}" >> "$GITHUB_OUTPUT" echo "remote=${remote}" >> "$GITHUB_OUTPUT" echo "intune=${intune}" >> "$GITHUB_OUTPUT" build-cosmic: name: ${{ matrix.image }} (${{ matrix.distro }}) needs: changes if: needs.changes.outputs.cosmic == 'true' runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: include: - image: fedora-cosmic distro: "44" arch: x86_64 runner: job-v2 - image: fedora-cosmic distro: rawhide arch: x86_64 runner: job-v2 container: image: "quay.io/fedora-ostree-desktops/buildroot:${{ matrix.distro }}" options: "--security-opt=label=disable --privileged --user 0:0 --device=/dev/fuse --volume /:/run/host:rw" env: IMAGE: ${{ matrix.image }} DISTRO: ${{ matrix.distro }} ARCH: ${{ matrix.arch }} REGISTRY: git.plabble.org/misthios GITEA_URL: https://git.plabble.org GITEA_REPO: Misthios/bootc-images steps: &build_steps - name: Install build tools run: | set -xeuo pipefail dnf install -y nodejs jq curl git createrepo_c dnf install -y skopeo dnf install -y cosign || true if ! command -v cosign >/dev/null; then case "$(uname -m)" in x86_64) cosign_arch=amd64 ;; aarch64) cosign_arch=arm64 ;; *) echo "Unsupported arch for cosign"; exit 1 ;; esac curl -fsSL -o /usr/local/bin/cosign \ "https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-${cosign_arch}" chmod +x /usr/local/bin/cosign fi - name: Configure containers storage run: | if [ -f /usr/share/containers/storage.conf ]; then sed -i 's/driver = "overlay"/driver = "vfs"/' /usr/share/containers/storage.conf fi - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Log in to registry # Only the push step needs it, and PR builds get no secrets. if: github.event_name != 'pull_request' env: REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | set -xeuo pipefail mkdir -p ~/.docker registry_host="${REGISTRY%%/*}" echo "${REGISTRY_TOKEN}" | skopeo login -u "${REGISTRY_USERNAME}" \ --password-stdin --authfile /tmp/auth.json "${registry_host}" echo "${REGISTRY_TOKEN}" | skopeo login -u "${REGISTRY_USERNAME}" \ --password-stdin --authfile ~/.docker/config.json "${registry_host}" - name: Build image env: KANIDM_UNIXD_TOKEN: ${{ secrets.KANIDM_UNIXD_TOKEN }} run: ./build.sh "${IMAGE}" "${DISTRO}" "${ARCH}" - name: Push and sign image if: github.event_name != 'pull_request' env: COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }} COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} run: | set -xeuo pipefail export STORAGE_DRIVER=vfs buildid="$(cat .buildid)" oci="build/${IMAGE}-${DISTRO}-${ARCH}/${IMAGE}-${DISTRO}-${ARCH}.ociarchive" tag="${DISTRO}.${buildid}" skopeo copy --authfile /tmp/auth.json \ "oci-archive:${oci}" "docker://${REGISTRY}/${IMAGE}:${tag}" skopeo copy --authfile /tmp/auth.json \ "oci-archive:${oci}" "docker://${REGISTRY}/${IMAGE}:${DISTRO}" printf '%s' "${COSIGN_PRIVATE_KEY}" | base64 -d > private.key cosign sign -y --key private.key "${REGISTRY}/${IMAGE}:${tag}" cosign sign -y --key private.key "${REGISTRY}/${IMAGE}:${DISTRO}" rm -f private.key - name: Generate changelog and publish release if: github.event_name != 'pull_request' env: RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} run: | buildid="$(cat .buildid)" pkgs="build/${IMAGE}-${DISTRO}-${ARCH}/packages-current.txt" ./release.sh "${IMAGE}" "${DISTRO}" "${buildid}" "${pkgs}" build-remote: name: fedora-remote (44) needs: changes if: needs.changes.outputs.remote == 'true' runs-on: job-v2 container: image: "quay.io/fedora-ostree-desktops/buildroot:44" options: "--security-opt=label=disable --privileged --user 0:0 --device=/dev/fuse --volume /:/run/host:rw" env: IMAGE: fedora-remote DISTRO: "44" ARCH: x86_64 REGISTRY: git.plabble.org/misthios GITEA_URL: https://git.plabble.org GITEA_REPO: Misthios/bootc-images steps: *build_steps build-intune: name: fedora-intune (44) needs: changes if: needs.changes.outputs.intune == 'true' runs-on: job-v2 container: image: "quay.io/fedora-ostree-desktops/buildroot:44" options: "--security-opt=label=disable --privileged --user 0:0 --device=/dev/fuse --volume /:/run/host:rw" env: IMAGE: fedora-intune DISTRO: "44" ARCH: x86_64 REGISTRY: git.plabble.org/misthios GITEA_URL: https://git.plabble.org GITEA_REPO: Misthios/bootc-images steps: *build_steps prune: name: Prune old releases and tags runs-on: job-v2 needs: [changes, build-cosmic, build-remote, build-intune] # Run even if some builds were skipped or failed. if: ${{ always() && github.event_name != 'pull_request' }} container: image: "quay.io/fedora-ostree-desktops/buildroot:44" options: "--security-opt=label=disable --privileged --user 0:0" env: GITEA_URL: https://git.plabble.org GITEA_REPO: Misthios/bootc-images steps: - name: Install tools run: dnf install -y nodejs jq curl skopeo - name: Checkout uses: actions/checkout@v4 - name: Prune old releases env: RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} run: | for image in fedora-cosmic fedora-remote fedora-intune; do ./prune-releases.sh "${image}" done - name: Prune old registry tags env: REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | set -xeuo pipefail authfile=/tmp/prune-auth.json echo "${REGISTRY_TOKEN}" | skopeo login -u "${REGISTRY_USERNAME}" \ --password-stdin --authfile "${authfile}" git.plabble.org for image in fedora-cosmic fedora-remote fedora-intune; do AUTHFILE="${authfile}" ./prune-registry.sh "${image}" Misthios 44 rawhide done