name: "Production: Deploy Bot"
run-name: "Production: Deploy Bot"

on:
  push:
    branches:
      - main
    paths:
      - 'bot/**'
      - 'bin/**'
      - 'deploy/**'
      - '.github/workflows/deploy-bot.yml'
  workflow_dispatch:

concurrency:
  group: deploy-gemmbot
  cancel-in-progress: false

jobs:
  deploy-bot:
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup SSH
        env:
          EC2_HOST: ${{ secrets.EC2_HOST }}
          EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
        run: |
          mkdir -p ~/.ssh
          echo "$EC2_SSH_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H $EC2_HOST >> ~/.ssh/known_hosts

      - name: Write bot .env on EC2
        env:
          EC2_HOST: ${{ secrets.EC2_HOST }}
          EC2_USER: ${{ secrets.EC2_USER }}
          ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }}
        run: |
          cat > /tmp/bot.env << EOF
          DEPLOYMENT_NAME=gemmbot
          AUTH_MODE=multi_user
          DATABASE_URL=file:/opt/gemmbot/data/gemmbot.db
          ENCRYPTION_KEY=${ENCRYPTION_KEY}
          CADDY_ADMIN_API=http://localhost:2019
          BASE_DOMAIN=gemmbot.gemmaanalytics.com
          REPOS_DIR=/opt/gemmbot/repos
          DATA_DIR=/opt/gemmbot/data
          BOT_ADMIN_PORT=7900
          SECRET_DROPOFF_PORT=7899
          MANAGEMENT_URL=https://gemmbot.gemmaanalytics.com
          GIT_USER_NAME=Gemmbot
          GIT_USER_EMAIL=gemmbot[bot]@users.noreply.github.com
          EOF
          # Strip leading whitespace from heredoc
          sed -i 's/^          //' /tmp/bot.env
          scp -i ~/.ssh/deploy_key /tmp/bot.env $EC2_USER@$EC2_HOST:/tmp/bot.env
          ssh -i ~/.ssh/deploy_key $EC2_USER@$EC2_HOST "sudo mv /tmp/bot.env /opt/gemmbot/bot/.env && sudo chown gemmbot:gemmbot /opt/gemmbot/bot/.env && sudo chmod 640 /opt/gemmbot/bot/.env"
          rm /tmp/bot.env

      - name: Deploy bot code
        env:
          EC2_HOST: ${{ secrets.EC2_HOST }}
          EC2_USER: ${{ secrets.EC2_USER }}
        run: |
          rsync -rlvz --delete --omit-dir-times \
            -e "ssh -i ~/.ssh/deploy_key" \
            --exclude node_modules \
            --exclude .env \
            bot/ $EC2_USER@$EC2_HOST:/opt/gemmbot/bot/

          rsync -rlvz --omit-dir-times \
            -e "ssh -i ~/.ssh/deploy_key" \
            bin/ $EC2_USER@$EC2_HOST:/opt/gemmbot/bin/

      - name: Provision sudoers rules
        env:
          EC2_HOST: ${{ secrets.EC2_HOST }}
          EC2_USER: ${{ secrets.EC2_USER }}
        run: |
          cat > /tmp/gemmbot-sudoers << 'SUDOEOF'
          # gemmbot needs to create/delete Linux users for session isolation
          # and run commands as those users (sudo -u gemmbot-xxx ...)
          gemmbot ALL=(root) NOPASSWD: /usr/sbin/useradd --create-home --shell /bin/bash --groups docker\,gemmbot-sessions gemmbot-*
          gemmbot ALL=(root) NOPASSWD: /usr/sbin/userdel --remove gemmbot-*
          gemmbot ALL=(root) NOPASSWD: /usr/sbin/usermod *
          gemmbot ALL=(root) NOPASSWD: /bin/chmod 710 /home/gemmbot-*
          gemmbot ALL=(root) NOPASSWD: /usr/bin/pkill * gemmbot-*
          gemmbot ALL=(root) NOPASSWD: /usr/bin/id gemmbot-*
          gemmbot ALL=(root) NOPASSWD: /bin/mv /tmp/gemmbot-* *
          gemmbot ALL=(root) NOPASSWD: /bin/chown gemmbot-*\:gemmbot-* *
          gemmbot ALL=(root) NOPASSWD: /bin/chmod *
          gemmbot ALL=(root) NOPASSWD: /bin/su - gemmbot-* -c *
          # Allow gemmbot to run any command as any gemmbot-* user
          gemmbot ALL=(gemmbot-*) NOPASSWD: ALL
          # VPN: session users (gemmbot-sessions group) need to enter the network namespace and start it
          %gemmbot-sessions ALL=(root) NOPASSWD: /usr/bin/ip netns exec ns-gemma *
          %gemmbot-sessions ALL=(root) NOPASSWD: /usr/local/bin/vpn-ns up
          SUDOEOF
          sed -i 's/^          //' /tmp/gemmbot-sudoers
          scp -i ~/.ssh/deploy_key /tmp/gemmbot-sudoers $EC2_USER@$EC2_HOST:/tmp/gemmbot-sudoers
          ssh -i ~/.ssh/deploy_key $EC2_USER@$EC2_HOST "
            echo '### Provisioning sudoers rules for gemmbot ###'
            sudo mv /tmp/gemmbot-sudoers /etc/sudoers.d/gemmbot
            sudo chown root:root /etc/sudoers.d/gemmbot
            sudo chmod 440 /etc/sudoers.d/gemmbot
            sudo visudo -c
            echo '### Sudoers rules provisioned ###'
          "
          rm -f /tmp/gemmbot-sudoers

      - name: Fix existing home directory permissions
        env:
          EC2_HOST: ${{ secrets.EC2_HOST }}
          EC2_USER: ${{ secrets.EC2_USER }}
        run: |
          ssh -i ~/.ssh/deploy_key $EC2_USER@$EC2_HOST "
            echo '### Fixing home dir permissions for existing users ###'
            for d in /home/gemmbot-*/; do
              [ -d \"\$d\" ] && sudo chmod 710 \"\$d\"
            done
            echo '### Home dir permissions fixed ###'
          "

      - name: Install dependencies, migrate, restart
        env:
          EC2_HOST: ${{ secrets.EC2_HOST }}
          EC2_USER: ${{ secrets.EC2_USER }}
        run: |
          ssh -i ~/.ssh/deploy_key $EC2_USER@$EC2_HOST "
            echo '### Stopping services (to release DB locks) ###'
            sudo systemctl stop gemmbot || true
            sudo systemctl stop gemmbot-ui || true

            echo '### Ensuring gemmbot-sessions group exists ###'
            sudo groupadd -f gemmbot-sessions
            # Add existing session users to the group
            for u in \$(getent passwd | grep '^gemmbot-' | cut -d: -f1); do
              sudo usermod -aG gemmbot-sessions \"\$u\" 2>/dev/null || true
            done

            cd /opt/gemmbot/bot
            echo '### Installing dependencies ###'
            npm ci

            echo '### Symlinking Prisma client from UI ###'
            rm -rf /opt/gemmbot/bot/node_modules/.prisma
            ln -s /opt/gemmbot/ui/node_modules/.prisma /opt/gemmbot/bot/node_modules/.prisma

            echo '### Ensuring Claude CLI is installed globally ###'
            sudo npm install -g @anthropic-ai/claude-code || true

            echo '### Setting up VPN helper scripts ###'
            # Copy (not symlink) so session users can execute them without
            # needing traverse permissions on /opt/gemmbot/
            sudo rm -rf /usr/local/bin/vpn-exec /usr/local/bin/vpn-ns
            sudo cp /opt/gemmbot/bin/vpn-exec /usr/local/bin/vpn-exec
            sudo cp /opt/gemmbot/bin/vpn-ns /usr/local/bin/vpn-ns
            sudo chmod 755 /usr/local/bin/vpn-exec /usr/local/bin/vpn-ns

            echo '### Fixing data dir permissions ###'
            sudo chown -R gemmbot:gemmbot /opt/gemmbot/data
            sudo chmod -R g+rw /opt/gemmbot/data

            echo '### Running database migrations ###'
            cd /opt/gemmbot/ui
            npx prisma migrate deploy

            echo '### Fixing data dir permissions ###'
            sudo chown -R gemmbot:gemmbot /opt/gemmbot/data
            sudo chmod -R g+rw /opt/gemmbot/data

            echo '### Starting services ###'
            sudo systemctl start gemmbot-ui
            sudo systemctl start gemmbot

            echo '### Bot deployment complete ###'
          "
