# Gitea Actions workflow for hrafn.
#
# Runs on every push to main (and on manual workflow_dispatch). Drives
# the in-repo elway playbook (playbooks/deploy.yaml) — that file is the
# single source of truth for "how hrafn is deployed", manual or automated.
#
# Replaces the hand-rsync deploy. Two things change as a result:
#   - the image is tagged with the commit SHA rather than a fixed `v1`,
#     so the host can answer "what is running" and a rollback is a retag
#   - only the build context ships (Dockerfile, compose.yaml,
#     pyproject.toml, README.md, src/) instead of the whole working tree,
#     so tests/, docs/, persistent-memory.md and friends stop living in
#     /opt/docker/compose/hrafn on the server
#
# Required Actions secrets — both already exist at user scope on vh from
# the nevermore/task-board wiring, so there is nothing new to provision:
#
#   DEPLOY_SSH_KEY    Private SSH key authorized for lkraven@ana-docker.
#   MGMT_REPO_TOKEN   Gitea PAT (read:repository) on vh/esh-pfi-infrastructure.
#                     Needed to clone elway from the management repo.
#
# NOT handled here: .env. It is host-owned, 0600, holds the bearer token,
# and is provisioned once from vault item ana-docker/hrafn/bearer-token.
# The playbook refuses to deploy if it is missing or not 0600.

name: Deploy hrafn

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  deploy:
    runs-on: pfi-fleet

    steps:
      - name: Install playbook prerequisites
        # DO NOT add `git` here. actions/checkout@v4 uses its node
        # implementation when no git binary is present, which is what every
        # working run of this pipeline has used. Installing git flips it to
        # the git binary, and this image ships no CA bundle — the checkout
        # then dies with "server certificate verification failed. CAfile:
        # none" (run 9921). Adding ca-certificates would paper over it; not
        # installing git avoids the code-path change entirely.
        run: |
          apt-get update -qq
          apt-get install -y --no-install-recommends \
            python3 python3-yaml openssh-client tar
          rm -rf /var/lib/apt/lists/*

      - name: Checkout hrafn (triggering repo)
        uses: actions/checkout@v4
        with:
          # Self-hosted runners reuse workspaces. Without a clean checkout a
          # stale tree can be tarred while GITHUB_SHA claims the new commit —
          # exactly the kind of drift the SHA tagging is supposed to prevent.
          clean: true

      # NO HEAD-vs-GITHUB_SHA ASSERTION. One was added here and removed: it
      # needed the git binary, whose installation broke the checkout (above),
      # and it was guarding a hypothesis that turned out to be wrong — the
      # frozen-source bug was a self-referential rsync in the playbook, not a
      # stale runner checkout. `clean: true` covers workspace reuse, and the
      # host-side content hash proves the shipped bytes landed. Adding a
      # package and a code-path change to assert a third time was not worth
      # destabilising a working checkout.

      - name: Checkout management repo (for elway)
        uses: actions/checkout@v4
        with:
          repository: vh/esh-pfi-infrastructure
          token: ${{ secrets.MGMT_REPO_TOKEN }}
          path: _mgmt

      - name: Configure SSH to ana-docker
        run: |
          mkdir -p ~/.ssh
          printf '%s\n' "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          cat > ~/.ssh/config <<'EOF'
          Host ana-docker
            HostName 10.250.50.70
            User lkraven
            IdentityFile ~/.ssh/id_ed25519
            StrictHostKeyChecking accept-new
          EOF
          chmod 600 ~/.ssh/config

      - name: Build the deploy context
        # Only what the Dockerfile actually consumes, plus compose.yaml
        # and .env.example. Deliberately excludes tests/, docs/,
        # persistent-memory.md, ROADMAP.md, CLAUDE.md, LICENSE and .env —
        # none of them belong in a production compose directory.
        #
        # This list is AUTHORITATIVE: the playbook converges the host
        # directory onto this tarball with rsync --delete, so anything
        # omitted here is removed from the host on the next deploy
        # (except the host-owned .env and .deployed).
        run: |
          mkdir -p dist
          tar czf dist/hrafn-context.tgz \
            Dockerfile compose.yaml pyproject.toml README.md .env.example src
          echo "context contents:"
          tar tzf dist/hrafn-context.tgz

          # Content hash over the same file list, in the same order the
          # playbook recomputes it on the host. This is what turns "the
          # deploy said OK" into "the bytes on the host are the bytes CI
          # built" — the assertion whose absence let the host source stay
          # frozen at 0.1.0 through every green deploy.
          CTX=$(find Dockerfile compose.yaml pyproject.toml README.md .env.example src \
                  -type f | LC_ALL=C sort | xargs sha256sum | sha256sum | cut -d' ' -f1)
          echo "context_sha256=$CTX" | tee -a "$GITHUB_ENV"
          echo "  version in this context:"
          grep -h '__version__' src/hrafn/__init__.py || true

      - name: Deploy hrafn (in-repo elway playbook)
        # hrafn_sha becomes the image tag and is written to
        # /opt/docker/compose/hrafn/.deployed on the host. context_sha256
        # is asserted against the host tree AFTER the converge, so a deploy
        # that fails to land new source fails the job instead of passing.
        run: |
          _mgmt/scripts/elway ana-docker \
            --playbook playbooks/deploy.yaml \
            --var hrafn_sha=${GITHUB_SHA::12} \
            --var context_sha256=${context_sha256}
