

























@@ -0,0 +1,183 @@
1+name: Docs Agent
2+3+on:
4+workflow_run:
5+workflows:
6+ - CI
7+types:
8+ - completed
9+schedule:
10+ - cron: "17 5 * * *"
11+workflow_dispatch:
12+13+permissions:
14+contents: write
15+16+concurrency:
17+group: docs-agent-main
18+cancel-in-progress: true
19+20+env:
21+FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
22+23+jobs:
24+update-docs:
25+if: >
26+ github.repository == 'openclaw/openclaw' &&
27+ github.actor != 'github-actions[bot]' &&
28+ (github.event_name != 'workflow_run' ||
29+ (github.event.workflow_run.conclusion == 'success' &&
30+ github.event.workflow_run.event == 'push' &&
31+ github.event.workflow_run.head_branch == 'main' &&
32+ github.event.workflow_run.actor.login != 'github-actions[bot]'))
33+ runs-on: ubuntu-24.04
34+timeout-minutes: 30
35+steps:
36+ - name: Checkout
37+uses: actions/checkout@v6
38+with:
39+ref: main
40+fetch-depth: 0
41+persist-credentials: false
42+submodules: false
43+44+ - name: Skip superseded workflow runs
45+id: superseded
46+env:
47+EVENT_NAME: ${{ github.event_name }}
48+WORKFLOW_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
49+run: |
50+ set -euo pipefail
51+52+ if [ "$EVENT_NAME" != "workflow_run" ]; then
53+ echo "run_agent=true" >> "$GITHUB_OUTPUT"
54+ echo "base_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
55+ exit 0
56+ fi
57+58+ git fetch --no-tags origin main
59+ remote_main="$(git rev-parse origin/main)"
60+ if [ "$remote_main" != "$WORKFLOW_HEAD_SHA" ]; then
61+ echo "CI run is superseded by ${remote_main}; skipping docs agent for ${WORKFLOW_HEAD_SHA}."
62+ echo "run_agent=false" >> "$GITHUB_OUTPUT"
63+ exit 0
64+ fi
65+66+ echo "run_agent=true" >> "$GITHUB_OUTPUT"
67+ echo "base_sha=${remote_main}" >> "$GITHUB_OUTPUT"
68+69+ - name: Setup Node environment
70+if: steps.superseded.outputs.run_agent == 'true'
71+uses: ./.github/actions/setup-node-env
72+with:
73+install-bun: "false"
74+75+ - name: Ensure docs agent key exists
76+if: steps.superseded.outputs.run_agent == 'true'
77+env:
78+OPENAI_API_KEY: ${{ secrets.OPENCLAW_DOCS_AGENT_OPENAI_API_KEY || secrets.OPENAI_API_KEY }}
79+run: |
80+ set -euo pipefail
81+ if [ -z "${OPENAI_API_KEY:-}" ]; then
82+ echo "Missing OPENCLAW_DOCS_AGENT_OPENAI_API_KEY or OPENAI_API_KEY secret." >&2
83+ exit 1
84+ fi
85+86+ - name: Run Codex docs agent
87+if: steps.superseded.outputs.run_agent == 'true'
88+uses: openai/codex-action@v1
89+with:
90+openai-api-key: ${{ secrets.OPENCLAW_DOCS_AGENT_OPENAI_API_KEY || secrets.OPENAI_API_KEY }}
91+prompt-file: .github/codex/prompts/docs-agent.md
92+model: gpt-5.4
93+effort: medium
94+sandbox: workspace-write
95+safety-strategy: drop-sudo
96+codex-args: '["--full-auto"]'
97+98+ - name: Enforce existing-docs-only patch
99+if: steps.superseded.outputs.run_agent == 'true'
100+run: |
101+ set -euo pipefail
102+103+ untracked="$(git ls-files --others --exclude-standard)"
104+ if [ -n "$untracked" ]; then
105+ echo "Docs agent created untracked files; forbidden:"
106+ printf '%s\n' "$untracked"
107+ exit 1
108+ fi
109+110+ added_or_deleted="$(git diff --name-status --diff-filter=AD)"
111+ if [ -n "$added_or_deleted" ]; then
112+ echo "Docs agent added or deleted tracked files; forbidden:"
113+ printf '%s\n' "$added_or_deleted"
114+ exit 1
115+ fi
116+117+ bad_paths="$(
118+ git diff --name-only | while IFS= read -r path; do
119+ case "$path" in
120+ docs/*|README.md|CHANGELOG.md) ;;
121+ *) printf '%s\n' "$path" ;;
122+ esac
123+ done
124+ )"
125+ if [ -n "$bad_paths" ]; then
126+ echo "Docs agent touched non-doc paths; forbidden:"
127+ printf '%s\n' "$bad_paths"
128+ exit 1
129+ fi
130+131+ - name: Restore Node environment
132+if: steps.superseded.outputs.run_agent == 'true'
133+uses: ./.github/actions/setup-node-env
134+with:
135+install-bun: "false"
136+install-deps: "false"
137+138+ - name: Check docs
139+if: steps.superseded.outputs.run_agent == 'true'
140+run: pnpm check:docs
141+142+ - name: Commit docs updates
143+if: steps.superseded.outputs.run_agent == 'true'
144+env:
145+BASE_SHA: ${{ steps.superseded.outputs.base_sha }}
146+GITHUB_TOKEN: ${{ github.token }}
147+TARGET_BRANCH: main
148+run: |
149+ set -euo pipefail
150+151+ if git diff --quiet; then
152+ echo "No docs changes."
153+ exit 0
154+ fi
155+156+ git fetch --no-tags origin "${TARGET_BRANCH}"
157+ remote_main="$(git rev-parse "origin/${TARGET_BRANCH}")"
158+ if [ "$remote_main" != "$BASE_SHA" ]; then
159+ echo "main advanced from ${BASE_SHA} to ${remote_main}; skipping stale docs update."
160+ exit 0
161+ fi
162+163+ git config user.name "openclaw-docs-agent[bot]"
164+ git config user.email "openclaw-docs-agent[bot]@users.noreply.github.com"
165+ git add docs README.md CHANGELOG.md
166+ git commit --no-verify -m "docs: refresh documentation"
167+168+ for attempt in 1 2 3 4 5; do
169+ if git push "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" HEAD:"${TARGET_BRANCH}"; then
170+ exit 0
171+ fi
172+ git fetch --no-tags origin "${TARGET_BRANCH}"
173+ remote_main="$(git rev-parse "origin/${TARGET_BRANCH}")"
174+ if [ "$remote_main" != "$BASE_SHA" ]; then
175+ echo "main advanced from ${BASE_SHA} to ${remote_main}; skipping stale docs update."
176+ exit 0
177+ fi
178+ echo "Push attempt ${attempt} failed; retrying."
179+ sleep $((attempt * 2))
180+ done
181+182+ echo "Failed to push docs updates after retries." >&2
183+ exit 1
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。