fix(#910): split evolution-analysis local triage from private-repo di… #108
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
| name: Deploy Site | |
| on: | |
| release: | |
| types: [published] | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'website/**' | |
| - 'skills/**' | |
| - 'optional-skills/**' | |
| - '.github/workflows/deploy-site.yml' | |
| workflow_dispatch: | |
| inputs: | |
| skills_index_run_id: | |
| description: 'Optional Build Skills Index run ID whose skills-index artifact should be deployed' | |
| required: false | |
| type: string | |
| rebuild_skills_index: | |
| description: 'Force a fresh multi-source crawl instead of reusing the latest healthy index' | |
| required: false | |
| default: false | |
| type: boolean | |
| permissions: | |
| contents: read | |
| actions: read | |
| pages: write | |
| id-token: write | |
| concurrency: | |
| group: pages | |
| cancel-in-progress: false | |
| jobs: | |
| deploy-vercel: | |
| # Triggered automatically on release publish (production cuts) and | |
| # manually via `gh workflow run deploy-site.yml` when an out-of-band | |
| # main commit needs to ship live before the next release tag — e.g. | |
| # a skills-index PR that doesn't touch website/** paths and so | |
| # doesn't auto-deploy via the deploy-docs path. | |
| if: github.event_name == 'release' || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Trigger Vercel Deploy | |
| run: curl -X POST "${{ secrets.VERCEL_DEPLOY_HOOK }}" | |
| deploy-docs: | |
| if: github.repository == 'NousResearch/hermes-agent' | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deploy.outputs.page_url }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: website/package-lock.json | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '3.11' | |
| - name: Install PyYAML for skill extraction | |
| run: pip install pyyaml==6.0.2 httpx==0.28.1 | |
| - name: Prepare skills index (unified multi-source catalog) | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GITHUB_TOKEN: ${{ github.token }} | |
| SKILLS_INDEX_RUN_ID: ${{ github.event.inputs.skills_index_run_id || '' }} | |
| REBUILD_SKILLS_INDEX: ${{ github.event.inputs.rebuild_skills_index || 'false' }} | |
| run: | | |
| # The unified external catalog is expensive to crawl and can burn | |
| # through the repository installation's GitHub API quota when several | |
| # docs deploys land close together. Normal docs deploys therefore | |
| # reuse the latest healthy catalog: first the artifact from a | |
| # scheduled skills-index run, then the currently live index. Only a | |
| # manual force rebuild does a fresh crawl here. | |
| # | |
| # If we do crawl, the build remains fatal. build_skills_index.py runs | |
| # the health check BEFORE writing and exits non-zero on source | |
| # collapse, keeping the last good Pages deployment live instead of | |
| # publishing a degenerate catalog. | |
| set -euo pipefail | |
| INDEX_PATH="website/static/api/skills-index.json" | |
| mkdir -p "$(dirname "$INDEX_PATH")" | |
| validate_index() { | |
| python3 - "$INDEX_PATH" <<'PY' | |
| import json | |
| import sys | |
| from pathlib import Path | |
| path = Path(sys.argv[1]) | |
| try: | |
| data = json.loads(path.read_text(encoding="utf-8")) | |
| except Exception as exc: | |
| print(f"invalid skills index JSON: {exc}", file=sys.stderr) | |
| sys.exit(1) | |
| skills = data.get("skills") | |
| if not isinstance(skills, list) or len(skills) < 1500: | |
| count = len(skills) if isinstance(skills, list) else "missing" | |
| print(f"skills index too small: {count}", file=sys.stderr) | |
| sys.exit(1) | |
| print(f"skills index ready: {len(skills)} skills") | |
| PY | |
| } | |
| if [ "$REBUILD_SKILLS_INDEX" = "true" ]; then | |
| python3 scripts/build_skills_index.py | |
| validate_index | |
| exit 0 | |
| fi | |
| if [ -n "$SKILLS_INDEX_RUN_ID" ]; then | |
| tmpdir="$(mktemp -d)" | |
| echo "Downloading skills-index artifact from run $SKILLS_INDEX_RUN_ID" | |
| if gh run download "$SKILLS_INDEX_RUN_ID" --name skills-index --dir "$tmpdir"; then | |
| candidate="$(find "$tmpdir" -name skills-index.json -type f | head -n 1 || true)" | |
| if [ -n "$candidate" ]; then | |
| cp "$candidate" "$INDEX_PATH" | |
| if validate_index; then | |
| exit 0 | |
| fi | |
| fi | |
| fi | |
| echo "::warning::Could not use skills-index artifact from run $SKILLS_INDEX_RUN_ID; trying live index" | |
| fi | |
| echo "Downloading currently live skills index" | |
| if curl -fsSL --retry 3 --retry-delay 5 \ | |
| "https://hermes-agent.nousresearch.com/docs/api/skills-index.json" \ | |
| -o "$INDEX_PATH" && validate_index; then | |
| exit 0 | |
| fi | |
| echo "::warning::Live skills index unavailable or unhealthy; falling back to a fresh crawl" | |
| rm -f "$INDEX_PATH" | |
| python3 scripts/build_skills_index.py | |
| validate_index | |
| - name: Extract skill metadata for dashboard | |
| run: python3 website/scripts/extract-skills.py | |
| - name: Regenerate per-skill docs pages + catalogs | |
| run: python3 website/scripts/generate-skill-docs.py | |
| - name: Install dependencies | |
| run: npm ci | |
| working-directory: website | |
| - name: Build Docusaurus | |
| run: npm run build | |
| working-directory: website | |
| - name: Stage deployment | |
| run: | | |
| mkdir -p _site/docs | |
| cp -r website/build/* _site/docs/ | |
| # llms.txt / llms-full.txt are also published at the site root | |
| # (https://hermes-agent.nousresearch.com/llms.txt) because some | |
| # agents and IDE plugins probe the classic root-level path rather | |
| # than /docs/llms.txt. Same file, two URLs, one source of truth. | |
| if [ -f website/build/llms.txt ]; then | |
| cp website/build/llms.txt _site/llms.txt | |
| fi | |
| if [ -f website/build/llms-full.txt ]; then | |
| cp website/build/llms-full.txt _site/llms-full.txt | |
| fi | |
| - name: Upload artifact | |
| uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 | |
| with: | |
| path: _site | |
| - name: Deploy to GitHub Pages | |
| id: deploy | |
| uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 |