name: 'Single arch image build'
description: 'Build single-arch image on platform appropriate runner'
inputs:
  image:
    description: 'Name of the image to build'
    required: true
  ghcr-token:
    description: 'GitHub Container Registry token'
    required: true
  platform:
    description: 'Platform to build for'
    required: true
  artifact-key-base:
    description: 'Base key for artifact name'
    required: true
  context:
    description: 'Path to build context'
    required: true
  dockerfile:
    description: 'Path to Dockerfile'
    required: true
  build-args:
    description: 'Docker build arguments'
    required: false
runs:
  using: 'composite'
  steps:
    - name: Prepare
      id: prepare
      shell: bash
      env:
        PLATFORM: ${{ inputs.platform }}
      run: |
        echo "platform-pair=${PLATFORM//\//-}" >> $GITHUB_OUTPUT

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0

    - name: Login to GitHub Container Registry
      uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
      if: ${{ !github.event.pull_request.head.repo.fork }}
      with:
        registry: ghcr.io
        username: ${{ github.repository_owner }}
        password: ${{ inputs.ghcr-token }}

    - name: Generate cache key suffix
      id: cache-key-suffix
      shell: bash
      env:
        REF: ${{ github.ref_name }}
      run: |
        if [[ "${{ github.event_name }}" == "pull_request" ]]; then
          echo "cache-key-suffix=pr-${{ github.event.number }}" >> $GITHUB_OUTPUT
        else
          SUFFIX=$(echo "${REF}" | sed 's/[^a-zA-Z0-9]/-/g')
          echo "suffix=${SUFFIX}" >> $GITHUB_OUTPUT
        fi

    - name: Generate cache target
      id: cache-target
      shell: bash
      env:
        BUILD_ARGS: ${{ inputs.build-args }}
        IMAGE: ${{ inputs.image }}
        SUFFIX: ${{ steps.cache-key-suffix.outputs.suffix }}
        PLATFORM_PAIR: ${{ steps.prepare.outputs.platform-pair }}
      run: |
        HASH=$(sha256sum <<< "${BUILD_ARGS}" | cut -d' ' -f1)
        CACHE_KEY="${PLATFORM_PAIR}-${HASH}"
        echo "cache-key-base=${CACHE_KEY}" >> $GITHUB_OUTPUT
        if [[ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]]; then
          # Essentially just ignore the cache output (forks can't write to registry cache)
          echo "cache-to=type=local,dest=/tmp/discard,ignore-error=true" >> $GITHUB_OUTPUT
        else
          echo "cache-to=type=registry,ref=${IMAGE}-build-cache:${CACHE_KEY}-${SUFFIX},mode=max,compression=zstd" >> $GITHUB_OUTPUT
        fi

    - name: Generate docker image tags
      id: meta
      uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5
      env:
        DOCKER_METADATA_PR_HEAD_SHA: 'true'

    - name: Build and push image
      id: build
      uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
      with:
        context: ${{ inputs.context }}
        file: ${{ inputs.dockerfile }}
        platforms: ${{ inputs.platform }}
        labels: ${{ steps.meta.outputs.labels }}
        cache-to: ${{ steps.cache-target.outputs.cache-to }}
        cache-from: |
          type=registry,ref=${{ inputs.image }}-build-cache:${{ steps.cache-target.outputs.cache-key-base }}-${{ steps.cache-key-suffix.outputs.suffix }}
          type=registry,ref=${{ inputs.image }}-build-cache:${{ steps.cache-target.outputs.cache-key-base }}-main
        outputs: type=image,"name=${{ inputs.image }}",push-by-digest=true,name-canonical=true,push=${{ !github.event.pull_request.head.repo.fork }}
        build-args: |
          BUILD_ID=${{ github.run_id }}
          BUILD_IMAGE=${{ github.event_name == 'release' && github.ref_name || steps.meta.outputs.tags }}
          BUILD_SOURCE_REF=${{ github.ref_name }}
          BUILD_SOURCE_COMMIT=${{ github.sha }}
          ${{ inputs.build-args }}

    - name: Export digest
      shell: bash
      run: | # zizmor: ignore[template-injection]
        mkdir -p ${{ runner.temp }}/digests
        digest="${{ steps.build.outputs.digest }}"
        touch "${{ runner.temp }}/digests/${digest#sha256:}"

    - name: Upload digest
      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
      with:
        name: ${{ inputs.artifact-key-base }}-${{ steps.cache-target.outputs.cache-key-base }}
        path: ${{ runner.temp }}/digests/*
        if-no-files-found: error
        retention-days: 1
