# Release: on a version tag, build the cross-platform binaries and publish them
# to a Gitea release with checksums. Runs in the prebuilt CI image, so the
# pinned toolchain + the release targets + cargo-zigbuild/zig are already warm.
#
# Matrix (D1, cross-built from Linux x86_64 via cargo-zigbuild):
#   x86_64-unknown-linux-musl   aarch64-unknown-linux-musl   (static, D2)
#   x86_64-pc-windows-gnu       aarch64-pc-windows-gnullvm   (standalone .exe)
# The two macOS targets are built separately by the dispatched
# release-macos.yaml (native Tart runner; ADR-ci-003 amendment), uploading to
# the same release. D3 package-manager manifests layer on later.
#
# Tests run once (host) before the matrix, so a tag can never publish untested
# code, even one pointing at a commit that was never gated on a branch. The
# version guard (ADR-0054) refuses to publish a tag whose vX.Y.Z disagrees with
# Cargo.toml's version, keeping `--version`, the release name, and the asset in
# lockstep.
name: release
on:
  push:
    tags:
      - 'v*'

jobs:
  test:
    runs-on: ci-public
    container:
      image: git.lazyeval.net/oli/rdbms-playground-ci:latest
    steps:
      - uses: actions/checkout@v4
      - name: version guard — tag must equal Cargo.toml version (ADR-0054)
        shell: bash
        env:
          TAG: ${{ github.ref_name }}
        run: |
          set -euo pipefail
          # Read the [package] version straight from Cargo.toml — toolchain-free
          # and robust. (An earlier `nix develop -c cargo metadata | node` version
          # broke: the flake devShell prints a banner to stdout, corrupting the
          # JSON pipe.) `^version = ` is anchored, so it matches only the package
          # version, never the `version = ` inside dependency inline tables.
          VER=$(grep -m1 '^version = ' Cargo.toml | sed -E 's/^version = "(.*)"/\1/')
          echo "tag=$TAG  cargo=v$VER"
          if [ -z "$VER" ]; then
            echo "ERROR: could not read the package version from Cargo.toml" >&2
            exit 1
          fi
          if [ "$TAG" != "v$VER" ]; then
            echo "ERROR: release tag '$TAG' != 'v$VER' (Cargo.toml). Bump Cargo.toml to the release version, commit, then retag (ADR-0054)." >&2
            exit 1
          fi
      - name: test
        run: nix develop -c cargo test --no-fail-fast

  build:
    needs: test
    runs-on: ci-public
    container:
      image: git.lazyeval.net/oli/rdbms-playground-ci:latest
    strategy:
      fail-fast: false
      matrix:
        target:
          - x86_64-unknown-linux-musl
          - aarch64-unknown-linux-musl
          - x86_64-pc-windows-gnu
          - aarch64-pc-windows-gnullvm
    steps:
      - uses: actions/checkout@v4

      - name: build
        run: nix develop -c cargo zigbuild --release --target ${{ matrix.target }}

      - name: package + publish
        # Pin bash: the runner defaults scripted steps to dash, which rejects
        # `set -o pipefail`. bash is in the CI image.
        shell: bash
        env:
          TARGET: ${{ matrix.target }}
          # GITEA_TOKEN is auto-provided with repo write (release) scope.
          TOKEN: ${{ secrets.GITEA_TOKEN }}
          API: ${{ github.server_url }}/api/v1
          REPO: ${{ github.repository }}
          TAG: ${{ github.ref_name }}
        run: |
          set -euo pipefail

          # Windows targets produce a .exe; the rest a bare binary.
          case "$TARGET" in *windows*) EXT=.exe ;; *) EXT= ;; esac
          BIN="target/$TARGET/release/rdbms-playground$EXT"
          OUT="rdbms-playground-$TAG-$TARGET$EXT"
          mkdir -p dist
          cp "$BIN" "dist/$OUT"
          ( cd dist && sha256sum "$OUT" > "$OUT.sha256" )
          ls -l dist

          # Create the release for this tag; if a sibling matrix job already
          # created it, look it up instead (idempotent + race-tolerant).
          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 f in dist/*; do
            name=$(basename "$f")
            echo "uploading $name"
            curl -sS -X POST "$API/repos/$REPO/releases/$id/assets?name=$name" \
              -H "Authorization: token $TOKEN" \
              -F "attachment=@$f" > /dev/null
          done
          echo "published $TARGET assets for $TAG"
