Update Claude Code Documentation #425
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: | | |
| python -m pip install --upgrade pip | |
| 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: | | |
| python 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: 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/ | |
| # 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}" | |
| 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 |