---
name: Deploy Smoke
on:
  push:
    branches: [main]
    paths:
      - Dockerfile
      - .dockerignore
      - docker-compose.yml
      - .do/app.yaml
      - gitbooks/developing/cloud-deploy.md
      - .github/workflows/deploy-smoke.yml
      - Cargo.toml
      - Cargo.lock
      - rust-toolchain.toml
      - src/**
  pull_request:
    paths:
      - Dockerfile
      - .dockerignore
      - docker-compose.yml
      - .do/app.yaml
      - gitbooks/developing/cloud-deploy.md
      - .github/workflows/deploy-smoke.yml
      - Cargo.toml
      - Cargo.lock
      - rust-toolchain.toml
      - src/**
  workflow_dispatch:
permissions:
  contents: read
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.head_ref || github.ref }}
  cancel-in-progress: true
jobs:
  docker-image:
    name: Build & smoke-test core image
    runs-on: ubuntu-22.04
    timeout-minutes: 45
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          fetch-depth: 1
          submodules: false

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build openhuman-core image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: Dockerfile
          push: false
          load: true
          tags: openhuman-core:smoke
          cache-from: type=gha,scope=deploy-smoke
          cache-to: type=gha,scope=deploy-smoke,mode=max

      - name: Run container
        run: |
          docker run -d \
            --name oh-smoke \
            -p 7788:7788 \
            -e OPENHUMAN_CORE_TOKEN=ci-smoke-token \
            -e OPENHUMAN_APP_ENV=staging \
            -e BACKEND_URL=https://staging-api.tinyhumans.ai \
            openhuman-core:smoke

      - name: Wait for /health
        run: |
          set -e
          for i in $(seq 1 30); do
            if curl -fsS http://localhost:7788/health > /tmp/health.json; then
              echo "Healthy on attempt $i"
              cat /tmp/health.json
              exit 0
            fi
            echo "attempt $i: not ready, sleeping..."
            sleep 2
          done
          echo "Container never became healthy. Logs:"
          docker logs oh-smoke || true
          exit 1

      - name: Verify /rpc rejects without bearer token
        run: |
          set -e
          status=$(curl -s -o /tmp/rpc.json -w "%{http_code}" \
            -X POST http://localhost:7788/rpc \
            -H 'Content-Type: application/json' \
            -d '{"jsonrpc":"2.0","id":1,"method":"openhuman.about_app_list","params":{}}')
          if [ "$status" != "401" ]; then
            echo "Expected 401 from /rpc without token, got $status"
            cat /tmp/rpc.json
            docker logs oh-smoke || true
            exit 1
          fi

      - name: Verify /rpc accepts the configured bearer token
        run: |
          set -e
          status=$(curl -s -o /tmp/rpc-ok.json -w "%{http_code}" \
            -X POST http://localhost:7788/rpc \
            -H 'Content-Type: application/json' \
            -H 'Authorization: Bearer ci-smoke-token' \
            -d '{"jsonrpc":"2.0","id":1,"method":"openhuman.about_app_list","params":{}}')
          if [ "$status" != "200" ]; then
            echo "Expected 200 from authenticated /rpc, got $status"
            cat /tmp/rpc-ok.json
            docker logs oh-smoke || true
            exit 1
          fi
          cat /tmp/rpc-ok.json

      - name: Container logs (always)
        if: always()
        run: docker logs oh-smoke || true

      - name: Tear down
        if: always()
        run: docker rm -f oh-smoke || true

  # Regression gate for issue #2065: named volume starts root-owned; the
  # entrypoint must chown it before dropping to the openhuman user, otherwise
  # the first disk write (init_rpc_token → write_token_file) raises EACCES
  # and the process exits with code 1.
  #
  # This job deliberately omits OPENHUMAN_CORE_TOKEN (so the core WILL attempt
  # to write core.token) and mounts a fresh anonymous volume at the workspace
  # path (so Docker creates it root:root).  The existing job above always sets
  # the token and therefore short-circuits the write — it cannot catch this bug.
  docker-volume-permissions:
    name: Smoke-test core with fresh volume and no pre-set token
    runs-on: ubuntu-22.04
    timeout-minutes: 45
    needs: docker-image
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          fetch-depth: 1
          submodules: false

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build openhuman-core image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: Dockerfile
          push: false
          load: true
          tags: openhuman-core:smoke
          cache-from: type=gha,scope=deploy-smoke
          cache-to: type=gha,scope=deploy-smoke,mode=max

      - name: Run container with fresh anonymous volume and no token
        run: |
          docker run -d \
            --name oh-vol-smoke \
            -p 7789:7788 \
            -v oh-vol-smoke-workspace:/home/openhuman/.openhuman \
            -e OPENHUMAN_APP_ENV=staging \
            -e BACKEND_URL=https://staging-api.tinyhumans.ai \
            openhuman-core:smoke

      - name: Wait for /health (volume-permissions path)
        run: |
          set -e
          for i in $(seq 1 30); do
            if curl -fsS http://localhost:7789/health > /tmp/vol-health.json; then
              echo "Healthy on attempt $i"
              cat /tmp/vol-health.json
              exit 0
            fi
            echo "attempt $i: not ready, sleeping..."
            sleep 2
          done
          echo "Container never became healthy. Logs:"
          docker logs oh-vol-smoke || true
          exit 1

      - name: Assert no permission-denied errors in logs
        run: |
          set -e
          if docker logs oh-vol-smoke 2>&1 | grep -q "Permission denied (os error 13)"; then
            echo "FAIL: 'Permission denied (os error 13)' found in container logs"
            docker logs oh-vol-smoke || true
            exit 1
          fi
          echo "PASS: no permission-denied errors in container logs"

      - name: Container logs (always)
        if: always()
        run: docker logs oh-vol-smoke || true

      - name: Tear down
        if: always()
        run: |
          docker rm -f oh-vol-smoke || true
          docker volume rm oh-vol-smoke-workspace || true
