name: Generic zig build
on:
  workflow_dispatch:
  push:
    branches:
      - '*'
env:
  BUILD_TARGET: x86_64-linux-musl
  BUILD_OPTIMIZATION: ReleaseSafe
  BINARY_NAME: zfin
  MACOS_TARGET: aarch64-macos
  MACOS_ARTIFACT: zfin-aarch64-macos
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository code
        uses: actions/checkout@v4
      - name: Setup Zig
        uses: https://codeberg.org/mlugg/setup-zig@v2.2.1
      - name: Build project
        run: zig build --summary all
      - name: Run tests
        run: zig build test --summary all
      - name: Package (linux)
        run: zig build -Dtarget="$BUILD_TARGET" -Doptimize="$BUILD_OPTIMIZATION"
      - name: Upload (linux)
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.BINARY_NAME }}
          path: zig-out/bin/${{ env.BINARY_NAME }}
      - name: Package (aarch64-macos)
        run: |
          # Cross-compile a separate ReleaseSafe build for Apple silicon
          zig build -Dtarget="$MACOS_TARGET" -Doptimize="$BUILD_OPTIMIZATION"
          # Rename so the upload artifact is unambiguous about
          # which target it's for.
          mv zig-out/bin/${{ env.BINARY_NAME }} zig-out/bin/${{ env.MACOS_ARTIFACT }}
      - name: Upload (aarch64-macos)
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.MACOS_ARTIFACT }}
          path: zig-out/bin/${{ env.MACOS_ARTIFACT }}
      - name: Notify
        uses: https://git.lerch.org/lobo/action-notify-ntfy@v2
        if: always() && env.GITEA_ACTIONS == 'true'
        with:
          host: ${{ secrets.NTFY_HOST }}
          topic: ${{ secrets.NTFY_TOPIC }}
          status: ${{ job.status }}
          user: ${{ secrets.NTFY_USER }}
          password: ${{ secrets.NTFY_PASSWORD }}
  deploy:
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/catthehacker/ubuntu:act-22.04
    needs: build
    steps:
      - name: Check out repository code
        uses: actions/checkout@v4
      - name: Download Artifact
        uses: actions/download-artifact@v3
        with:
          name: ${{ env.BINARY_NAME }}
      - name: "Make executable actually executable"
        run: chmod 755 ${{ env.BINARY_NAME }} && mv ${{ env.BINARY_NAME }} docker
      - name: Get short ref
        id: vars
        run: echo "shortsha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
      -
        name: Login to Gitea
        uses: docker/login-action@v2
        with:
          registry: git.lerch.org
          username: ${{ github.actor }}
          password: ${{ secrets.PACKAGE_PUSH }}
      -
        name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: docker
          push: true
          tags: |
            git.lerch.org/${{ github.repository }}:${{ steps.vars.outputs.shortsha }}
            git.lerch.org/${{ github.repository }}:latest
      - name: Notify
        uses: https://git.lerch.org/lobo/action-notify-ntfy@v2
        if: always()
        with:
          host: ${{ secrets.NTFY_HOST }}
          topic: ${{ secrets.NTFY_TOPIC }}
          user: ${{ secrets.NTFY_USER }}
          password: ${{ secrets.NTFY_PASSWORD }}
  publish-macos:
    # Publish the aarch64-macos binary as a Forgejo generic
    # package so users can `curl`-download a release build
    # without having Zig installed. Mirrors the docker-image
    # publication for the linux side: same registry, same
    # auth secret, same shortsha + `latest` versioning.
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Check out repository code
        uses: actions/checkout@v4
      - name: Download Artifact
        uses: actions/download-artifact@v3
        with:
          name: ${{ env.MACOS_ARTIFACT }}
      - name: Make executable
        run: chmod 755 ${{ env.MACOS_ARTIFACT }}
      - name: Get short ref
        id: vars
        run: echo "shortsha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
      - name: Publish to Forgejo generic package registry
        env:
          # Same secret that authorizes the docker push. The
          # generic-packages endpoint accepts the same token
          # format (basic auth: username + password/token).
          PACKAGE_PUSH: ${{ secrets.PACKAGE_PUSH }}
          ACTOR: ${{ github.actor }}
          REPO: ${{ github.repository }}
          SHORTSHA: ${{ steps.vars.outputs.shortsha }}
        run: |
          set -euo pipefail
          # Owner is the first path segment of github.repository
          # (e.g. "lobo" in "lobo/zfin").
          OWNER="${REPO%%/*}"
          PACKAGE_NAME="${{ env.BINARY_NAME }}-aarch64-macos"
          BASE_URL="https://git.lerch.org/api/packages/${OWNER}/generic/${PACKAGE_NAME}"
          FILE="${{ env.MACOS_ARTIFACT }}"

          # Upload under both the short-SHA version and `latest`.
          # Forgejo's generic registry treats a re-PUT to the
          # same (version, filename) as a conflict (HTTP 409),
          # so `latest` needs DELETE-then-PUT.
          for VERSION in "$SHORTSHA" "latest"; do
            URL="${BASE_URL}/${VERSION}/${FILE}"
            echo "Publishing ${URL}"
            # Delete any pre-existing artifact at this version
            # (idempotency for `latest`; harmless 404 for new
            # short-SHA versions).
            curl -sS -o /dev/null -w "DELETE %{http_code}\n" \
              -u "${ACTOR}:${PACKAGE_PUSH}" \
              -X DELETE "${URL}" || true
            # Upload the binary.
            curl -sSf -u "${ACTOR}:${PACKAGE_PUSH}" \
              --upload-file "${FILE}" \
              "${URL}"
            echo "  uploaded ${FILE} -> ${URL}"
          done
      - name: Notify
        uses: https://git.lerch.org/lobo/action-notify-ntfy@v2
        if: always()
        with:
          host: ${{ secrets.NTFY_HOST }}
          topic: ${{ secrets.NTFY_TOPIC }}
          user: ${{ secrets.NTFY_USER }}
          password: ${{ secrets.NTFY_PASSWORD }}
