205 lines
6.9 KiB
YAML
205 lines
6.9 KiB
YAML
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/base-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
|