name: System images

on:
  workflow_dispatch:
  push:
    branches:
      - main
      - ops/i1-dogfood-deploy
    paths:
      - apps/gateway/**
      - packages/contracts/**
      - infra/gateway/**
      - .github/workflows/system-images.yml

permissions:
  contents: write
  packages: write

concurrency:
  group: system-images-${{ github.ref }}
  cancel-in-progress: true

env:
  MODEL_GATEWAY_IMAGE: ghcr.io/platform-modules/awp-model-gateway
  SUBROUTER_IMAGE: ghcr.io/platform-modules/awp-subrouter
  SUBROUTER_REVISION: 1c5719c702e16d7f458a2b5e20be9084fa88d86b

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout AWP
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Checkout pinned Subrouter source
        uses: actions/checkout@v4
        with:
          repository: manaflow-ai/subrouter
          ref: ${{ env.SUBROUTER_REVISION }}
          path: .system-image-sources/subrouter

      - name: Set up Node 24
        uses: actions/setup-node@v4
        with:
          node-version: 24
          registry-url: https://npm.pkg.github.com
          scope: "@platform-modules"

      - name: Build gateway JavaScript
        env:
          NODE_AUTH_TOKEN: ${{ secrets.PLATFORM_MODULES_NPM_TOKEN || secrets.GITHUB_TOKEN }}
        run: |
          set -euo pipefail
          corepack enable
          corepack prepare pnpm@9.7.0 --activate
          pnpm install --frozen-lockfile
          pnpm --filter @awp/contracts build
          pnpm --filter @awp/gateway build

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

      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and publish model gateway
        id: gateway
        uses: docker/build-push-action@v6
        with:
          context: .
          file: infra/gateway/Dockerfile
          platforms: linux/amd64
          push: true
          tags: ${{ env.MODEL_GATEWAY_IMAGE }}:git-${{ github.sha }}
          labels: |
            org.opencontainers.image.source=https://github.com/${{ github.repository }}
            org.opencontainers.image.revision=${{ github.sha }}

      - name: Build and publish pinned Subrouter
        id: subrouter
        uses: docker/build-push-action@v6
        with:
          context: .system-image-sources/subrouter
          platforms: linux/amd64
          push: true
          tags: ${{ env.SUBROUTER_IMAGE }}:source-${{ env.SUBROUTER_REVISION }}
          labels: |
            org.opencontainers.image.source=https://github.com/manaflow-ai/subrouter
            org.opencontainers.image.revision=${{ env.SUBROUTER_REVISION }}

      - name: Smoke-test published images
        env:
          GATEWAY_DIGEST: ${{ steps.gateway.outputs.digest }}
          SUBROUTER_DIGEST: ${{ steps.subrouter.outputs.digest }}
        run: |
          set -euo pipefail
          gateway="$MODEL_GATEWAY_IMAGE@$GATEWAY_DIGEST"
          subrouter="$SUBROUTER_IMAGE@$SUBROUTER_DIGEST"
          docker pull "$gateway"
          docker pull "$subrouter"
          docker run --rm --entrypoint /usr/local/bin/subrouter "$subrouter" --help >/dev/null
          mkdir -p /tmp/awp-gateway-smoke
          printf 'proxy-smoke\n' > /tmp/awp-gateway-smoke/proxy
          printf 'signing-smoke\n' > /tmp/awp-gateway-smoke/signing
          docker run -d --rm --name awp-model-gateway-smoke \
            -e AWP_SUBROUTER_URL=http://127.0.0.1:31415 \
            -e AWP_SUBROUTER_PROXY_TOKEN_FILE=/run/secrets/proxy \
            -e AWP_MODEL_GATEWAY_SIGNING_SECRET_FILE=/run/secrets/signing \
            -v /tmp/awp-gateway-smoke:/run/secrets:ro \
            "$gateway" >/dev/null
          trap 'docker rm -f awp-model-gateway-smoke >/dev/null 2>&1 || true' EXIT
          for _ in $(seq 1 30); do
            if docker logs awp-model-gateway-smoke 2>&1 | grep -q 'AWP model gateway listening'; then
              exit 0
            fi
            sleep 1
          done
          docker logs awp-model-gateway-smoke >&2
          exit 1

      - name: Record immutable system-image desired state
        env:
          GATEWAY_DIGEST: ${{ steps.gateway.outputs.digest }}
          SUBROUTER_DIGEST: ${{ steps.subrouter.outputs.digest }}
        run: |
          set -euo pipefail
          test -n "$GATEWAY_DIGEST"
          test -n "$SUBROUTER_DIGEST"
          printf '%s@%s\n' "$MODEL_GATEWAY_IMAGE" "$GATEWAY_DIGEST" > infra/dogfood/model-gateway-image.lock
          printf '%s@%s\n' "$SUBROUTER_IMAGE" "$SUBROUTER_DIGEST" > infra/dogfood/subrouter-image.lock

      - name: Commit desired-state digests
        run: |
          set -euo pipefail
          if [ -z "$(git status --porcelain -- infra/dogfood/model-gateway-image.lock infra/dogfood/subrouter-image.lock)" ]; then
            echo "System image digest locks already current."
            exit 0
          fi
          git config user.name "AWP Image Publisher"
          git config user.email "awp-image-publisher@users.noreply.github.com"
          git add infra/dogfood/model-gateway-image.lock infra/dogfood/subrouter-image.lock
          git commit -m "chore(execution): pin published system image digests"
          git push origin "HEAD:${GITHUB_REF_NAME}"
