catalog-refresh #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Refresh the committed site catalog from live AgentFront conformance. | |
| # | |
| # tools.culture.dev (M3) is hosted on Cloudflare Pages via git-integration, which | |
| # builds site-astro/ from the *committed* catalog.json. So as sibling tools change | |
| # versions or cross the conformance line, the live index goes stale until the | |
| # catalog is regenerated. This job does that regeneration on a schedule (and on | |
| # demand) and opens a PR — it never commits to main directly, so a human reviews | |
| # the version/conformance diff before a merge triggers the CF rebuild. | |
| # | |
| # Status: needs a first `workflow_dispatch` run to validate in CI. | |
| # Secrets (both optional): | |
| # SIBLING_REPOS_TOKEN read-access PAT to clone *private* siblings; public | |
| # ones clone with the default GITHUB_TOKEN. Without it, | |
| # private siblings are reported as excluded. | |
| # CATALOG_REFRESH_PR_TOKEN write PAT / App token for opening the refresh PR. | |
| # Only needed if you want that PR to trigger CI — PRs | |
| # opened by the default GITHUB_TOKEN do not. Falls back | |
| # to GITHUB_TOKEN (which can still open the PR). | |
| name: catalog-refresh | |
| on: | |
| schedule: | |
| - cron: "0 6 * * 1" # Mondays 06:00 UTC | |
| workflow_dispatch: {} | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| concurrency: | |
| group: catalog-refresh | |
| cancel-in-progress: false | |
| jobs: | |
| refresh: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout culture-tools | |
| uses: actions/checkout@v4 | |
| - name: Set up uv + Python | |
| uses: astral-sh/setup-uv@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install culture-tools (+ dev deps) | |
| run: uv sync | |
| - name: Install the AgentFront auditor | |
| run: | | |
| uv tool install agentfront | |
| echo "$HOME/.local/bin" >> "$GITHUB_PATH" | |
| - name: Clone candidate sibling repos (from the manifest) | |
| env: | |
| GH_TOKEN: ${{ secrets.SIBLING_REPOS_TOKEN || secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p _siblings | |
| # Keep the token out of clone URLs and the cloned repos' git config: feed | |
| # it through GIT_ASKPASS instead, so the URL carries only the | |
| # x-access-token *username* (not a secret) and nothing is persisted. | |
| askpass="$RUNNER_TEMP/askpass.sh" | |
| printf '#!/bin/sh\necho "$GH_TOKEN"\n' > "$askpass" | |
| chmod +x "$askpass" | |
| export GIT_ASKPASS="$askpass" GIT_TERMINAL_PROMPT=0 | |
| # The manifest is the single source of truth for what to fetch — emit | |
| # "<owner/repo>\t<dir>" rows so this never drifts from the Python list. | |
| uv run python - > _siblings/manifest.tsv <<'PY' | |
| from culture_tools.index import candidates | |
| for tool in candidates(): | |
| print(f"{tool.repo}\t{tool.repo_dir}") | |
| PY | |
| while IFS=$'\t' read -r repo dir; do | |
| [ -z "${repo:-}" ] && continue | |
| echo "::group::clone $repo -> _siblings/$dir" | |
| git clone --depth 1 \ | |
| "https://x-access-token@github.com/${repo}.git" \ | |
| "_siblings/$dir" \ | |
| || echo "skip: could not clone $repo (private/missing) — it will be excluded" | |
| echo "::endgroup::" | |
| done < _siblings/manifest.tsv | |
| rm -f _siblings/manifest.tsv | |
| - name: Enrich (best-effort) — install conformant tools for `learn --json` | |
| continue-on-error: true | |
| run: | | |
| # Optional layer: populates each listed tool's purpose + command map. | |
| # If a tool can't be installed the catalog still builds; that entry just | |
| # carries no command surface. Never fails the job. | |
| for pkg in agentfront colleague culture-tools; do | |
| uv tool install "$pkg" || echo "skip install $pkg" | |
| done | |
| - name: Regenerate the catalog | |
| run: | | |
| set -euo pipefail | |
| uv run culture-tools index build --out _stage --repos-dir _siblings | |
| cp _stage/catalog.json site-astro/src/data/catalog.json | |
| rm -rf site-astro/public/simple | |
| cp -r _stage/simple site-astro/public/simple | |
| cp _stage/_redirects site-astro/public/_redirects | |
| rm -rf _siblings _stage | |
| - name: Open a PR if the catalog changed | |
| uses: peter-evans/create-pull-request@v7 | |
| with: | |
| # PR creation needs *write*. SIBLING_REPOS_TOKEN is documented read-only | |
| # (cloning private siblings), so it must NOT be reused here. The default | |
| # GITHUB_TOKEN works via the permissions: block above; note that a PR it | |
| # opens does not itself trigger CI — set CATALOG_REFRESH_PR_TOKEN (a PAT | |
| # or App token) if you want the refresh PR to run checks automatically. | |
| token: ${{ secrets.CATALOG_REFRESH_PR_TOKEN || secrets.GITHUB_TOKEN }} | |
| base: main | |
| branch: bot/catalog-refresh | |
| delete-branch: true | |
| commit-message: "chore(index): refresh catalog from live conformance" | |
| title: "chore(index): refresh tools.culture.dev catalog" | |
| body: | | |
| Automated catalog refresh from live AgentFront conformance | |
| (`culture-tools index build --repos-dir <cloned siblings>`). | |
| **Review the version / conformance diff before merging** — merging to | |
| `main` triggers a Cloudflare Pages rebuild of tools.culture.dev. If a | |
| tool's command surface looks stripped, its package likely failed to | |
| install in the enrichment step (non-fatal) — re-run or hold. | |
| Generated by `.github/workflows/catalog-refresh.yml`. |