Build container image #1444
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: Build container image | |
| on: | |
| pull_request: | |
| branches: ['*'] | |
| schedule: | |
| - cron: '05 10 * * *' # 10:05am UTC everyday | |
| push: | |
| branches: ['*'] | |
| paths-ignore: | |
| - '**/README.md' | |
| - 'releases.json' | |
| workflow_dispatch: | |
| env: | |
| IMAGE_DESC: "Zena" | |
| IMAGE_NAME: "${{ github.event.repository.name }}" | |
| IMAGE_REGISTRY: "ghcr.io/${{ github.repository_owner }}" | |
| FEDORA_VERSION: "43" | |
| DEFAULT_TAG: "latest" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.brand_name}}-${{ inputs.stream_name }} | |
| cancel-in-progress: true | |
| jobs: | |
| build_push: | |
| name: Build and push image | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| flavor: ["", "nvidia"] | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Change image name depending on build flavor | |
| env: | |
| BUILD_FLAVOR: ${{ matrix.flavor }} | |
| run: | | |
| if [ "${BUILD_FLAVOR}" != "" ] ; then | |
| echo "IMAGE_NAME=${IMAGE_NAME}-${{ matrix.flavor }}" >> $GITHUB_ENV | |
| fi | |
| - name: Lower case image variables | |
| run: | | |
| echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}" >> ${GITHUB_ENV} | |
| echo "IMAGE_NAME=${IMAGE_NAME,,}" >> ${GITHUB_ENV} | |
| - name: Set tag prefix | |
| if: github.ref_name != 'main' | |
| run: | | |
| echo "TAG_PREFIX=${{ github.ref_name }}." >> $GITHUB_ENV | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v6 | |
| - name: Mount BTRFS for podman storage | |
| id: container-storage-action | |
| uses: ublue-os/container-storage-action@main | |
| continue-on-error: true | |
| with: | |
| target-dir: /var/lib/containers | |
| mount-opts: compress-force=zstd:2 | |
| - name: Get current date | |
| id: date | |
| run: | | |
| echo "date=$(date -u +%Y\-%m\-%d\T%H\:%M\:%S\Z)" >> $GITHUB_OUTPUT | |
| - name: Image Metadata | |
| uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 | |
| id: metadata | |
| with: | |
| tags: | | |
| type=raw,value=${{ env.TAG_PREFIX }}{{date 'YYYYMMDD'}} | |
| type=raw,value=${{ env.TAG_PREFIX }}${{ env.DEFAULT_TAG }} | |
| type=raw,value=${{ env.TAG_PREFIX }}${{ env.FEDORA_VERSION }} | |
| type=raw,value=${{ env.TAG_PREFIX }}${{ env.FEDORA_VERSION }}.{{date 'YYYYMMDD'}} | |
| type=sha,enable=${{ github.event_name == 'pull_request' }} | |
| type=ref,event=pr | |
| labels: | | |
| org.opencontainers.image.created=${{ steps.date.outputs.date }} | |
| org.opencontainers.image.description=${{ env.IMAGE_DESC }} | |
| org.opencontainers.image.documentation=https://raw.githubusercontent.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/${{ github.sha }}/README.md | |
| org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/blob/${{ github.sha }}/Containerfile | |
| org.opencontainers.image.title=${{ env.IMAGE_NAME }} | |
| org.opencontainers.image.url=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/tree/${{ github.sha }} | |
| org.opencontainers.image.vendor=${{ github.repository_owner }} | |
| org.opencontainers.image.version=${{ env.FEDORA_VERSION }}.{{date 'YYYYMMDD'}} | |
| containers.bootc=1 | |
| sep-tags: ' ' | |
| sep-annotations: ' ' | |
| - name: Check secure boot key | |
| id: secret-check | |
| run: | | |
| if [ -z "${{ secrets.SECUREBOOT_KEY }}" ]; then | |
| echo "present=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "present=true" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Decode Secure Boot keys | |
| if: steps.secret-check.outputs.present == 'true' | |
| run: | | |
| echo "$SECUREBOOT_KEY" | base64 --decode > system-files/common/secureboot/MOK.key | |
| chmod 600 system-files/common/secureboot/MOK.key | |
| env: | |
| SECUREBOOT_KEY: ${{ secrets.SECUREBOOT_KEY }} | |
| - name: Prepare build args file | |
| run: | | |
| cat <<'EOF' >>build_args.txt | |
| FEDORA_VERSION=${{ env.FEDORA_VERSION }} | |
| IMAGE=${{ env.IMAGE_NAME }} | |
| EOF | |
| - name: Build Image | |
| id: build_image | |
| run: | | |
| sudo -E buildah build \ | |
| --file Containerfile \ | |
| --build-arg-file build_args.txt \ | |
| --tag raw-img . | |
| - name: Run Rechunker | |
| id: rechunk | |
| uses: ublue-os/legacy-rechunk@a925083d9af7cb04b3e2a6e8c01bfa495f38b710 # v1.0.0 | |
| with: | |
| rechunk: 'ghcr.io/ublue-os/legacy-rechunk:v1.0.0-x86_64' | |
| ref: 'raw-img' | |
| prev-ref: '${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}' | |
| skip_compression: false | |
| version: '${{ steps.metadata.outputs.tags }}' | |
| labels: '${{ steps.metadata.outputs.labels }}' | |
| - name: Load in podman and tag | |
| run: | | |
| IMAGE=$(podman pull ${{ steps.rechunk.outputs.ref }}) | |
| sudo rm -rf ${{ steps.rechunk.outputs.output }} | |
| for tag in ${{ steps.metadata.outputs.tags }}; do | |
| podman tag $IMAGE "${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:$tag" | |
| done | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee | |
| if: github.event_name != 'pull_request' | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Push To GHCR | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| set -euo pipefail | |
| retries=5 | |
| delay=10 | |
| # Loop through each tag | |
| for tag in ${{ steps.metadata.outputs.tags }}; do | |
| echo "Pushing tag: $tag" | |
| for attempt in $(seq 1 $retries); do | |
| echo " Attempt $attempt/$retries for $tag..." | |
| if podman push "${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:$tag" --tls-verify=true; then | |
| echo " Push of $tag succeeded" | |
| break | |
| fi | |
| if [ "$attempt" -lt "$retries" ]; then | |
| echo " Push of $tag failed — retrying in $delay seconds..." | |
| sleep $delay | |
| else | |
| echo " Push of $tag failed after $retries attempts" | |
| exit 1 | |
| fi | |
| done | |
| done | |
| - name: Install Cosign | |
| uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 | |
| if: github.event_name != 'pull_request' | |
| with: | |
| cosign-release: 'v2.6.1' | |
| - name: Sign container image | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| IMAGE_FULL="${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}" | |
| for tag in ${{ steps.metadata.outputs.tags }}; do | |
| cosign sign -y --key env://COSIGN_PRIVATE_KEY $IMAGE_FULL:$tag | |
| done | |
| env: | |
| TAGS: ${{ steps.push.outputs.digest }} | |
| COSIGN_EXPERIMENTAL: false | |
| COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }} |