name: Community Docker
run-name: Community Docker ${{ inputs.version }}

on:
  workflow_call:
    inputs:
      version:
        description: Image version
        required: true
        type: string
      push_latest:
        description: Also update the latest tag
        required: true
        type: boolean
    secrets:
      DOCKER_USERNAME:
        required: true
      DOCKERHUB_TOKEN:
        required: true

permissions:
  contents: read

jobs:
  docker:
    name: Build and push Community image
    runs-on: ubuntu-latest
    environment: community-release
    steps:
      - name: Check out repository
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

      - name: Resolve image metadata
        id: image
        shell: bash
        env:
          INPUT_VERSION: ${{ inputs.version }}
          INPUT_PUSH_LATEST: ${{ inputs.push_latest }}
          GITHUB_REF_TYPE: ${{ github.ref_type }}
          GITHUB_REF_NAME: ${{ github.ref_name }}
        run: |
          set -euo pipefail
          version="${INPUT_VERSION}"
          push_latest="${INPUT_PUSH_LATEST}"

          if [ "${GITHUB_REF_TYPE}" != "tag" ] || [ "${GITHUB_REF_NAME}" != "v${version}" ]; then
            echo "Community Docker publication requires the matching protected release tag: expected=v${version}, ref=${GITHUB_REF_TYPE}:${GITHUB_REF_NAME}" >&2
            exit 1
          fi

          if [[ ! "${version}" =~ ^(0|[1-9][0-9]{0,2})\.(0|[1-9][0-9]{0,2})\.(0|[1-9][0-9]{0,4})$ ]]; then
            echo "Version must use numeric SemVer without a v prefix, for example 5.3.0: ${version}" >&2
            exit 1
          fi

          major="${BASH_REMATCH[1]}"
          minor="${BASH_REMATCH[2]}"
          patch="${BASH_REMATCH[3]}"
          if [ "${major}" -lt 4 ]; then
            echo "Public Community images start at major version 4: ${version}" >&2
            exit 1
          fi
          if [ "${major}" -gt 255 ] || [ "${minor}" -gt 255 ] || [ "${patch}" -gt 65535 ]; then
            echo "Version exceeds the Windows release version limits: ${version}" >&2
            exit 1
          fi
          if [ "${push_latest}" != "true" ] && [ "${push_latest}" != "false" ]; then
            echo "push_latest must be true or false: ${push_latest}" >&2
            exit 1
          fi

          {
            echo "version=${version}"
            echo "tags<<EOF"
            echo "chat2db/chat2db:${version}"
            if [ "${push_latest}" = "true" ]; then
              echo "chat2db/chat2db:latest"
            fi
            echo "EOF"
          } >> "${GITHUB_OUTPUT}"

      - name: Set up Node.js
        uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
        with:
          node-version: 22.22.2
          cache: yarn
          cache-dependency-path: chat2db-community-client/yarn.lock

      - name: Build Community frontend
        working-directory: chat2db-community-client
        run: |
          yarn install --frozen-lockfile
          UMI_PublicPath=/static/front/ yarn run build:web:community --app_version="${{ steps.image.outputs.version }}"

      - name: Stage frontend for Spring Boot
        shell: bash
        run: |
          set -euo pipefail
          resources=chat2db-community-server/chat2db-community-start/src/main/resources
          rm -rf "${resources}/static/front"
          mkdir -p "${resources}/static/front" "${resources}/thymeleaf"
          cp -R chat2db-community-client/dist/. "${resources}/static/front/"
          cp chat2db-community-client/dist/index.html "${resources}/thymeleaf/index.html"

      - name: Set up JDK 17
        uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00
        with:
          distribution: temurin
          java-version: "17"
          cache: maven

      - name: Package Community backend
        shell: bash
        run: |
          set -euo pipefail
          mvn -B clean package \
            -Dmaven.test.skip=true \
            -Dchat2db.finalName=chat2db-community \
            -f chat2db-community-server/pom.xml \
            -pl chat2db-community-start \
            -am
          test -f chat2db-community-server/chat2db-community-start/target/chat2db-community.jar
          test -d chat2db-community-server/chat2db-community-start/target/lib

      - name: Smoke test Community image
        shell: bash
        run: |
          set -euo pipefail
          image=chat2db-community:smoke
          container=chat2db-community-smoke
          key_file="${RUNNER_TEMP}/chat2db-community-encryption.key"

          umask 077
          openssl rand -base64 32 > "${key_file}"
          chmod 600 "${key_file}"

          cleanup() {
            docker rm --force "${container}" >/dev/null 2>&1 || true
            docker image rm "${image}" >/dev/null 2>&1 || true
            rm -f "${key_file}"
          }
          trap cleanup EXIT

          docker build \
            --tag "${image}" \
            --file docker/Dockerfile \
            chat2db-community-server/chat2db-community-start/target
          docker run \
            --detach \
            --name "${container}" \
            --publish 127.0.0.1:18025:10825 \
            --env CHAT2DB_COMMUNITY_ENCRYPTION_KEY_FILE=/run/secrets/chat2db-community-encryption.key \
            --volume "${key_file}:/run/secrets/chat2db-community-encryption.key:ro" \
            "${image}"

          for attempt in {1..60}; do
            if curl --fail --silent --show-error http://127.0.0.1:18025/ --output /tmp/index.html; then
              break
            fi
            if [ "${attempt}" -eq 60 ]; then
              docker logs "${container}"
              exit 1
            fi
            sleep 1
          done

          grep --quiet 'src="/static/front/umi.js"' /tmp/index.html
          curl --fail --silent --show-error \
            --dump-header /tmp/umi.headers \
            http://127.0.0.1:18025/static/front/umi.js \
            --output /tmp/umi.js
          grep --extended-regexp --ignore-case --quiet \
            '^content-type:[[:space:]]*(text|application)/javascript' \
            /tmp/umi.headers
          test "$(wc --bytes < /tmp/umi.js)" -gt 100000

      - name: Set up QEMU
        uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392

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

      - name: Log in to Docker Hub
        uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push image
        uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
        with:
          context: chat2db-community-server/chat2db-community-start/target
          file: docker/Dockerfile
          push: true
          platforms: linux/amd64,linux/arm64
          tags: ${{ steps.image.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max