Skip to content

Commit ce43732

Browse files
authored
Merge pull request #132 from Miyamura80/feat/jules-maintenance-workflows
Add Jules maintenance workflows for dead code cleanup and doc drift detection
2 parents 092feb6 + 4528e1f commit ce43732

5 files changed

Lines changed: 718 additions & 1 deletion

File tree

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
# ─────────────────────────────────────────────────────────────────────
2+
# Jules Outdated Documentation Drift Detection
3+
# ─────────────────────────────────────────────────────────────────────
4+
# Automated weekly documentation drift check via Jules API. Runs every
5+
# Wednesday at 4pm UTC and on manual dispatch. Opens a PR with
6+
# any corrections.
7+
#
8+
# Jules reads OUTDATED_DOCUMENTATION_GUIDELINE.md before making changes.
9+
#
10+
# Required secrets: JULES_API_KEY
11+
# ─────────────────────────────────────────────────────────────────────
12+
name: Jules Find Outdated Docs
13+
14+
on:
15+
schedule:
16+
- cron: "0 16 * * 3" # Wednesday 4pm UTC
17+
workflow_dispatch:
18+
19+
permissions:
20+
contents: read
21+
actions: read
22+
23+
concurrency:
24+
group: jules-find-outdated-docs
25+
cancel-in-progress: false
26+
27+
env:
28+
JULES_API_BASE: "https://jules.googleapis.com/v1alpha"
29+
MAX_POLL_ATTEMPTS: 60
30+
POLL_INTERVAL_SECONDS: 30
31+
32+
jobs:
33+
find-outdated-docs:
34+
name: Detect and fix outdated documentation via Jules
35+
runs-on: ubuntu-latest
36+
timeout-minutes: 45
37+
38+
steps:
39+
# ── 1. Checkout ───────────────────────────────────────────────
40+
- name: Checkout repository
41+
uses: actions/checkout@v4
42+
with:
43+
fetch-depth: 0
44+
45+
# ── 2. Create Jules documentation drift session ───────────────
46+
- name: Create Jules documentation drift session
47+
id: jules-create
48+
env:
49+
JULES_API_KEY: ${{ secrets.JULES_API_KEY }}
50+
run: |
51+
set -euo pipefail
52+
53+
if [[ -z "${JULES_API_KEY:-}" ]]; then
54+
echo "::error::JULES_API_KEY is not configured. Add it in repository Actions secrets."
55+
exit 1
56+
fi
57+
58+
REPO="${{ github.repository }}"
59+
OWNER="${REPO%%/*}"
60+
REPO_NAME="${REPO##*/}"
61+
SOURCE="sources/github/${OWNER}/${REPO_NAME}"
62+
63+
PROMPT="IMPORTANT: Before you begin, read the file OUTDATED_DOCUMENTATION_GUIDELINE.md in the root of this repository.
64+
It contains the rules and validation requirements you must follow strictly when detecting
65+
and fixing outdated documentation.
66+
67+
Also read docs/translation-guide.md if it exists, to understand the translation policy.
68+
Any documentation changes you make must respect the translation workflow - only edit English
69+
source files, never edit translation files directly.
70+
71+
You are a documentation maintenance assistant for this project.
72+
73+
Scan the repository for documentation drift including:
74+
- README.md sections that no longer match actual project behavior
75+
- CLAUDE.md instructions that reference moved, renamed, or deleted files
76+
- Docstrings that describe outdated function signatures or behavior
77+
- Code examples in docs that use deprecated APIs or patterns
78+
- Configuration references that point to renamed or removed settings
79+
- Broken internal cross-references between documentation files
80+
- Changelog entries that reference incorrect versions or dates
81+
- Install/setup instructions that skip required steps or list wrong commands
82+
83+
Strict rules - you MUST follow every one:
84+
1. Follow ALL rules in OUTDATED_DOCUMENTATION_GUIDELINE.md without exception.
85+
2. Only fix documentation that is verifiably incorrect by cross-referencing the actual code.
86+
3. Do NOT rewrite documentation style, tone, or structure - only fix factual inaccuracies.
87+
4. Do NOT add new documentation sections - only update existing content.
88+
5. Do NOT modify translation files (*.lang.mdx, meta.lang.json) - only English sources.
89+
6. For each fix, include the evidence (file path and line) showing why the doc is wrong.
90+
7. Preserve all existing formatting, heading levels, and link structures.
91+
8. If a referenced file was moved, update the path. If deleted, note the removal clearly.
92+
9. Group related fixes into logical commits with clear messages.
93+
10. If no outdated documentation is found, do not create a PR."
94+
95+
TITLE="docs: fix outdated documentation (automated weekly drift check)"
96+
97+
BODY=$(jq -n \
98+
--arg prompt "$PROMPT" \
99+
--arg title "$TITLE" \
100+
--arg source "$SOURCE" \
101+
'{
102+
prompt: $prompt,
103+
title: $title,
104+
automationMode: "AUTO_CREATE_PR",
105+
sourceContext: {
106+
source: $source,
107+
githubRepoContext: {
108+
startingBranch: "main"
109+
}
110+
}
111+
}')
112+
113+
MAX_RETRIES=3
114+
RETRY_DELAY=5
115+
116+
for attempt in $(seq 1 "$MAX_RETRIES"); do
117+
HTTP_CODE=$(curl -s -o /tmp/jules_response.json -w "%{http_code}" \
118+
-X POST \
119+
-H "Content-Type: application/json" \
120+
-H "X-Goog-Api-Key: ${JULES_API_KEY}" \
121+
-d "$BODY" \
122+
"${JULES_API_BASE}/sessions")
123+
124+
if [[ "$HTTP_CODE" -ge 200 && "$HTTP_CODE" -lt 300 ]]; then
125+
break
126+
elif [[ "$HTTP_CODE" -ge 500 && $attempt -lt $MAX_RETRIES ]]; then
127+
echo "::warning::Jules API returned ${HTTP_CODE} - retrying in ${RETRY_DELAY}s (attempt ${attempt}/${MAX_RETRIES})"
128+
sleep "$RETRY_DELAY"
129+
RETRY_DELAY=$((RETRY_DELAY * 2))
130+
else
131+
echo "::error::Jules session creation failed with HTTP ${HTTP_CODE}"
132+
cat /tmp/jules_response.json
133+
exit 1
134+
fi
135+
done
136+
137+
SESSION_NAME=$(jq -r '.name' /tmp/jules_response.json)
138+
SESSION_URL=$(jq -r '.url // empty' /tmp/jules_response.json)
139+
140+
if [[ -z "$SESSION_NAME" || "$SESSION_NAME" == "null" ]]; then
141+
echo "::error::No session name in Jules response"
142+
cat /tmp/jules_response.json
143+
exit 1
144+
fi
145+
146+
{
147+
echo "session_name<<GHEOF"
148+
echo "$SESSION_NAME"
149+
echo "GHEOF"
150+
echo "session_url<<GHEOF"
151+
echo "$SESSION_URL"
152+
echo "GHEOF"
153+
} >> "$GITHUB_OUTPUT"
154+
155+
echo "Jules session created: ${SESSION_NAME}"
156+
echo "Jules UI: ${SESSION_URL}"
157+
158+
# ── 3. Poll until Jules finishes ──────────────────────────────
159+
- name: Poll Jules session until completion
160+
id: jules-poll
161+
env:
162+
JULES_API_KEY: ${{ secrets.JULES_API_KEY }}
163+
JULES_SESSION_NAME: ${{ steps.jules-create.outputs.session_name }}
164+
run: |
165+
set -euo pipefail
166+
167+
SESSION_NAME="$JULES_SESSION_NAME"
168+
MAX_ATTEMPTS="$MAX_POLL_ATTEMPTS"
169+
INTERVAL="$POLL_INTERVAL_SECONDS"
170+
171+
echo "Polling ${SESSION_NAME} (max ${MAX_ATTEMPTS} x ${INTERVAL}s)"
172+
173+
for attempt in $(seq 1 "$MAX_ATTEMPTS"); do
174+
RETRY_DELAY=5
175+
for retry in 1 2 3; do
176+
HTTP_CODE=$(curl -s -o /tmp/jules_session.json -w "%{http_code}" \
177+
-H "X-Goog-Api-Key: ${JULES_API_KEY}" \
178+
"${JULES_API_BASE}/${SESSION_NAME}")
179+
180+
if [[ "$HTTP_CODE" -ge 200 && "$HTTP_CODE" -lt 300 ]]; then
181+
break
182+
elif [[ $retry -lt 3 ]]; then
183+
echo "::warning::Poll returned ${HTTP_CODE} - retry ${retry}/3 in ${RETRY_DELAY}s"
184+
sleep "$RETRY_DELAY"
185+
RETRY_DELAY=$((RETRY_DELAY * 2))
186+
else
187+
echo "::error::Failed to poll session after 3 retries (HTTP ${HTTP_CODE})"
188+
exit 1
189+
fi
190+
done
191+
192+
STATE=$(jq -r '.state // "UNKNOWN"' /tmp/jules_session.json)
193+
echo "[${attempt}/${MAX_ATTEMPTS}] state=${STATE}"
194+
195+
case "$STATE" in
196+
COMPLETED)
197+
PR_URL=$(jq -r '.outputs[0].pullRequest.url // empty' /tmp/jules_session.json)
198+
PR_TITLE=$(jq -r '.outputs[0].pullRequest.title // empty' /tmp/jules_session.json)
199+
200+
{
201+
echo "jules_state<<GHEOF"
202+
echo "COMPLETED"
203+
echo "GHEOF"
204+
echo "pr_url<<GHEOF"
205+
echo "$PR_URL"
206+
echo "GHEOF"
207+
echo "pr_title<<GHEOF"
208+
echo "$PR_TITLE"
209+
echo "GHEOF"
210+
} >> "$GITHUB_OUTPUT"
211+
212+
echo "Session completed. PR: ${PR_URL}"
213+
exit 0
214+
;;
215+
FAILED)
216+
echo "jules_state=FAILED" >> "$GITHUB_OUTPUT"
217+
echo "::error::Jules session ended in FAILED state"
218+
jq '.' /tmp/jules_session.json
219+
exit 1
220+
;;
221+
esac
222+
223+
sleep "$INTERVAL"
224+
done
225+
226+
echo "jules_state=TIMEOUT" >> "$GITHUB_OUTPUT"
227+
echo "::error::Timed out after ${MAX_ATTEMPTS} poll attempts"
228+
exit 1

0 commit comments

Comments
 (0)