name: 🧰 准备环境

on:
  push:
    # 主分支：下游 sync / thirdparty 消费者只关心 main。
    # 其它分支（含 ci bot 推送的 tsl-playbook / thirdparty/skill 分支）跑 Prepare 纯属空耗，故在此过滤。
    branches:
      - main
  pull_request:
    # PR：为下游 checks 消费者（standards + tests）预备 bare 仓库。
    # PR 的 github.sha 是 Gitea 生成的 merge commit，不在 refs/heads/*，
    # 故下面的 fetch 额外取 PR ref 并按事件类型选校验目标。
    branches:
      - main
  workflow_dispatch:
  schedule:
    # thirdparty 快照每日轮询：Prepare 定时成功后，update-thirdparty-skills 通过 workflow_run 触发。
    - cron: "17 3 * * *"

concurrency:
  group: prepare-${{ github.repository }}
  cancel-in-progress: false

env:
  ACCESS_TOKEN: ${{ secrets.WORKFLOW }}
  WORKSPACE_ROOT: "/data/workspace"

jobs:
  prepare:
    runs-on: standard-ubuntu-22
    permissions:
      contents: read

    steps:
      - name: 🔧 检查并安装共享工具
        id: tools
        shell: bash
        run: |
          set -euo pipefail

          declare -A package_for=(
            [git]="git"
            [python3]="python3"
            [curl]="curl"
            [flock]="util-linux"
            [realpath]="coreutils"
          )
          required_commands=(git python3 curl flock realpath)
          missing_commands=()
          missing_packages=()
          declare -A seen_packages=()

          for command in "${required_commands[@]}"; do
            if ! command -v "$command" >/dev/null 2>&1; then
              package="${package_for[$command]}"
              missing_commands+=("$command")
              if [[ -z "${seen_packages[$package]+x}" ]]; then
                missing_packages+=("$package")
                seen_packages[$package]=1
              fi
            fi
          done

          installed=false
          if [ "${#missing_packages[@]}" -gt 0 ]; then
            echo "缺失命令: ${missing_commands[*]}"
            echo "准备安装: ${missing_packages[*]}"

            if [ "$(id -u)" -eq 0 ]; then
              APT=(apt-get)
            elif command -v sudo >/dev/null 2>&1; then
              APT=(sudo apt-get)
            else
              echo "无法安装缺失命令；当前用户不是 root 且没有 sudo" >&2
              echo "命令: ${missing_commands[*]}" >&2
              echo "包: ${missing_packages[*]}" >&2
              exit 1
            fi

            "${APT[@]}" update -qq
            "${APT[@]}" install -y -qq "${missing_packages[@]}"
            installed=true
          fi

          for command in "${required_commands[@]}"; do
            if ! command -v "$command" >/dev/null 2>&1; then
              echo "安装后仍找不到命令: $command (${package_for[$command]})" >&2
              exit 1
            fi
          done

          {
            echo "## Prepare 环境"
            echo ""
            echo "| 命令 | 版本 |"
            echo "| --- | --- |"
            for command in "${required_commands[@]}"; do
              version_output=$("$command" --version 2>&1 || true)
              version_line=${version_output%%$'\n'*}
              version_line=${version_line//|/\\|}
              printf '| `%s` | `%s` |\n' "$command" "$version_line"
            done
            echo ""
            if [ "$installed" = true ]; then
              echo "安装的包：\`${missing_packages[*]}\`"
            else
              echo "安装的包：无，所有命令已存在。"
            fi
          } >> "$GITHUB_STEP_SUMMARY"

          echo "installed=$installed" >> "$GITHUB_OUTPUT"

      - name: 📥 准备共享 bare 仓库
        shell: bash
        run: |
          set -euo pipefail

          REPO_NAME="${{ github.event.repository.name }}"
          REMOTE_URL="${{ github.server_url }}/${{ github.repository }}.git"
          EVENT_NAME="${{ github.event_name }}"
          REPOSITORY_DIR="${WORKSPACE_ROOT}/${REPO_NAME}/repository.git"

          # 校验目标 SHA 因事件而异：
          # - pull_request：github.sha 是 Gitea 生成的 merge commit，不在
          #   refs/heads/* 里，直接校验会失败；改用 PR head SHA，并在下方额外
          #   fetch PR ref 把 head 提交拉进 bare 仓库。下游 workflow_run 消费者
          #   读到的 head_sha 也正是这个 PR head，两者一致。
          # - 其它事件（push / schedule / dispatch）：沿用 github.sha。
          if [ "$EVENT_NAME" = "pull_request" ]; then
            HEAD_SHA="${{ github.event.pull_request.head.sha }}"
            PR_NUMBER="${{ github.event.pull_request.number }}"
          else
            HEAD_SHA="${{ github.sha }}"
            PR_NUMBER=""
          fi

          case "$HEAD_SHA" in
            ''|*[!0-9a-fA-F]*)
              echo "无效的触发提交 SHA: $HEAD_SHA" >&2
              exit 1
              ;;
          esac
          case "$REMOTE_URL" in
            https://*) ;;
            *)
              echo "拒绝通过非 HTTPS remote 使用 WORKFLOW token: $REMOTE_URL" >&2
              exit 1
              ;;
          esac
          if [ -z "$ACCESS_TOKEN" ]; then
            echo "未配置 WORKFLOW secret，无法读取仓库" >&2
            exit 1
          fi

          mkdir -p "$(dirname "$REPOSITORY_DIR")"
          if [ ! -e "$REPOSITORY_DIR" ]; then
            git init --bare "$REPOSITORY_DIR"
          else
            if [ ! -d "$REPOSITORY_DIR" ]; then
              echo "共享仓库路径存在但不是目录: $REPOSITORY_DIR" >&2
              exit 1
            fi
            if ! is_bare=$(git --git-dir="$REPOSITORY_DIR" rev-parse --is-bare-repository 2>/dev/null) || \
               [ "$is_bare" != "true" ]; then
              echo "共享仓库路径不是有效 bare 仓库: $REPOSITORY_DIR" >&2
              exit 1
            fi
          fi

          if git --git-dir="$REPOSITORY_DIR" remote get-url origin >/dev/null 2>&1; then
            git --git-dir="$REPOSITORY_DIR" remote set-url origin "$REMOTE_URL"
          else
            git --git-dir="$REPOSITORY_DIR" remote add origin "$REMOTE_URL"
          fi

          git \
            -c credential.helper= \
            -c 'credential.helper=!f() { test "$1" = get || exit 0; printf "%s\n" username=oauth2; printf "%s\n" "password=${ACCESS_TOKEN}"; }; f' \
            -c credential.interactive=never \
            --git-dir="$REPOSITORY_DIR" fetch \
            --prune --prune-tags --tags --force origin \
            '+refs/heads/*:refs/remotes/origin/*'

          # PR head 不在 refs/heads/*，按需补取 PR ref 把 head 提交拉进 bare 仓库。
          # 先试 PR head SHA 是否已在库（同仓库分支 PR 的 head 常已随 refs/heads/*
          # 到位），不在再按 PR 号 fetch Gitea 的 refs/pull/<n>/head。
          if [ -n "$PR_NUMBER" ] && \
             ! git --git-dir="$REPOSITORY_DIR" cat-file -e "${HEAD_SHA}^{commit}" 2>/dev/null; then
            git \
              -c credential.helper= \
              -c 'credential.helper=!f() { test "$1" = get || exit 0; printf "%s\n" username=oauth2; printf "%s\n" "password=${ACCESS_TOKEN}"; }; f' \
              -c credential.interactive=never \
              --git-dir="$REPOSITORY_DIR" fetch --force origin \
              "+refs/pull/${PR_NUMBER}/head:refs/remotes/origin/pull/${PR_NUMBER}/head" || true
          fi

          if ! git --git-dir="$REPOSITORY_DIR" cat-file -e "${HEAD_SHA}^{commit}"; then
            echo "共享仓库中不存在触发提交: $HEAD_SHA（事件: $EVENT_NAME）" >&2
            exit 1
          fi

          resolved_sha=$(git --git-dir="$REPOSITORY_DIR" rev-parse "${HEAD_SHA}^{commit}")
          {
            echo ""
            echo "## Prepare 仓库"
            echo ""
            echo "- bare 仓库：\`$REPOSITORY_DIR\`"
            echo "- 触发提交：\`$resolved_sha\`"
            echo "- 远端：\`$REMOTE_URL\`"
          } >> "$GITHUB_STEP_SUMMARY"

          echo "Prepare 完成: $REPOSITORY_DIR @ $resolved_sha"
