name: Pub Docker Img

on:
    push:
        branches: [main]
        tags: ["v*"]
        paths:
            - "Dockerfile"
            - ".dockerignore"
            - "Cargo.toml"
            - "Cargo.lock"
            - "rust-toolchain.toml"
            - "src/**"
            - "crates/**"
            - "benches/**"
            - "firmware/**"
            - "dev/config.template.toml"
            - ".github/workflows/pub-docker-img.yml"
    pull_request:
        branches: [main]
        paths:
            - "Dockerfile"
            - ".dockerignore"
            - "Cargo.toml"
            - "Cargo.lock"
            - "rust-toolchain.toml"
            - "src/**"
            - "crates/**"
            - "benches/**"
            - "firmware/**"
            - "dev/config.template.toml"
            - ".github/workflows/pub-docker-img.yml"
    workflow_dispatch:

concurrency:
    group: docker-${{ github.event.pull_request.number || github.ref }}
    cancel-in-progress: true

env:
    REGISTRY: ghcr.io
    IMAGE_NAME: ${{ github.repository }}

jobs:
    pr-smoke:
        name: PR Docker Smoke
        if: github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
        runs-on: blacksmith-2vcpu-ubuntu-2404
        timeout-minutes: 25
        permissions:
            contents: read
        steps:
            - name: Checkout repository
              uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

            - name: Setup Blacksmith Builder
              uses: useblacksmith/setup-docker-builder@ef12d5b165b596e3aa44ea8198d8fde563eab402 # v1

            - name: Extract metadata (tags, labels)
              if: github.event_name == 'pull_request'
              id: meta
              uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5
              with:
                  images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
                  tags: |
                      type=ref,event=pr

            - name: Build smoke image
              uses: useblacksmith/build-push-action@30c71162f16ea2c27c3e21523255d209b8b538c1 # v2
              with:
                  context: .
                  push: false
                  load: true
                  provenance: false
                  sbom: false
                  tags: zeroclaw-pr-smoke:latest
                  labels: ${{ steps.meta.outputs.labels || '' }}
                  platforms: linux/amd64

            - name: Verify image
              run: docker run --rm zeroclaw-pr-smoke:latest --version

    publish:
        name: Build and Push Docker Image
        if: (github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))) && github.repository == 'zeroclaw-labs/zeroclaw'
        runs-on: blacksmith-2vcpu-ubuntu-2404
        timeout-minutes: 25
        permissions:
            contents: read
            packages: write
        steps:
            - name: Checkout repository
              uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

            - name: Setup Blacksmith Builder
              uses: useblacksmith/setup-docker-builder@ef12d5b165b596e3aa44ea8198d8fde563eab402 # v1

            - name: Log in to Container Registry
              uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
              with:
                  registry: ${{ env.REGISTRY }}
                  username: ${{ github.actor }}
                  password: ${{ secrets.GITHUB_TOKEN }}

            - name: Compute tags
              id: meta
              shell: bash
              run: |
                  set -euo pipefail
                  IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
                  SHA_TAG="${IMAGE}:sha-${GITHUB_SHA::12}"

                  if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
                    TAG_NAME="${GITHUB_REF#refs/tags/}"
                    TAGS="${IMAGE}:${TAG_NAME},${SHA_TAG}"
                  elif [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
                    TAGS="${IMAGE}:latest,${SHA_TAG}"
                  else
                    BRANCH_NAME="${GITHUB_REF#refs/heads/}"
                    BRANCH_NAME="${BRANCH_NAME//\//-}"
                    TAGS="${IMAGE}:${BRANCH_NAME},${SHA_TAG}"
                  fi

                  echo "tags=${TAGS}" >> "$GITHUB_OUTPUT"

            - name: Build and push Docker image
              uses: useblacksmith/build-push-action@30c71162f16ea2c27c3e21523255d209b8b538c1 # v2
              with:
                  context: .
                  push: true
                  tags: ${{ steps.meta.outputs.tags }}
                  platforms: ${{ startsWith(github.ref, 'refs/tags/v') && 'linux/amd64,linux/arm64' || 'linux/amd64' }}

            - name: Set GHCR package visibility to public
              shell: bash
              env:
                  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
              run: |
                  set -euo pipefail
                  owner="${GITHUB_REPOSITORY_OWNER,,}"
                  repo="${GITHUB_REPOSITORY#*/}"

                  # Package path can vary depending on repository/package linkage.
                  candidates=(
                    "$repo"
                    "${owner}%2F${repo}"
                  )

                  for scope in orgs users; do
                    for pkg in "${candidates[@]}"; do
                      code="$(curl -sS -o /tmp/ghcr-visibility.json -w "%{http_code}" \
                        -X PATCH \
                        -H "Authorization: Bearer ${GH_TOKEN}" \
                        -H "Accept: application/vnd.github+json" \
                        -H "X-GitHub-Api-Version: 2022-11-28" \
                        "https://api.github.com/${scope}/${owner}/packages/container/${pkg}/visibility" \
                        -d '{"visibility":"public"}' || true)"

                      if [ "$code" = "200" ] || [ "$code" = "204" ]; then
                        echo "GHCR package visibility is public (${scope}/${owner}/${pkg})."
                        exit 0
                      fi

                      echo "Visibility attempt ${scope}/${owner}/${pkg} returned HTTP ${code}."
                    done
                  done

                  echo "::warning::Unable to update GHCR visibility via API in this run; proceeding to direct anonymous pull verification."

            - name: Verify anonymous GHCR pull access
              shell: bash
              run: |
                  set -euo pipefail
                  token_resp="$(curl -sS "https://ghcr.io/token?scope=repository:${GITHUB_REPOSITORY}:pull")"
                  token="$(echo "$token_resp" | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')"

                  if [ -z "$token" ]; then
                    echo "::error::Anonymous GHCR token request failed: $token_resp"
                    exit 1
                  fi

                  code="$(curl -sS -o /tmp/ghcr-manifest.json -w "%{http_code}" \
                    -H "Authorization: Bearer ${token}" \
                    -H "Accept: application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.v2+json" \
                    "https://ghcr.io/v2/${GITHUB_REPOSITORY}/manifests/latest")"

                  if [ "$code" != "200" ]; then
                    echo "::error::Anonymous manifest pull failed with HTTP ${code}"
                    cat /tmp/ghcr-manifest.json || true
                    exit 1
                  fi

                  echo "Anonymous GHCR pull access verified."
