Skip to content

ci: add input for pushing image #1

ci: add input for pushing image

ci: add input for pushing image #1

name: Reusable Build and Push

Check failure on line 1 in .github/workflows/reusable-build.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/reusable-build.yml

Invalid workflow file

(Line: 177, Col: 13): Unexpected symbol: '"true"'. Located at position 16 within expression: inputs.push == "true", (Line: 184, Col: 13): Unexpected symbol: '"true"'. Located at position 16 within expression: inputs.push == "true", (Line: 226, Col: 13): Unexpected symbol: '"true"'. Located at position 16 within expression: inputs.push == "true" && contains(matrix.image_flavor, 'hwe')
on:
workflow_call:
inputs:
image_flavors:
description: "JSON string of flavors to build, '[main, nvidia, hwe, hwe-nvidia]'"
default: "['main', 'nvidia', 'nvidia-open']"
type: string
brand_name:
description: "The Brand Name: bluefin"
required: true
default: bluefin
type: string
stream_name:
description: "The Fedora Version: gts, stable, or latest"
required: true
type: string
kernel_pin:
description: "The full kernel version to pin"
type: string
push:
description: "Whether the image should be pushed to a registry"
type: string
default: false
env:
IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.brand_name}}-${{ inputs.stream_name }}
cancel-in-progress: true
jobs:
build_container:
name: image
runs-on: ubuntu-24.04
continue-on-error: false
strategy:
fail-fast: false
matrix:
image_flavor: ${{ fromJson(inputs.image_flavors) }}
base_name: ["${{ inputs.brand_name }}", "${{ inputs.brand_name }}-dx"]
stream_name: ["${{ inputs.stream_name }}"]
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
- name: Maximize build space
uses: ublue-os/container-storage-action@911baca08baf30c8654933e9e9723cb399892140
continue-on-error: true
with:
target-dir: /var/lib/containers
mount-opts: compress-force=zstd:2
loopback-free: 0.9
- name: Setup Just
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
- name: Check Just Syntax
shell: bash
run: |
just check
- name: Image Name
shell: bash
run: |
IMAGE_NAME="$(just image_name ${{ matrix.base_name }} ${{ matrix.stream_name }} ${{ matrix.image_flavor }})"
echo "IMAGE_NAME=${IMAGE_NAME}" >> $GITHUB_ENV
- name: Default Tag
shell: bash
run: |
DEFAULT_TAG="$(just generate-default-tag \
${{ matrix.stream_name }} \
"1")"
echo "Default Tag: ${DEFAULT_TAG}"
echo "DEFAULT_TAG=${DEFAULT_TAG}" >> $GITHUB_ENV
- name: Build Image
id: build-image
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
sudo -E $(command -v just) repo_organization="${{ github.repository_owner }}" \
build-ghcr "${{ matrix.base_name }}" \
"${{ matrix.stream_name }}" \
"${{ matrix.image_flavor }}" \
"${{ inputs.kernel_pin }}"
- name: Setup Syft
id: setup-syft
if: false
uses: anchore/sbom-action/download-syft@aa0e114b2e19480f157109b9922bda359bd98b90 # v0
with:
syft-version: v1.20.0
- name: Generate SBOM
if: false
id: generate-sbom
env:
IMAGE: ${{ env.IMAGE_NAME }}
STREAM_NAME: ${{ matrix.stream_name }}
SYFT_CMD: ${{ steps.setup-syft.outputs.cmd }}
run: |
sudo systemctl start podman.socket
OUTPUT_PATH="$(mktemp -d)/sbom.json"
export SYFT_PARALLELISM=$(($(nproc)*2))
sudo $SYFT_CMD ${IMAGE}:${STREAM_NAME} -o spdx-json=${OUTPUT_PATH}
echo "OUTPUT_PATH=${OUTPUT_PATH}" >> $GITHUB_OUTPUT
- name: Rechunk Image
id: rechunk-image
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
sudo -E $(command -v just) rechunk "${{ matrix.base_name }}" \
"${{ matrix.stream_name }}" \
"${{ matrix.image_flavor }}" \
"1"
- name: Load Image into Podman
id: load-rechunk
shell: bash
run: |
sudo -E $(command -v just) load-rechunk "${{ matrix.base_name }}" \
"${{ env.DEFAULT_TAG }}" \
"${{ matrix.image_flavor }}"
- name: Secureboot Check
id: secureboot
shell: bash
run: |
sudo -E $(command -v just) secureboot "${{ matrix.base_name }}" \
"${{ env.DEFAULT_TAG }}" \
"${{ matrix.image_flavor }}"
- name: Generate tags
id: generate-tags
shell: bash
run: |
alias_tags="$(just generate-build-tags \
"${{ matrix.base_name }}" \
"${{ matrix.stream_name }}" \
"${{ matrix.image_flavor }}" \
"${{ inputs.kernel_pin }}" \
"1" \
"$(podman inspect ${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }} | jq -r '.[].Config.Labels["org.opencontainers.image.version"]')" \
"${{ github.event_name }}" \
"${{ github.event.number }}")"
echo "Tags for this Action..."
echo "$alias_tags"
echo "alias_tags=${alias_tags}" >> $GITHUB_OUTPUT
# Tag Images
- name: Tag Images
shell: bash
run: |
set -eoux pipefail
sudo -E $(command -v just) tag-images "${{ env.IMAGE_NAME }}" \
"${{ env.DEFAULT_TAG }}" \
"${{ steps.generate-tags.outputs.alias_tags }}"
# Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR.
# https://github.com/macbre/push-to-ghcr/issues/12
- name: Lowercase Registry
id: registry_case
uses: ASzc/change-string-case-action@d0603cd0a7dd490be678164909f65c7737470a7f # v6
with:
string: ${{ env.IMAGE_REGISTRY }}
- name: Login to GitHub Container Registry
if: inputs.push == "true"
run: |
echo ${{ secrets.GITHUB_TOKEN }} | podman login ghcr.io -u ${{ github.actor }} --password-stdin
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Push to GHCR
id: push
if: inputs.push == "true"
uses: Wandalen/wretry.action@e68c23e6309f2871ca8ae4763e7629b9c258e1ea # v3.8.0
with:
attempt_limit: 3
attempt_delay: 15000
command: |
set -euox pipefail
for tag in ${{ steps.generate-tags.outputs.alias_tags }}; do
sudo -E podman push ${{ env.IMAGE_NAME }}:${tag} ${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}:${tag}
done
if [[ "${{ matrix.image_flavor }}" =~ hwe ]]; then
image_name="${{ env.IMAGE_NAME }}"
asus_name="${image_name/hwe/asus}"
surface_name="${image_name/hwe/surface}"
for tag in ${{ steps.generate-tags.outputs.alias_tags }}; do
sudo -E podman push ${asus_name}:${tag} ${{ steps.registry_case.outputs.lowercase }}/${asus_name}:${tag}
sudo -E podman push ${surface_name}:${tag} ${{ steps.registry_case.outputs.lowercase }}/${surface_name}:${tag}
done
fi
digest=$(skopeo inspect docker://${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }} --format '{{.Digest}}')
echo "digest=${digest}" >> $GITHUB_OUTPUT
- name: Install Cosign
uses: sigstore/cosign-installer@7e8b541eb2e61bf99390e1afd4be13a184e9ebc5 # v3.10.1
if: github.event_name != 'pull_request'
- name: Sign container image
if: github.event_name != 'pull_request'
run: |
cosign sign -y --key env://COSIGN_PRIVATE_KEY ${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}@${TAGS}
env:
TAGS: ${{ steps.push.outputs.outputs && fromJSON(steps.push.outputs.outputs).digest }}
COSIGN_EXPERIMENTAL: false
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
- name: Sign container image
if: inputs.push == "true" && contains(matrix.image_flavor, 'hwe')
shell: bash
run: |
image_name="${{ env.IMAGE_NAME }}"
asus_name="${image_name/hwe/asus}"
surface_name="${image_name/hwe/surface}"
cosign sign -y --key env://COSIGN_PRIVATE_KEY ${{ steps.registry_case.outputs.lowercase }}/${asus_name}@${TAGS}
cosign sign -y --key env://COSIGN_PRIVATE_KEY ${{ steps.registry_case.outputs.lowercase }}/${surface_name}@${TAGS}
env:
TAGS: ${{ steps.push.outputs.outputs && fromJSON(steps.push.outputs.outputs).digest }}
COSIGN_EXPERIMENTAL: false
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
- name: Add SBOM Attestation
if: false
env:
IMAGE: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}
DIGEST: ${{ steps.push.outputs.outputs && fromJSON(steps.push.outputs.outputs).digest }}
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
SBOM_OUTPUT: ${{ steps.generate-sbom.outputs.OUTPUT_PATH }}
run: |
cd "$(dirname "$SBOM_OUTPUT")"
cosign attest -y \
--predicate ./sbom.json \
--type spdxjson \
--key env://COSIGN_PRIVATE_KEY \
"${IMAGE}@${DIGEST}"
check:
name: Check all ${{ matrix.stream_name }} builds successful
if: always()
runs-on: ubuntu-latest
needs: [build_container]
steps:
- name: Check Jobs
env:
JOBS: ${{ toJson(needs) }}
run: |
echo "Job status:"
echo $JOBS | jq -r 'to_entries[] | " - \(.key): \(.value.result)"'
for i in $(echo $JOBS | jq -r 'to_entries[] | .value.result'); do
if [ "$i" != "success" ] && [ "$i" != "skipped" ]; then
echo ""
echo "Status check not okay!"
exit 1
fi
done