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@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.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