--- name: Build container image on: push: branches: - main - testing - testing-candidate #schedule: # - cron: '05 10 * * *' # 10:05am UTC everyday workflow_dispatch: inputs: handwritten: description: "Small changelog about changes in this build" required: false type: string env: IMAGE_REGISTRY: "ghcr.io/${{ github.repository_owner }}" # do not edit IMAGE_NAME: ${{ vars.IMAGE_NAME || github.event.repository.name }} REPO_ORGANIZATION: ${{ vars.REPO_ORGANIZATION || github.repository_owner }} IMAGE_DESC: ${{ vars.IMAGE_DESC || 'AeroCore customized Bazzite Deck image' }} IMAGE_KEYWORDS: ${{ vars.IMAGE_KEYWORDS || 'bootc,oci,linux,bazzite,steam-deck,aerocore' }} IMAGE_LOGO_URL: ${{ vars.IMAGE_LOGO_URL || 'https://avatars.githubusercontent.com/u/120078124?s=200&v=4' }} DEFAULT_TAG: ${{ vars.DEFAULT_TAG || 'stable' }} BIB_IMAGE: ${{ vars.BIB_IMAGE || 'quay.io/centos-bootc/bootc-image-builder:latest' }} BASE_IMAGE: ${{ vars.BASE_IMAGE || 'ghcr.io/ublue-os/bazzite-deck:stable-44.20261012' }} FLATPAK_REMOTE_URL: ${{ vars.FLATPAK_REMOTE_URL }} HOMEBREW_BOTTLE_DOMAIN: ${{ vars.HOMEBREW_BOTTLE_DOMAIN }} HOMEBREW_API_DOMAIN: ${{ vars.HOMEBREW_API_DOMAIN }} OSTREE_IMAGE_REF: ${{ vars.OSTREE_IMAGE_REF }} concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} cancel-in-progress: true jobs: build_push: name: Build and push image runs-on: ubuntu-24.04 outputs: release_tag: ${{ steps.gen-version.outputs.release_tag }} permissions: contents: read packages: write id-token: write steps: # These stage versions are pinned by https://github.com/renovatebot/renovate - name: Show disk space run: sudo df -h - name: Maximize build space uses: ublue-os/remove-unwanted-software@695eb75bc387dbcd9685a8e72d23439d8686cba6 with: extra-squeeze: true - name: Check if /mnt is there id: check-mnt run: | if sudo mountpoint /mnt; then echo "mnt_is_there=1" >> "$GITHUB_OUTPUT" else echo "mnt_is_there=0" >> "$GITHUB_OUTPUT" fi - name: Mount BTRFS for podman storage if: ${{ steps.check-mnt.outputs.mnt_is_there == '1' }} uses: ublue-os/container-storage-action@main with: target-dir: /var/lib/containers - name: Show available build space run: sudo df -h - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - name: Install just uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 #v4.0.0 - name: Check Just Syntax shell: bash run: | just check - name: Image Name id: image-name run: | IMAGE_NAME=$(just image_name) echo "IMAGE_NAME=${IMAGE_NAME}" >> "$GITHUB_ENV" - name: Generate Version and Tags id: gen-version env: BASE_IMAGE: ${{ vars.BASE_IMAGE || 'ghcr.io/ublue-os/bazzite-deck:stable-44.20261012' }} run: | set -euo pipefail sudo podman pull "${BASE_IMAGE}" FEDORA_VERSION=$(sudo podman run --rm --entrypoint /usr/bin/rpm "${BASE_IMAGE}" -E %fedora) VERSION_BASE="${FEDORA_VERSION}.$(date +%Y%m%d)" if [[ "${GITHUB_REF_NAME}" == "testing-candidate" ]]; then DEFAULT_TAG="testing-candidate" VERSION_TAG="testing-candidate-${VERSION_BASE}" VERSION_PRETTY_PREFIX="Testing candidate" IMAGE_BRANCH="testing-candidate" elif [[ "${GITHUB_REF_NAME}" == "testing" ]]; then DEFAULT_TAG="testing" VERSION_TAG="testing-${VERSION_BASE}" VERSION_PRETTY_PREFIX="Testing" IMAGE_BRANCH="testing" else DEFAULT_TAG="stable" VERSION_TAG="${VERSION_BASE}" VERSION_PRETTY_PREFIX="Stable" IMAGE_BRANCH="stable" fi mapfile -t existing_tags < <(skopeo list-tags "docker://${IMAGE_REGISTRY,,}/${IMAGE_NAME,,}" 2>/dev/null | jq -r '.Tags[]' || true) if printf '%s\n' "${existing_tags[@]}" | grep -Fxq "${VERSION_TAG}"; then build=1 while printf '%s\n' "${existing_tags[@]}" | grep -Fxq "${VERSION_TAG}.${build}"; do ((build++)) done VERSION_TAG="${VERSION_TAG}.${build}" fi VERSION_BASE_PRETTY="${VERSION_TAG#testing-candidate-}" VERSION_BASE_PRETTY="${VERSION_BASE_PRETTY#testing-}" VERSION_PRETTY="${VERSION_PRETTY_PREFIX} (F${VERSION_BASE_PRETTY})" if [[ "${GITHUB_REF_NAME}" == "testing-candidate" ]]; then ALIAS_TAGS="${VERSION_TAG} testing-candidate testing-candidate-${FEDORA_VERSION}" elif [[ "${GITHUB_REF_NAME}" == "testing" ]]; then ALIAS_TAGS="${VERSION_TAG} testing testing-${FEDORA_VERSION}" else ALIAS_TAGS="${VERSION_TAG} stable-${VERSION_TAG} latest stable stable-${FEDORA_VERSION}" fi { echo "DEFAULT_TAG=${DEFAULT_TAG}" echo "IMAGE_BRANCH=${IMAGE_BRANCH}" echo "VERSION_TAG=${VERSION_TAG}" echo "VERSION_PRETTY=${VERSION_PRETTY}" echo "ALIAS_TAGS=${ALIAS_TAGS}" } >> "$GITHUB_ENV" echo "release_tag=${VERSION_TAG}" >> "$GITHUB_OUTPUT" - name: Prepare environment run: | # Lowercase the image uri https://github.com/macbre/push-to-ghcr/issues/12 echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}" >> "$GITHUB_ENV" echo "IMAGE_NAME=${IMAGE_NAME,,}" >> "$GITHUB_ENV" # This actually builds the container image - name: Build Image id: build-image env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BASE_IMAGE: ${{ vars.BASE_IMAGE || 'ghcr.io/ublue-os/bazzite-deck:stable-44.20261012' }} FLATPAK_REMOTE_URL: ${{ vars.FLATPAK_REMOTE_URL }} HOMEBREW_BOTTLE_DOMAIN: ${{ vars.HOMEBREW_BOTTLE_DOMAIN }} HOMEBREW_API_DOMAIN: ${{ vars.HOMEBREW_API_DOMAIN }} OSTREE_IMAGE_REF: ${{ vars.OSTREE_IMAGE_REF }} INSTRUMENTS_ENABLED: ${{ vars.INSTRUMENTS_ENABLED || 'true' }} INSTRUMENTS_RELEASE_REPOSITORY: ${{ vars.INSTRUMENTS_RELEASE_REPOSITORY || 'AeroCore-IO/booster-installer' }} INSTRUMENTS_VERSION: ${{ vars.INSTRUMENTS_VERSION || 'latest' }} INSTRUMENTS_RELEASE_API_BASE: ${{ vars.INSTRUMENTS_RELEASE_API_BASE || 'https://api.github.com' }} run: | GITHUB_TOKEN_FILE="${RUNNER_TEMP}/aerocore-build-github-token" umask 077 printf '%s' "${GITHUB_TOKEN}" > "${GITHUB_TOKEN_FILE}" trap 'rm -f "${GITHUB_TOKEN_FILE}"' EXIT sudo -E GITHUB_TOKEN_FILE="${GITHUB_TOKEN_FILE}" "$(command -v just)" build \ "${IMAGE_NAME}" \ "${DEFAULT_TAG}" # This is optional, this provides smaller delta updates - name: Rechunk with rpm-ostree id: rechunk run: | sudo -E "$(command -v just)" ostree-rechunk \ "${IMAGE_NAME}" \ "${DEFAULT_TAG}" # If you are feeling adventurous, use the new distro agnostic rechunker # https://github.com/coreos/chunkah # You can delete the Rechunk with rpm-ostree portion then if you use this #- name: Rechunk with Chunkah # id: rechunk # run: | # sudo -E $(command -v just) rechunk \ # ${IMAGE_NAME} \ # ${DEFAULT_TAG} - name: Generate Build Tags id: gen-build-tags run: | echo "Tags for this Action..." echo "${ALIAS_TAGS}" echo "alias_tags=${ALIAS_TAGS}" >> "$GITHUB_OUTPUT" - name: Tag Image id: tag-images env: ALIAS_TAGS: ${{ steps.gen-build-tags.outputs.alias_tags }} run: | sudo -E "$(command -v just)" tag-images \ "${IMAGE_NAME}" \ "${DEFAULT_TAG}" \ "${ALIAS_TAGS}" - name: Install Syft id: setup-syft if: github.event_name != 'pull_request' uses: anchore/sbom-action/download-syft@66cbf4bc1f1c0d2edc94016e65bc221b6bb0ad6c # v0.24.3 with: syft-version: v1.44.0 - name: Generate RPM SBOM id: generate-sbom if: github.event_name != 'pull_request' env: SYFT_CMD: ${{ steps.setup-syft.outputs.cmd }} run: | set -euo pipefail sbom="${RUNNER_TEMP}/aerocore-sbom.json" mountpoint="$(sudo podman image mount "${IMAGE_NAME}:${DEFAULT_TAG}")" trap 'sudo podman image unmount "${IMAGE_NAME}:${DEFAULT_TAG}"' EXIT sudo "${SYFT_CMD}" "dir:${mountpoint}" \ --select-catalogers rpm \ --source-name "${IMAGE_NAME}-${VERSION_TAG}" \ -o "syft-json=${sbom}" sudo chown "$(id -u):$(id -g)" "${sbom}" echo "sbom=${sbom}" >> "$GITHUB_OUTPUT" # These `if` statements keep pull requests from publishing packages. # They publish default-branch builds and manual testing branch builds. - name: Login to GitHub Container Registry uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 if: github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || github.ref_name == 'testing' || github.ref_name == 'testing-candidate') with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Push To GHCR if: github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || github.ref_name == 'testing' || github.ref_name == 'testing-candidate') id: push-image env: ALIAS_TAGS: ${{ steps.gen-build-tags.outputs.alias_tags }} run: | set -euox pipefail for tag in ${ALIAS_TAGS}; do sudo -E podman push --digestfile=/tmp/digestfile \ "${IMAGE_NAME}:${tag}" "${IMAGE_REGISTRY}/${IMAGE_NAME}:${tag}" done digest=$(< /tmp/digestfile) echo "digest=${digest}" >> "$GITHUB_OUTPUT" - name: Install ORAS if: github.event_name != 'pull_request' uses: oras-project/setup-oras@005458ad77f1c8facd38a094e4af2e69e5607ff4 # v2.0.2 - name: Upload RPM SBOM if: github.event_name != 'pull_request' env: DIGEST: ${{ steps.push-image.outputs.digest }} GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} SBOM: ${{ steps.generate-sbom.outputs.sbom }} run: | set -euo pipefail echo "${GHCR_TOKEN}" | oras login ghcr.io -u "${GITHUB_ACTOR}" --password-stdin cd "$(dirname "${SBOM}")" oras attach \ --artifact-type application/vnd.spdx+json \ --annotation "filename=$(basename "${SBOM}")" \ "${IMAGE_REGISTRY}/${IMAGE_NAME}@${DIGEST}" \ "$(basename "${SBOM}")" # This section is optional and only needs to be enabled if you plan on distributing # your project for others to consume. You will need to create a public and private key # using Cosign and save the private key as a repository secret in Github for this workflow # to consume. For more details, review the image signing section of the README. - name: Install Cosign uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 if: github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || github.ref_name == 'testing' || github.ref_name == 'testing-candidate') # https://github.com/containers/container-libs/issues/388 with: cosign-release: 'v2.6.3' - name: Sign container image id: sign-image if: github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || github.ref_name == 'testing' || github.ref_name == 'testing-candidate') env: COSIGN_EXPERIMENTAL: false COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }} COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} DIGEST: ${{ steps.push-image.outputs.digest }} run: | cosign sign -y --key env://COSIGN_PRIVATE_KEY "${IMAGE_REGISTRY}/${IMAGE_NAME}@${DIGEST}" generate_release: name: Generate Release needs: [build_push] if: github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || github.ref_name == 'testing' || github.ref_name == 'testing-candidate') permissions: contents: write packages: read secrets: inherit uses: ./.github/workflows/generate_release.yml with: release_tag: ${{ needs.build_push.outputs.release_tag }} handwritten: ${{ inputs.handwritten }}