name: sync-project-tree

# Keeps this repo's file-layout snapshot (docs/website/PROJECT_TREE.md in the
# RunicGateway/docs repo) current. On every push to `main` it regenerates the
# tree from tracked files and, if it changed, opens (or force-updates) a pull
# request against the docs repo. It never writes to the docs repo's `main`
# directly. Auth reuses the same REGISTRY_USER / REGISTRY_TOKEN secrets the
# other workflows use (the token needs repo read/write on RunicGateway/docs).

on:
  push:
    branches: [main]
  workflow_dispatch: {}

concurrency:
  group: sync-project-tree
  cancel-in-progress: true

env:
  GITEA_HOST: gitea.whitlocktech.com
  DOCS_REPO: RunicGateway/docs
  SELF_REPO: RunicGateway/website
  DOCS_PATH: website/PROJECT_TREE.md
  TREE_TITLE: Website
  ROOT_LABEL: website
  PR_BRANCH: chore/sync-website-tree

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - name: Check out this repo
        uses: actions/checkout@v4
        with:
          fetch-depth: 1

      - name: Ensure python3 is available
        run: |
          set -euo pipefail
          command -v python3 >/dev/null 2>&1 || { sudo apt-get update -qq && sudo apt-get install -y -qq python3; }

      - name: Render PROJECT_TREE.md from tracked files
        run: |
          set -euo pipefail
          mkdir -p _sync
          {
            printf '# %s — Project Tree\n\n' "${TREE_TITLE}"
            printf '> **Auto-generated.** This file is maintained by the `sync-project-tree` CI workflow in\n'
            printf '> the [`%s`](https://%s/%s) repository, which\n' "${SELF_REPO}" "${GITEA_HOST}" "${SELF_REPO}"
            printf '> opens a pull request here whenever the tracked file layout on `main` changes. Do not edit\n'
            printf '> by hand — changes will be overwritten by the next sync.\n\n'
            printf 'A snapshot of the tracked files in the repository (build output, dependencies, and other\n'
            printf 'git-ignored paths are excluded).\n\n'
            printf '```text\n'
            git ls-files | python3 .gitea/scripts/gen_tree.py "${ROOT_LABEL}"
            printf '```\n'
          } > _sync/PROJECT_TREE.md
          echo "----- generated ${DOCS_PATH} -----"
          cat _sync/PROJECT_TREE.md

      - name: Open or update the docs PR if the tree changed
        env:
          REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
          REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
        run: |
          set -euo pipefail
          # Secrets can carry a trailing CR/LF depending on how they were pasted;
          # strip line breaks before they land in a URL or Authorization header.
          CI_USER="$(printf '%s' "${REGISTRY_USER}" | tr -d '\r\n')"
          CI_TOKEN="$(printf '%s' "${REGISTRY_TOKEN}" | tr -d '\r\n')"
          API="https://${GITEA_HOST}/api/v1/repos/${DOCS_REPO}"
          REMOTE="https://${CI_USER}:${CI_TOKEN}@${GITEA_HOST}/${DOCS_REPO}.git"

          git clone --depth 1 "${REMOTE}" docs_repo
          cd docs_repo
          git config user.name  "runic-docs-bot"
          git config user.email "ci@whitlocktech.com"

          mkdir -p "$(dirname "${DOCS_PATH}")"
          cp ../_sync/PROJECT_TREE.md "${DOCS_PATH}"
          git add "${DOCS_PATH}"
          if git diff --cached --quiet; then
            echo "PROJECT_TREE.md already up to date — nothing to sync."
            exit 0
          fi

          SHORT_SHA="$(echo "${GITHUB_SHA:-local}" | cut -c1-7)"
          git checkout -B "${PR_BRANCH}"
          git commit -m "docs(tree): sync ${DOCS_PATH} from ${SELF_REPO}@${SHORT_SHA} [skip ci]"
          git push --force "${REMOTE}" "HEAD:${PR_BRANCH}"

          # Open a PR only if one isn't already open for this branch (a force-push
          # to an existing open PR's head updates it in place).
          OPEN="$(curl -sSf -H "Authorization: token ${CI_TOKEN}" \
            "${API}/pulls?state=open&limit=50" \
            | jq --arg b "${PR_BRANCH}" '[.[] | select(.head.ref == $b)] | length')"
          if [ "${OPEN}" = "0" ]; then
            curl -sSf -X POST "${API}/pulls" \
              -H "Authorization: token ${CI_TOKEN}" \
              -H "Content-Type: application/json" \
              -d "$(jq -n \
                    --arg head "${PR_BRANCH}" \
                    --arg base "main" \
                    --arg title "docs(tree): sync ${DOCS_PATH}" \
                    --arg body "Automated project-tree sync from [\`${SELF_REPO}\`](https://${GITEA_HOST}/${SELF_REPO}), regenerated from tracked files on \`main\`. Merge once the layout looks right; the workflow will keep this branch current until then." \
                    '{head: $head, base: $base, title: $title, body: $body}')" \
              >/dev/null
            echo "Opened a new docs PR for ${PR_BRANCH}."
          else
            echo "Existing open docs PR for ${PR_BRANCH} was updated via force-push."
          fi
