[codex] Add wiki update workflow (#7454)
* Add wiki update workflow * Update greploop skill automation * Harden wiki update workflow * Fix wiki workflow review findings * Address reviewer workflow feedback * Harden wiki change validation * Scope wiki PR lookup to repository * Address greptile wiki workflow feedback * Skip wiki link check without changes * Address greptile read tool feedback
This commit is contained in:
parent
50f858a8ce
commit
8416ea8af4
|
|
@ -23,7 +23,11 @@ Iteratively fix a PR/MR/CL until Greptile gives a perfect review: 5/5 confidence
|
|||
|
||||
## Instructions
|
||||
|
||||
### 0. Detect platform
|
||||
### 0. Delegate execution when invoked by Codex
|
||||
|
||||
When Greploop is invoked from Codex and sub-agents are available, the main agent must delegate the actual Greploop execution to a sub-agent by default. Pass along the detected or provided PR/MR/CL identifier, repository/worktree path, current branch, VCS platform, user scope constraints, and any known changed-file intent. The parent agent monitors progress, relays concise status updates, and reports final results. Only run Greploop directly from the parent agent when sub-agents are unavailable or the environment cannot delegate.
|
||||
|
||||
### 1. Detect platform
|
||||
|
||||
First check for Perforce, then fall back to git remote detection:
|
||||
|
||||
|
|
@ -43,13 +47,33 @@ fi
|
|||
|
||||
For self-hosted GitLab instances whose hostname doesn't contain "gitlab", the user can override by passing `--vcs gitlab` as an input. For Perforce, pass `--vcs perforce`.
|
||||
|
||||
### 1. Identify the PR/MR/CL
|
||||
### 2. Identify or create the PR/MR/CL
|
||||
|
||||
**GitHub:**
|
||||
```bash
|
||||
gh pr view --json number,headRefName -q '{number: .number, branch: .headRefName}'
|
||||
if PR_JSON=$(gh pr view --json number,headRefName -q '{number: .number, branch: .headRefName}' 2>/dev/null); then
|
||||
echo "$PR_JSON"
|
||||
else
|
||||
PR_JSON=""
|
||||
fi
|
||||
```
|
||||
|
||||
If `PR_JSON` is empty because no PR exists for the current branch/worktree, automatically publish a draft PR before starting the loop:
|
||||
|
||||
1. Inspect `git status --short` and determine the intended change scope. Do not silently stage unrelated changes; if the worktree is mixed and the intended files are unclear, stop and ask.
|
||||
2. Ensure the work is on a review branch. If the current branch is missing, protected, default, or unsuitable, create/switch to a `codex/<descriptive-name>` branch.
|
||||
3. Stage intended changes only, commit if needed, push the branch, and create a draft PR.
|
||||
|
||||
```bash
|
||||
git switch -c codex/<descriptive-name> # only when a review branch is needed
|
||||
git add <intended-files-only>
|
||||
git commit -m "<concise change summary>" # only when there are staged changes
|
||||
git push -u origin HEAD
|
||||
gh pr create --draft --fill
|
||||
```
|
||||
|
||||
Then continue Greploop against the created PR number.
|
||||
|
||||
**GitLab:**
|
||||
```bash
|
||||
glab mr view --output json | jq '{iid: .iid, branch: .source_branch}'
|
||||
|
|
@ -73,7 +97,7 @@ Key field differences:
|
|||
- GitLab: `iid`, `source_branch`, `sha`
|
||||
- Perforce: changelist number, `P4CLIENT`, shelved files
|
||||
|
||||
### 2. Loop
|
||||
### 3. Loop
|
||||
|
||||
Repeat the following cycle. **Max 5 iterations** to avoid runaway loops.
|
||||
|
||||
|
|
@ -351,8 +375,11 @@ Repeat for each unresolved discussion ID. (GitLab has no batch resolution — lo
|
|||
#### F. Commit and push / re-shelve
|
||||
|
||||
**GitHub/GitLab:**
|
||||
|
||||
Before staging, inspect the worktree and keep the write set scoped to Greptile fixes. Do not run `git add -A` when unrelated changes are present; stage only intended files, and stop/ask if scope is ambiguous.
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git add <intended-files-only>
|
||||
git commit -m "address greptile review feedback (greploop iteration N)"
|
||||
git push
|
||||
```
|
||||
|
|
@ -371,7 +398,7 @@ sleep 5
|
|||
|
||||
Then go back to step **A**.
|
||||
|
||||
### 3. Report
|
||||
### 4. Report
|
||||
|
||||
After exiting the loop, summarize:
|
||||
|
||||
|
|
|
|||
204
.github/workflows/update-wiki.yml
vendored
Normal file
204
.github/workflows/update-wiki.yml
vendored
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
name: Update Wiki
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
update-wiki:
|
||||
name: Refresh repo wiki
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
actions: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: main
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure git identity
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Refresh wiki with Claude Code
|
||||
uses: anthropics/claude-code-action@99ca333651aa9a8becc279065fad21c4ef1c4494 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
prompt: |
|
||||
Refresh the repo-local wiki under doc/wiki so it remains accurate for the current Elsa Core codebase.
|
||||
|
||||
Scope:
|
||||
- Edit only files under doc/wiki/.
|
||||
- Keep the existing wiki structure unless the codebase genuinely needs a new or renamed wiki page.
|
||||
- Ground every update in the current repository source, tests, specs, and ADRs.
|
||||
- Preserve relative Markdown links and Mermaid diagrams where useful.
|
||||
- Do not modify production code, tests, package files, workflows, or non-wiki docs.
|
||||
- Prefer concise contributor-facing explanations over exhaustive API reference.
|
||||
|
||||
Validation:
|
||||
- Check local Markdown links under doc/wiki before finishing.
|
||||
- If the wiki is already up to date, leave the worktree unchanged.
|
||||
claude_args: >-
|
||||
--allowed-tools
|
||||
"Edit(doc/wiki/**),Write(doc/wiki/**),Bash(rg:* .),Bash(git diff:*),Bash(git status:*),Bash(ls:* .),Bash(wc:*)"
|
||||
|
||||
- name: Verify wiki-only changes
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 - <<'PY'
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
status = subprocess.run(
|
||||
["git", "status", "--porcelain=v1", "-z", "--untracked-files=all"],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
).stdout
|
||||
|
||||
records = status.split(b"\0")
|
||||
invalid_paths = []
|
||||
changed_paths = []
|
||||
i = 0
|
||||
|
||||
while i < len(records):
|
||||
record = records[i]
|
||||
if not record:
|
||||
i += 1
|
||||
continue
|
||||
|
||||
text = record.decode()
|
||||
code = text[:2]
|
||||
paths = [text[3:]]
|
||||
|
||||
if "R" in code or "C" in code:
|
||||
i += 1
|
||||
if i < len(records) and records[i]:
|
||||
paths.append(records[i].decode())
|
||||
|
||||
changed_paths.extend(paths)
|
||||
invalid_paths.extend(path for path in paths if not path.startswith("doc/wiki/"))
|
||||
i += 1
|
||||
|
||||
if not changed_paths:
|
||||
print("No wiki changes detected.")
|
||||
sys.exit(0)
|
||||
|
||||
if invalid_paths:
|
||||
print("The wiki update workflow may only modify files under doc/wiki/.", file=sys.stderr)
|
||||
print("\n".join(invalid_paths), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print("Wiki-only changes verified.")
|
||||
PY
|
||||
|
||||
if git diff --quiet -- doc/wiki && [ -z "$(git ls-files --others --exclude-standard doc/wiki)" ]; then
|
||||
echo "No wiki changes detected."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
- name: Verify local wiki links
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if git diff --quiet -- doc/wiki && [ -z "$(git ls-files --others --exclude-standard doc/wiki)" ]; then
|
||||
echo "No wiki changes to validate."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
|
||||
root = Path(".").resolve()
|
||||
errors = []
|
||||
|
||||
for md in sorted(Path("doc/wiki").rglob("*.md")):
|
||||
text = md.read_text()
|
||||
for match in re.finditer(r"\[[^\]]+\]\(([^)]+)\)", text):
|
||||
target = match.group(1).split("#", 1)[0]
|
||||
if not target or target.startswith(("http://", "https://", "mailto:")):
|
||||
continue
|
||||
|
||||
path = (md.parent / target).resolve()
|
||||
try:
|
||||
path.relative_to(root)
|
||||
except ValueError:
|
||||
errors.append((md, target, "outside repo"))
|
||||
continue
|
||||
|
||||
if not path.exists():
|
||||
errors.append((md, target, "missing"))
|
||||
|
||||
if errors:
|
||||
for md, target, reason in errors:
|
||||
print(f"{md}: {target} -> {reason}")
|
||||
sys.exit(1)
|
||||
|
||||
print("All local markdown links resolve.")
|
||||
PY
|
||||
|
||||
- name: Open or update wiki refresh pull request
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BASE_BRANCH: main
|
||||
UPDATE_BRANCH: codex/update-wiki
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if git diff --quiet -- doc/wiki && [ -z "$(git ls-files --others --exclude-standard doc/wiki)" ]; then
|
||||
echo "No wiki changes to publish."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git checkout -B "$UPDATE_BRANCH"
|
||||
git add doc/wiki
|
||||
git commit -m "Refresh codebase wiki"
|
||||
|
||||
remote_sha="$(git ls-remote --heads origin "$UPDATE_BRANCH" | awk '{print $1}')"
|
||||
if [ -n "$remote_sha" ]; then
|
||||
git push --force-with-lease="refs/heads/$UPDATE_BRANCH:$remote_sha" origin "HEAD:$UPDATE_BRANCH"
|
||||
else
|
||||
git push origin "HEAD:$UPDATE_BRANCH"
|
||||
fi
|
||||
|
||||
existing_pr="$(gh pr list --repo "$GITHUB_REPOSITORY" --state open --head "$GITHUB_REPOSITORY_OWNER:$UPDATE_BRANCH" --json number --jq '.[0].number // empty')"
|
||||
body="$(cat <<'MD'
|
||||
## Summary
|
||||
|
||||
Refreshes the repo-local `doc/wiki/` documentation after changes landed on `main`.
|
||||
|
||||
## Validation
|
||||
|
||||
- Verified the workflow changed only files under `doc/wiki/`.
|
||||
- Verified all local Markdown links under `doc/wiki/` recursively resolve.
|
||||
|
||||
This PR was opened automatically by the Update Wiki workflow.
|
||||
MD
|
||||
)"
|
||||
|
||||
if [ -n "$existing_pr" ]; then
|
||||
gh pr edit "$existing_pr" \
|
||||
--repo "$GITHUB_REPOSITORY" \
|
||||
--title "[codex] Refresh codebase wiki" \
|
||||
--body "$body" \
|
||||
--base "$BASE_BRANCH"
|
||||
echo "Updated existing PR #$existing_pr."
|
||||
else
|
||||
gh pr create \
|
||||
--repo "$GITHUB_REPOSITORY" \
|
||||
--title "[codex] Refresh codebase wiki" \
|
||||
--body "$body" \
|
||||
--base "$BASE_BRANCH" \
|
||||
--head "$GITHUB_REPOSITORY_OWNER:$UPDATE_BRANCH"
|
||||
fi
|
||||
Loading…
Reference in a new issue