Skip to content

Commit c5d52cf

Browse files
committed
ci: add reusable docs-sync workflow
Consolidates per-repo docs-sync workflows across the dojoengine ecosystem into a single reusable workflow hosted here. Callers (dojo, katana, torii, torii-core, saya, dojo.js, dojo.c, dojo.unity, dojo.unreal, dojo.bevy, and cartridge-gg/controller) invoke this via `uses:` and pass their repo-specific diff globs, DOCS_PATTERNS, canonical docs path, and target docs repo. Because this file lives in a public repo, cross-org callers (e.g., cartridge-gg/controller) can invoke it without special access configuration. Callers forward their own CREATE_PR_TOKEN and ANTHROPIC_API_KEY via `secrets: inherit`.
1 parent 32a6ee4 commit c5d52cf

1 file changed

Lines changed: 219 additions & 0 deletions

File tree

.github/workflows/docs-sync.yml

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
name: Reusable docs-sync
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
target-docs-repo:
7+
description: "owner/name of the docs repo to open PRs against (e.g., dojoengine/book)"
8+
required: true
9+
type: string
10+
source-repo-slug:
11+
description: "owner/name of the caller repo (e.g., dojoengine/katana)"
12+
required: true
13+
type: string
14+
diff-globs:
15+
description: "newline-separated pathspec globs passed to `git diff --` (e.g., `*.rs` one per line)"
16+
required: true
17+
type: string
18+
docs-patterns:
19+
description: "newline-separated bash regexes; a changed file matching any triggers docs-sync"
20+
required: true
21+
type: string
22+
canonical-desc:
23+
description: "prose describing the single canonical docs location for this caller"
24+
required: true
25+
type: string
26+
docs-structure-desc:
27+
description: "prose describing the target docs repo's layout (Vocs content root, nav path, conventions)"
28+
required: true
29+
type: string
30+
31+
jobs:
32+
docs-sync:
33+
runs-on: ubuntu-latest
34+
permissions:
35+
contents: read
36+
pull-requests: read
37+
id-token: write
38+
39+
steps:
40+
- name: Checkout source repository
41+
uses: actions/checkout@v4
42+
with:
43+
fetch-depth: 0
44+
45+
- name: Get changed files
46+
id: changed-files
47+
env:
48+
DIFF_GLOBS: ${{ inputs.diff-globs }}
49+
run: |
50+
set -e
51+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
52+
git fetch origin
53+
DIFF_BASE="${{ github.event.inputs.commit_sha }}~1"
54+
DIFF_HEAD="${{ github.event.inputs.commit_sha }}"
55+
else
56+
git fetch origin main
57+
DIFF_BASE="${{ github.event.pull_request.base.sha }}"
58+
DIFF_HEAD="${{ github.event.pull_request.merge_commit_sha }}"
59+
fi
60+
CHANGED_FILES=$(git diff --name-only "$DIFF_BASE" "$DIFF_HEAD")
61+
62+
GLOBS=()
63+
while IFS= read -r g; do
64+
[ -z "$g" ] && continue
65+
GLOBS+=("$g")
66+
done <<< "$DIFF_GLOBS"
67+
# Truncate diff to avoid blowing up the prompt
68+
DIFF_CONTENT=$(git diff "$DIFF_BASE" "$DIFF_HEAD" -- "${GLOBS[@]}" | head -c 60000)
69+
70+
{
71+
echo "changed_files<<EOF"
72+
echo "$CHANGED_FILES"
73+
echo "EOF"
74+
echo "diff_content<<EOF"
75+
echo "$DIFF_CONTENT"
76+
echo "EOF"
77+
} >> "$GITHUB_OUTPUT"
78+
79+
- name: Check if docs update needed
80+
id: check-docs
81+
env:
82+
CHANGED_FILES: ${{ steps.changed-files.outputs.changed_files }}
83+
DOCS_PATTERNS: ${{ inputs.docs-patterns }}
84+
run: |
85+
NEEDS_DOCS_UPDATE=false
86+
while IFS= read -r pattern; do
87+
[ -z "$pattern" ] && continue
88+
while IFS= read -r file; do
89+
[ -z "$file" ] && continue
90+
if [[ $file =~ $pattern ]]; then
91+
NEEDS_DOCS_UPDATE=true
92+
break 2
93+
fi
94+
done <<< "$CHANGED_FILES"
95+
done <<< "$DOCS_PATTERNS"
96+
97+
echo "needs_update=$NEEDS_DOCS_UPDATE" >> "$GITHUB_OUTPUT"
98+
echo "Files that may need docs updates: $(echo "$CHANGED_FILES" | tr '\n' ' ')"
99+
100+
- name: Checkout docs repository
101+
if: steps.check-docs.outputs.needs_update == 'true'
102+
uses: actions/checkout@v4
103+
with:
104+
repository: ${{ inputs.target-docs-repo }}
105+
token: ${{ secrets.CREATE_PR_TOKEN }}
106+
path: docs-repo
107+
108+
- name: Analyze changes and update docs
109+
if: steps.check-docs.outputs.needs_update == 'true'
110+
uses: anthropics/claude-code-action@beta
111+
with:
112+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
113+
model: "claude-sonnet-4-5-20250929"
114+
direct_prompt: |
115+
Analyze changes in the ${{ inputs.source-repo-slug }} repository and update documentation
116+
in the ${{ inputs.target-docs-repo }} repository ONLY if user-facing behavior changed.
117+
118+
**Change Information:**
119+
- Title: ${{ github.event.pull_request.title || format('Manual trigger for commit {0}', github.event.inputs.commit_sha) }}
120+
- Description: ${{ github.event.pull_request.body || 'Manually triggered documentation sync' }}
121+
- Files changed: ${{ steps.changed-files.outputs.changed_files }}
122+
- Commit SHA: ${{ github.event.pull_request.merge_commit_sha || github.event.inputs.commit_sha }}
123+
124+
**Diff of user-facing files:**
125+
${{ steps.changed-files.outputs.diff_content }}
126+
127+
**Docs repo structure** (checked out in `docs-repo/`):
128+
${{ inputs.docs-structure-desc }}
129+
130+
**Canonical docs location for this repo:**
131+
${{ inputs.canonical-desc }}
132+
133+
**Rules — read these carefully:**
134+
1. DEFAULT TO NO CHANGES. Most code PRs do not need docs updates.
135+
Internal refactors, test changes, CI changes, and dependency bumps need nothing.
136+
Only proceed if there is a concrete user-facing change (new API, changed behavior,
137+
new feature, removed feature, changed configuration).
138+
2. SINGLE CANONICAL LOCATION. Each piece of information belongs on exactly one page.
139+
Find the one page that owns the topic and make your substantive edits there.
140+
Other pages MAY add a brief cross-reference linking to the canonical page,
141+
but do NOT duplicate explanations, code samples, or configuration details
142+
across multiple pages.
143+
3. MINIMAL EDITS. Update only the specific section affected. Do not rewrite
144+
surrounding paragraphs, add new sections for context, or reorganize existing content.
145+
4. ONE CODE EXAMPLE per concept. If a code sample is needed, add it once in the
146+
canonical location. Do not add the same or similar examples to multiple pages.
147+
5. Do NOT create git branches, commits, or PRs — just update files.
148+
6. Do NOT create new top-level sections or pages unless the canonical location
149+
description above explicitly says to. Edit existing pages.
150+
7. If no documentation updates are needed, state that clearly and exit.
151+
152+
allowed_tools: "Read,Write,Edit,MultiEdit,Glob,Grep"
153+
154+
- name: Create branch and commit changes
155+
if: steps.check-docs.outputs.needs_update == 'true'
156+
working-directory: docs-repo
157+
env:
158+
SOURCE_REPO_SLUG: ${{ inputs.source-repo-slug }}
159+
GITHUB_TOKEN: ${{ secrets.CREATE_PR_TOKEN }}
160+
run: |
161+
SOURCE_REPO_NAME="${SOURCE_REPO_SLUG##*/}"
162+
git config user.name "github-actions[bot]"
163+
git config user.email "github-actions[bot]@users.noreply.github.com"
164+
165+
if [ -n "$(git status --porcelain)" ]; then
166+
BRANCH_NAME="docs-update-$(date +%s)"
167+
git checkout -b "$BRANCH_NAME"
168+
169+
git add .
170+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
171+
git commit -m "docs: Update documentation for $SOURCE_REPO_NAME commit ${{ github.event.inputs.commit_sha }}
172+
173+
Updates documentation to reflect changes made in commit:
174+
${{ github.event.inputs.commit_sha }}
175+
176+
Manually triggered documentation sync"
177+
else
178+
git commit -m "docs: Update documentation for $SOURCE_REPO_NAME PR #${{ github.event.pull_request.number }}
179+
180+
Updates documentation to reflect changes made in:
181+
${{ github.event.pull_request.title }}
182+
183+
Related $SOURCE_REPO_NAME PR: $SOURCE_REPO_SLUG#${{ github.event.pull_request.number }}"
184+
fi
185+
186+
git push origin "$BRANCH_NAME"
187+
188+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
189+
gh pr create \
190+
--title "docs: Update documentation for $SOURCE_REPO_NAME commit ${{ github.event.inputs.commit_sha }}" \
191+
--body "This PR updates the documentation to reflect changes made in $SOURCE_REPO_SLUG commit ${{ github.event.inputs.commit_sha }}
192+
193+
**Commit Details:**
194+
- Commit SHA: ${{ github.event.inputs.commit_sha }}
195+
- Files changed: ${{ steps.changed-files.outputs.changed_files }}
196+
- Trigger: Manual documentation sync
197+
198+
Please review the documentation changes to ensure they accurately reflect the $SOURCE_REPO_NAME updates."
199+
gh pr merge --auto --squash
200+
else
201+
gh pr create \
202+
--title "docs: Update documentation for $SOURCE_REPO_NAME PR #${{ github.event.pull_request.number }}" \
203+
--body "This PR updates the documentation to reflect changes made in $SOURCE_REPO_SLUG#${{ github.event.pull_request.number }}
204+
205+
**Original PR Details:**
206+
- Title: ${{ github.event.pull_request.title }}
207+
- Files changed: ${{ steps.changed-files.outputs.changed_files }}
208+
209+
Please review the documentation changes to ensure they accurately reflect the $SOURCE_REPO_NAME updates."
210+
gh pr merge --auto --squash
211+
fi
212+
else
213+
echo "No documentation changes were made by Claude"
214+
fi
215+
216+
- name: Cleanup
217+
if: always()
218+
run: |
219+
rm -rf docs-repo || true

0 commit comments

Comments
 (0)