forked from ericbuess/claude-code-docs
-
Notifications
You must be signed in to change notification settings - Fork 6
165 lines (140 loc) · 6.19 KB
/
update-docs.yml
File metadata and controls
165 lines (140 loc) · 6.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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