# macOS release leg — the two *-apple-darwin binaries, built natively on the
# Tart (Apple-Silicon) runner and attached to an existing Gitea release.
#
# Manual dispatch only: the Mac runner is intermittent, so this is triggered by
# hand (with the Mac up) for a given release tag. The 4-target Linux/Windows
# release (release.yaml) runs on the tag itself and never waits on the Mac, so a
# release always has those four; the macOS two are added by dispatching this.
#
# NOTE: Gitea exposes workflow_dispatch only for workflows on the DEFAULT branch,
# so this becomes triggerable once the CI work is merged to `main`.
name: release-macos
on:
  workflow_dispatch:
    inputs:
      tag:
        description: 'Release tag to build the macOS binaries for and attach to (e.g. v0.1.0)'
        required: true

jobs:
  release-macos:
    runs-on: macos
    env:
      NIX_CONFIG: "experimental-features = nix-command flakes"
      TAG: ${{ inputs.tag }}
      # Auto-provided by Gitea Actions; has repo write (release) scope.
      TOKEN: ${{ secrets.GITEA_TOKEN }}
      API: ${{ github.server_url }}/api/v1
      REPO: ${{ github.repository }}
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ inputs.tag }}

      - name: test
        run: nix develop -c cargo test --no-fail-fast

      - name: build, de-nix, sign, package + publish
        run: |
          set -e
          mkdir -p dist
          for t in aarch64-apple-darwin x86_64-apple-darwin; do
            echo "==================== $t ===================="
            nix develop -c cargo build --release --target "$t"
            f="target/$t/release/rdbms-playground"

            # Rewrite the nix-store libiconv load path to the system one, then
            # re-sign ad-hoc (install_name_tool invalidates the signature; arm64
            # requires a valid one). Guard against any remaining /nix/store dep.
            for l in $(otool -L "$f" | awk '/\/nix\/store.*libiconv.*dylib/ {print $1}'); do
              install_name_tool -change "$l" /usr/lib/libiconv.2.dylib "$f"
            done
            codesign --force --sign - "$f"
            if otool -L "$f" | grep -q /nix/store; then
              echo "ERROR: $t binary links a /nix/store dylib"; exit 1
            fi

            out="rdbms-playground-$TAG-$t"
            cp "$f" "dist/$out"
            ( cd dist && shasum -a 256 "$out" > "$out.sha256" )   # macOS: shasum, not sha256sum
          done
          ls -l dist

          # Idempotent create-or-get the release (release.yaml likely created it
          # already from the tag), then upload the two macOS binaries + checksums.
          created=$(curl -sS -X POST "$API/repos/$REPO/releases" \
            -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
            -d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\",\"body\":\"Automated release for $TAG.\"}")
          id=$(printf '%s' "$created" | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{try{const o=JSON.parse(s);process.stdout.write(String(o.id||""))}catch(e){}})')
          if [ -z "$id" ]; then
            id=$(curl -sS "$API/repos/$REPO/releases/tags/$TAG" \
              -H "Authorization: token $TOKEN" \
              | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{process.stdout.write(String(JSON.parse(s).id))})')
          fi
          echo "release id: $id"
          for fa in dist/*; do
            name=$(basename "$fa")
            echo "uploading $name"
            curl -sS -X POST "$API/repos/$REPO/releases/$id/assets?name=$name" \
              -H "Authorization: token $TOKEN" -F "attachment=@$fa" > /dev/null
          done
          echo "published macOS assets for $TAG"

      - name: prune nix store — keep the last 2 toolchain generations
        # The runner wipes the workspace each run, so cargo target/ never
        # accumulates. Bound the persistent nix store by generation: record the
        # current devShell as a generation of a persistent profile (in $HOME),
        # keep the 2 newest, reclaim what older ones referenced — so the
        # toolchain stays *warm* across runs and only stale generations are GC'd.
        #
        # The profile's parent dir MUST exist first, or `nix develop --profile`
        # errors ("cannot read directory …") and the profile/gc-root is never
        # created — which made `nix-collect-garbage` delete the whole toolchain
        # closure every run (re-downloaded ~3.8 GiB each time; the retention was
        # silently broken by the swallowed `|| true`). No `|| true` on the
        # profile realization now: a future breakage should fail loudly.
        if: always()
        run: |
          echo "--- disk before ---"; df -h / | tail -1
          P="$HOME/.cache/rdbms-ci/toolchain"
          mkdir -p "$(dirname "$P")"
          nix develop --profile "$P" -c true
          nix-env -p "$P" --delete-generations +2 || true
          nix-collect-garbage || true
          echo "--- disk after ---"; df -h / | tail -1
