name: Release Docker Image
concurrency:
  group: "release-image-${{ github.ref }}"

on:
  pull_request:
    paths-ignore:
      - "*.md"
      - "**/*.md"
      - ".gitlab-ci.yml"
      - ".gitignore"
      - "renovate.json"
      - "pkg/**"
      - "docs/**"
  push:
    branches:
      - main
    paths-ignore:
      - "*.md"
      - "**/*.md"
      - ".gitlab-ci.yml"
      - ".gitignore"
      - "renovate.json"
      - "pkg/**"
      - "docs/**"
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

env:
  BUILTIN_REGISTRY: forgejo.ellis.link
  BUILTIN_REGISTRY_ENABLED: "${{ ((vars.BUILTIN_REGISTRY_USER && secrets.BUILTIN_REGISTRY_PASSWORD) || (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false)) && 'true' || 'false' }}"
  IMAGE_PATH: forgejo.ellis.link/continuwuation/continuwuity

jobs:
  build-release:
    name: "Build ${{ matrix.slug }} (release)"
    runs-on: dind
    permissions:
      contents: read
      packages: write
      attestations: write
      id-token: write
    strategy:
      matrix:
        include:
          - platform: "linux/amd64"
            slug: "linux-amd64"
          - platform: "linux/arm64"
            slug: "linux-arm64"

    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
        with:
          persist-credentials: false
      - name: Prepare Docker build environment
        id: prepare
        uses: ./.forgejo/actions/prepare-docker-build
        with:
          platform: ${{ matrix.platform }}
          slug: ${{ matrix.slug }}
          target_cpu: ""
          profile: "release"
          images: ${{ env.IMAGE_PATH }}
          registry_user: ${{ vars.BUILTIN_REGISTRY_USER || github.actor }}
          registry_password: ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
      - name: Build and push Docker image by digest
        id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          file: "docker/Dockerfile"
          build-args: |
            GIT_COMMIT_HASH=${{ github.sha }}
            GIT_COMMIT_HASH_SHORT=${{ env.COMMIT_SHORT_SHA }}
            GIT_REMOTE_URL=${{github.event.repository.html_url }}
            GIT_REMOTE_COMMIT_URL=${{github.event.head_commit.url }}
            CARGO_INCREMENTAL=${{ env.BUILDKIT_ENDPOINT != '' && '1' || '0' }}
            TARGET_CPU=
            RUST_PROFILE=release
          platforms: ${{ matrix.platform }}
          labels: ${{ steps.prepare.outputs.metadata_labels }}
          annotations: ${{ steps.prepare.outputs.metadata_annotations }}
          cache-from: type=gha
          # cache-to: type=gha,mode=max
          sbom: true
          outputs: |
            ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' && format('type=image,"name={0}",push-by-digest=true,name-canonical=true,push=true', env.IMAGE_PATH) || format('type=image,"name={0}",push=false', env.IMAGE_PATH) }}
            type=local,dest=/tmp/binaries
        env:
          SOURCE_DATE_EPOCH: ${{ env.TIMESTAMP }}
      - name: Upload Docker artifacts
        uses: ./.forgejo/actions/upload-docker-artifacts
        with:
          slug: ${{ matrix.slug }}
          cpu_suffix: ${{ steps.prepare.outputs.cpu_suffix }}
          artifact_suffix: ""
          digest_suffix: ""
          digest: ${{ steps.build.outputs.digest }}

  merge-release:
    name: "Create Multi-arch Release Manifest"
    runs-on: dind
    needs: build-release
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
        with:
          persist-credentials: false
      - name: Create multi-platform manifest
        uses: ./.forgejo/actions/create-docker-manifest
        with:
          digest_pattern: "digests-linux-{amd64,arm64}"
          tag_suffix: ""
          images: ${{ env.IMAGE_PATH }}
          registry_user: ${{ vars.BUILTIN_REGISTRY_USER || github.actor }}
          registry_password: ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}

  build-maxperf:
    name: "Build ${{ matrix.slug }} (max-perf)"
    runs-on: dind
    needs: build-release
    permissions:
      contents: read
      packages: write
      attestations: write
      id-token: write
    strategy:
      matrix:
        include:
          - platform: "linux/amd64"
            slug: "linux-amd64"
            target_cpu: "haswell"
          - platform: "linux/arm64"
            slug: "linux-arm64"
            target_cpu: ""

    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
        with:
          persist-credentials: false
      - name: Prepare max-perf Docker build environment
        id: prepare
        uses: ./.forgejo/actions/prepare-docker-build
        with:
          platform: ${{ matrix.platform }}
          slug: ${{ matrix.slug }}
          target_cpu: ${{ matrix.target_cpu }}
          profile: "release-max-perf"
          images: ${{ env.IMAGE_PATH }}
          registry_user: ${{ vars.BUILTIN_REGISTRY_USER || github.actor }}
          registry_password: ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
      - name: Build and push max-perf Docker image by digest
        id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          file: "docker/Dockerfile"
          build-args: |
            GIT_COMMIT_HASH=${{ github.sha }}
            GIT_COMMIT_HASH_SHORT=${{ env.COMMIT_SHORT_SHA }}
            GIT_REMOTE_URL=${{github.event.repository.html_url }}
            GIT_REMOTE_COMMIT_URL=${{github.event.head_commit.url }}
            CARGO_INCREMENTAL=${{ env.BUILDKIT_ENDPOINT != '' && '1' || '0' }}
            TARGET_CPU=${{ matrix.target_cpu }}
            RUST_PROFILE=release-max-perf
          platforms: ${{ matrix.platform }}
          labels: ${{ steps.prepare.outputs.metadata_labels }}
          annotations: ${{ steps.prepare.outputs.metadata_annotations }}
          cache-from: type=gha
          # cache-to: type=gha,mode=max
          sbom: true
          outputs: |
            ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' && format('type=image,"name={0}",push-by-digest=true,name-canonical=true,push=true', env.IMAGE_PATH) || format('type=image,"name={0}",push=false', env.IMAGE_PATH) }}
            type=local,dest=/tmp/binaries
        env:
          SOURCE_DATE_EPOCH: ${{ env.TIMESTAMP }}
      - name: Upload max-perf Docker artifacts
        uses: ./.forgejo/actions/upload-docker-artifacts
        with:
          slug: ${{ matrix.slug }}
          cpu_suffix: ${{ steps.prepare.outputs.cpu_suffix }}
          artifact_suffix: "-maxperf"
          digest_suffix: "-maxperf"
          digest: ${{ steps.build.outputs.digest }}

  merge-maxperf:
    name: "Create Max-Perf Manifest"
    runs-on: dind
    needs: build-maxperf
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
        with:
          persist-credentials: false
      - name: Create max-perf manifest
        uses: ./.forgejo/actions/create-docker-manifest
        with:
          digest_pattern: "digests-maxperf-linux-{amd64-haswell,arm64}"
          tag_suffix: "-maxperf"
          images: ${{ env.IMAGE_PATH }}
          registry_user: ${{ vars.BUILTIN_REGISTRY_USER || github.actor }}
          registry_password: ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
