name: CI/CD

# Decommission (2026-07): trigger switched from push:main to manual only, so
# documentation commits don't rebuild/redeploy images. Run from the Gitea UI
# (Actions → Run workflow) if a rebuild is ever needed again.
on:
  workflow_dispatch:

env:
  REGISTRY: gitea.gitea.svc.cluster.local:3000
  K8S_MANIFESTS_REPO: http://chemavx:${{ secrets.CI_TOKEN }}@gitea.gitea.svc.cluster.local:3000/chemavx/k8s-manifests.git
  GIT_SSL_NO_VERIFY: "true"
  TELEGRAM_CHAT_ID: "5138407666"

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ssl-verify: false
          # Full history: needed to diff against github.event.before
          fetch-depth: 0

      - name: Set image tag
        id: tag
        run: echo "TAG=${GITHUB_SHA::8}" >> $GITHUB_OUTPUT

      - name: Detect changed components
        id: changes
        run: |
          BEFORE="${{ github.event.before }}"
          CHANGED=""
          case "$BEFORE" in
            ""|0000000000000000000000000000000000000000)
              echo "First push or unknown base — building all images"
              CHANGED="__all__"
              ;;
            *)
              if git cat-file -e "$BEFORE" 2>/dev/null; then
                CHANGED=$(git diff --name-only "$BEFORE" "$GITHUB_SHA")
              else
                echo "Base commit $BEFORE not in history (force push?) — building all images"
                CHANGED="__all__"
              fi
              ;;
          esac
          echo "Changed files:"
          echo "$CHANGED"

          if [ "$CHANGED" = "__all__" ]; then
            BOT=true; API=true; DASH=true
          else
            BOT=false; API=false; DASH=false
            matches() { echo "$CHANGED" | grep -qE "$1"; }
            # The workflow itself affects every image build
            if matches '^\.gitea/workflows/ci\.yml$'; then BOT=true; API=true; DASH=true; fi
            # bot and api images both COPY bot/, api/ and requirements.txt
            if matches '^(bot/|api/|requirements\.txt$)'; then BOT=true; API=true; fi
            if matches '^Dockerfile$'; then BOT=true; fi
            if matches '^Dockerfile\.api$'; then API=true; fi
            # dashboard image builds from the dashboard/ context only
            if matches '^dashboard/'; then DASH=true; fi
          fi

          ANY=false
          if [ "$BOT" = "true" ] || [ "$API" = "true" ] || [ "$DASH" = "true" ]; then ANY=true; fi
          echo "build_bot=$BOT"        >> $GITHUB_OUTPUT
          echo "build_api=$API"        >> $GITHUB_OUTPUT
          echo "build_dashboard=$DASH" >> $GITHUB_OUTPUT
          echo "build_any=$ANY"        >> $GITHUB_OUTPUT
          echo "Will build: bot=$BOT api=$API dashboard=$DASH"

      - name: Log in to registry
        if: steps.changes.outputs.build_any == 'true'
        run: echo "${{ secrets.CI_TOKEN }}" | docker login gitea.gitea.svc.cluster.local:3000 -u chemavx --password-stdin

      - name: Create buildx builder
        if: steps.changes.outputs.build_any == 'true'
        run: |
          cat > /tmp/buildkitd.toml << 'EOF'
          [registry."registry-cache.registry-cache.svc.cluster.local:5000"]
            http = true
            insecure = true

          [registry."gitea.gitea.svc.cluster.local:3000"]
            http = true
            insecure = true

          [registry."docker.io"]
            mirrors = ["registry-cache.registry-cache.svc.cluster.local:5000"]
          EOF
          docker buildx create \
            --name ci-builder \
            --driver docker-container \
            --driver-opt network=host \
            --config /tmp/buildkitd.toml \
            --use
          docker buildx inspect --bootstrap

      - name: Build and push bot image
        if: steps.changes.outputs.build_bot == 'true'
        run: |
          TAG=${{ steps.tag.outputs.TAG }}
          docker buildx build \
            --builder ci-builder \
            --cache-from type=registry,ref=gitea.gitea.svc.cluster.local:3000/chemavx/polymarket-bot:buildcache \
            --cache-to type=registry,ref=gitea.gitea.svc.cluster.local:3000/chemavx/polymarket-bot:buildcache,mode=max \
            -t gitea.gitea.svc.cluster.local:3000/chemavx/polymarket-bot:${TAG} \
            --push \
            -f Dockerfile .

      - name: Build and push API image
        if: steps.changes.outputs.build_api == 'true'
        run: |
          TAG=${{ steps.tag.outputs.TAG }}
          docker buildx build \
            --builder ci-builder \
            --cache-from type=registry,ref=gitea.gitea.svc.cluster.local:3000/chemavx/polymarket-bot-api:buildcache \
            --cache-to type=registry,ref=gitea.gitea.svc.cluster.local:3000/chemavx/polymarket-bot-api:buildcache,mode=max \
            -t gitea.gitea.svc.cluster.local:3000/chemavx/polymarket-bot-api:${TAG} \
            --push \
            -f Dockerfile.api .

      - name: Build and push dashboard image
        if: steps.changes.outputs.build_dashboard == 'true'
        run: |
          TAG=${{ steps.tag.outputs.TAG }}
          docker buildx build \
            --builder ci-builder \
            --cache-from type=registry,ref=gitea.gitea.svc.cluster.local:3000/chemavx/polymarket-bot-dashboard:buildcache \
            --cache-to type=registry,ref=gitea.gitea.svc.cluster.local:3000/chemavx/polymarket-bot-dashboard:buildcache,mode=max \
            -t gitea.gitea.svc.cluster.local:3000/chemavx/polymarket-bot-dashboard:${TAG} \
            --push \
            -f dashboard/Dockerfile \
            dashboard

      - name: Verify images in registry
        if: steps.changes.outputs.build_any == 'true'
        run: |
          TAG=${{ steps.tag.outputs.TAG }}
          check_image() {
            local image=$1
            HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
              -u "chemavx:${{ secrets.CI_TOKEN }}" \
              -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
              "http://gitea.gitea.svc.cluster.local:3000/v2/chemavx/${image}/manifests/${TAG}")
            if [ "$HTTP_CODE" != "200" ]; then
              echo "ERROR: chemavx/${image}:${TAG} not found in registry (HTTP $HTTP_CODE)"
              exit 1
            fi
            echo "OK: chemavx/${image}:${TAG} verified in registry"
          }
          if [ "${{ steps.changes.outputs.build_bot }}" = "true" ]; then
            check_image polymarket-bot
          fi
          if [ "${{ steps.changes.outputs.build_api }}" = "true" ]; then
            check_image polymarket-bot-api
          fi
          if [ "${{ steps.changes.outputs.build_dashboard }}" = "true" ]; then
            check_image polymarket-bot-dashboard
          fi

      - name: Update k8s manifests
        if: steps.changes.outputs.build_any == 'true'
        run: |
          pip3 install pyyaml -q

          TAG=${{ steps.tag.outputs.TAG }}

          git config --global user.email "ci@git.chemavx.xyz"
          git config --global user.name "Gitea CI"

          git clone ${{ env.K8S_MANIFESTS_REPO }} /tmp/k8s-manifests
          cd /tmp/k8s-manifests

          # Only bump the tag of images that were actually rebuilt: the others
          # keep their current (still existing) tag in the registry.
          if [ "${{ steps.changes.outputs.build_bot }}" = "true" ]; then
            sed -i "s|image: .*polymarket-bot[^-].*|image: git.chemavx.xyz/chemavx/polymarket-bot:${TAG}|g" \
              polymarket-bot/deployment-bot.yaml \
              polymarket-bot/cronjob-outcomes.yaml
          fi
          if [ "${{ steps.changes.outputs.build_api }}" = "true" ]; then
            sed -i "s|image: .*polymarket-bot-api.*|image: git.chemavx.xyz/chemavx/polymarket-bot-api:${TAG}|g" \
              polymarket-bot/deployment-api.yaml
          fi
          if [ "${{ steps.changes.outputs.build_dashboard }}" = "true" ]; then
            sed -i "s|image: .*polymarket-bot-dashboard.*|image: git.chemavx.xyz/chemavx/polymarket-bot-dashboard:${TAG}|g" \
              polymarket-bot/deployment-dashboard.yaml
          fi
          sed -i "s|imagePullPolicy: Never|imagePullPolicy: Always|g" \
            polymarket-bot/deployment-bot.yaml \
            polymarket-bot/deployment-api.yaml \
            polymarket-bot/deployment-dashboard.yaml

          python3 -c "
          import yaml, sys
          files = [
              'polymarket-bot/deployment-bot.yaml',
              'polymarket-bot/deployment-api.yaml',
              'polymarket-bot/deployment-dashboard.yaml',
          ]
          errors = []
          for f in files:
              try:
                  yaml.safe_load(open(f))
                  print('OK: ' + f)
              except yaml.YAMLError as e:
                  errors.append('FAIL: ' + f + ': ' + str(e))
          if errors:
              for e in errors: print(e, file=sys.stderr)
              sys.exit(1)
          "

          git add polymarket-bot/deployment-bot.yaml polymarket-bot/deployment-api.yaml polymarket-bot/deployment-dashboard.yaml
          git diff --cached --quiet || git commit -m "ci: update polymarket-bot images to ${TAG} [skip ci]"
          git push

      - name: Notify Telegram
        if: always()
        env:
          TAG: ${{ steps.tag.outputs.TAG }}
          JOB_STATUS: ${{ job.status }}
          TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
          BUILD_BOT: ${{ steps.changes.outputs.build_bot }}
          BUILD_API: ${{ steps.changes.outputs.build_api }}
          BUILD_DASH: ${{ steps.changes.outputs.build_dashboard }}
        run: |
          TAG="${TAG:-${GITHUB_SHA:0:8}}"
          BUILT=""
          [ "$BUILD_BOT" = "true" ]  && BUILT="${BUILT}bot "
          [ "$BUILD_API" = "true" ]  && BUILT="${BUILT}api "
          [ "$BUILD_DASH" = "true" ] && BUILT="${BUILT}dashboard "
          if [ "$JOB_STATUS" = "success" ]; then
            if [ -n "$BUILT" ]; then
              MSG="✅ Deploy polymarket-bot:${TAG} completado (imágenes: ${BUILT% })"
            else
              MSG="✅ CI polymarket-bot:${TAG} OK — sin cambios de imagen, nada que desplegar"
            fi
          else
            MSG="❌ Deploy polymarket-bot:${TAG} fallido (status: ${JOB_STATUS})"
          fi
          curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
            -d "chat_id=${{ env.TELEGRAM_CHAT_ID }}" \
            --data-urlencode "text=${MSG}"
