Update Claude Code Documentation #1387
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: Update Claude Code Documentation | |
| on: | |
| schedule: | |
| # Run every 3 hours (at 00:00, 03:00, 06:00, 09:00, 12:00, 15:00, 18:00, 21:00 UTC) | |
| - cron: '0 */3 * * *' | |
| workflow_dispatch: # Allow manual trigger | |
| permissions: | |
| contents: write | |
| jobs: | |
| update-docs: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| ref: main | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install dependencies | |
| run: | | |
| python3 -m pip install --upgrade pip | |
| python3 -m pip install -r scripts/requirements.txt | |
| # ================================================================= | |
| # SAFEGUARD: Count files BEFORE fetch to detect mass deletions | |
| # ================================================================= | |
| - name: Count files before fetch | |
| id: count-before | |
| run: | | |
| BEFORE=$(find docs/ -name "*.md" 2>/dev/null | wc -l) | |
| echo "count=$BEFORE" >> $GITHUB_OUTPUT | |
| echo "📊 Files before fetch: $BEFORE" | |
| - name: Fetch latest documentation | |
| id: fetch-docs | |
| env: | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| GITHUB_REF_NAME: ${{ github.ref_name }} | |
| run: | | |
| python3 scripts/fetch_claude_docs.py || echo "fetch_failed=true" >> $GITHUB_OUTPUT | |
| continue-on-error: true | |
| # ================================================================= | |
| # SAFEGUARD: Validate file count AFTER fetch (FAIL + REVERT on trigger) | |
| # ================================================================= | |
| - name: Validate after fetch (safeguard) | |
| id: validate-safeguard | |
| run: | | |
| AFTER=$(find docs/ -name "*.md" 2>/dev/null | wc -l) | |
| BEFORE=${{ steps.count-before.outputs.count }} | |
| echo "📊 Files after fetch: $AFTER (was: $BEFORE)" | |
| # SAFEGUARD 1: Check deletion percentage | |
| if [ "$BEFORE" -gt 0 ]; then | |
| DELETED=$((BEFORE - AFTER)) | |
| if [ "$DELETED" -lt 0 ]; then | |
| DELETED=0 | |
| fi | |
| PERCENT=$((DELETED * 100 / BEFORE)) | |
| if [ "$PERCENT" -gt 10 ]; then | |
| echo "::error::🚨 SAFEGUARD TRIGGERED: $PERCENT% of files would be deleted!" | |
| echo "::error:: Before: $BEFORE files, After: $AFTER files, Would delete: $DELETED" | |
| echo "::error:: This indicates sitemap discovery failure." | |
| echo "" | |
| echo "Reverting docs/ to previous state..." | |
| git checkout -- docs/ | |
| echo "safeguard_triggered=true" >> $GITHUB_OUTPUT | |
| echo "::error::Workflow failed. Manual investigation required." | |
| exit 1 | |
| fi | |
| fi | |
| # SAFEGUARD 2: Check minimum file count | |
| if [ "$AFTER" -lt 250 ]; then | |
| echo "::error::🚨 SAFEGUARD TRIGGERED: Only $AFTER files remain (expected 250+)!" | |
| echo "Reverting docs/ to previous state..." | |
| git checkout -- docs/ | |
| echo "safeguard_triggered=true" >> $GITHUB_OUTPUT | |
| echo "::error::Workflow failed. Manual investigation required." | |
| exit 1 | |
| fi | |
| echo "✅ Safeguard validation passed: $AFTER files present" | |
| - name: Build search index | |
| if: steps.validate-safeguard.outputs.safeguard_triggered != 'true' | |
| continue-on-error: true | |
| run: | | |
| echo "Building full-text search index..." | |
| python3 scripts/build_search_index.py || echo "⚠️ Search index build failed — content search may be unavailable" | |
| echo "✅ Search index step complete" | |
| - name: Check for changes | |
| id: verify-changed-files | |
| run: | | |
| git diff --exit-code || echo "changed=true" >> $GITHUB_OUTPUT | |
| - name: Generate commit message | |
| if: steps.verify-changed-files.outputs.changed == 'true' | |
| id: commit-msg | |
| run: | | |
| # Stage changes to see what will be committed | |
| git add -A docs/ paths_manifest.json | |
| # Get list of changed files with proper quoting | |
| # Using printf with %q for shell-safe quoting would be ideal, but not available in all shells | |
| # Instead, we carefully construct the file list from git output (which is already sanitized) | |
| CHANGED_FILES=$(git diff --name-status --cached | grep "^M" | cut -f2 | grep -E "\.md$" | sed 's|^docs/||' | paste -sd ", " -) | |
| ADDED_FILES=$(git diff --name-status --cached | grep "^A" | cut -f2 | grep -E "\.md$" | sed 's|^docs/||' | paste -sd ", " -) | |
| DELETED_FILES=$(git diff --name-status --cached | grep "^D" | cut -f2 | grep -E "\.md$" | sed 's|^docs/||' | paste -sd ", " -) | |
| # Build commit message with safe date format | |
| COMMIT_MSG="Update Claude Code docs - $(date -u +'%Y-%m-%d')" | |
| # Append file lists with proper quoting | |
| if [ -n "${CHANGED_FILES}" ]; then | |
| COMMIT_MSG="${COMMIT_MSG} | Updated: ${CHANGED_FILES}" | |
| fi | |
| if [ -n "${ADDED_FILES}" ]; then | |
| COMMIT_MSG="${COMMIT_MSG} | Added: ${ADDED_FILES}" | |
| fi | |
| if [ -n "${DELETED_FILES}" ]; then | |
| COMMIT_MSG="${COMMIT_MSG} | Removed: ${DELETED_FILES}" | |
| fi | |
| # Use GitHub Actions multiline output format for safe escaping | |
| # This prevents any shell interpretation of the commit message | |
| { | |
| echo "message<<EOF" | |
| echo "${COMMIT_MSG}" | |
| echo "EOF" | |
| } >> $GITHUB_OUTPUT | |
| - name: Commit and push if changed | |
| if: steps.verify-changed-files.outputs.changed == 'true' | |
| env: | |
| COMMIT_MESSAGE: ${{ steps.commit-msg.outputs.message }} | |
| run: | | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| # Files already staged in previous step | |
| # Use environment variable to avoid shell interpretation | |
| git commit -m "${COMMIT_MESSAGE}" | |
| # Pull with rebase to handle commits pushed during the fetch window | |
| git pull --rebase origin main | |
| git push | |
| - name: Log failure if fetch failed | |
| if: steps.fetch-docs.outputs.fetch_failed == 'true' | |
| run: | | |
| echo "::warning::Documentation fetch failed. Please check the workflow run for details." | |
| exit 1 |