Add docs/wiki source tree and Gitea Wiki sync helper (#224)
Bootstrap repo-tracked wiki pages (10 required pages), the operator- confirmed sync script, PR template publication gate, and safety tests so Gitea-Tools can publish to the live Gitea Wiki per issue #224. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
## Description
|
||||
|
||||
[Summary of changes and issue number closed.]
|
||||
|
||||
Closes #[Issue Number]
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] I have verified my identity matches the required role.
|
||||
- [ ] No secrets, tokens, keychain IDs, or raw service URLs are committed.
|
||||
- [ ] All tests pass for touched code.
|
||||
- [ ] `git diff --check` is clean.
|
||||
|
||||
## Documentation and Wiki
|
||||
|
||||
- [ ] Does this change require a wiki update (workflows, tools, profiles, runbooks)?
|
||||
- [ ] If yes, has `docs/wiki/` been updated accordingly?
|
||||
- [ ] If wiki pages changed, plan the Gitea Wiki sync after merge (`scripts/sync-gitea-wiki.sh`, see Runbooks).
|
||||
- [ ] Readiness gate (#224): the Gitea Wiki is populated and current for this repo — verify the repo **Wiki tab**, not `docs/wiki/`. If stale or empty, record the required sync as a follow-up before approval.
|
||||
- [ ] If this PR closes a wiki-related issue: closure requires live Gitea Wiki proof links (Wiki Home plus page listing or wiki git log). Markdown in `docs/wiki/`, sync-helper code, or policy docs alone are not sufficient to close a wiki issue.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Project History
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md) | [Operator Guide](Operator-Guide.md) | [Repositories Map](Repositories.md) | [Identity and Profiles](Identity-and-Profiles.md) | [Workflow Model](Workflow.md) | [Safety and Gates](Safety-and-Gates.md) | [MCP Tools Reference](MCP-Tools.md) | [Operator Runbooks](Runbooks.md) | [Open Decisions](Open-Decisions.md) | [Project History](History.md)
|
||||
|
||||
## 2026-07-06
|
||||
|
||||
- **Wiki bootstrap (#224)** — Added repo-tracked `docs/wiki/` (10 pages), `scripts/sync-gitea-wiki.sh`, PR template gate, and sync safety tests for Gitea-Tools publication.
|
||||
|
||||
## Prior milestones
|
||||
|
||||
- Gated review/merge path (#16), task capability resolver (#69), issue-write tool gates.
|
||||
- Canonical JSON execution profiles (#19) and thin MCP launchers.
|
||||
- Role session router (#206) and review decision lock (#211).
|
||||
@@ -0,0 +1,35 @@
|
||||
# Gitea-Tools Project Wiki
|
||||
|
||||
Welcome to the version-controlled wiki for the Gitea-Tools MCP server and CLI tooling.
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md)
|
||||
- [Operator Guide](Operator-Guide.md)
|
||||
- [Repositories Map](Repositories.md)
|
||||
- [Identity and Profiles](Identity-and-Profiles.md)
|
||||
- [Workflow Model](Workflow.md)
|
||||
- [Safety and Gates](Safety-and-Gates.md)
|
||||
- [MCP Tools Reference](MCP-Tools.md)
|
||||
- [Operator Runbooks](Runbooks.md)
|
||||
- [Open Decisions](Open-Decisions.md)
|
||||
- [Project History](History.md)
|
||||
|
||||
## Gitea Wiki mirror
|
||||
|
||||
These repo-tracked pages are the **source of truth**. The Gitea native Wiki
|
||||
for this repository is a read-only convenience mirror generated from this
|
||||
directory with `scripts/sync-gitea-wiki.sh` (dry-run by default; see
|
||||
[Runbooks](Runbooks.md)). Never edit the Gitea Wiki directly — change the
|
||||
pages here through a PR, then sync.
|
||||
|
||||
## Project overview
|
||||
|
||||
Gitea-Tools provides the Gitea MCP server, execution-profile configuration,
|
||||
identity handling, and CLI helpers used across MCP Control Plane workflows.
|
||||
It enforces author/reviewer separation, gated review/merge, task-capability
|
||||
resolution, and fail-closed safety rails in code.
|
||||
|
||||
Canonical long-form docs also live under `docs/` in the repository (for example
|
||||
`docs/gitea-execution-profiles.md` and `docs/llm-workflow-runbooks.md`). The
|
||||
wiki summarizes operator-facing rules; the repo docs carry implementation detail.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Identity and Profiles
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md) | [Operator Guide](Operator-Guide.md) | [Repositories Map](Repositories.md) | [Identity and Profiles](Identity-and-Profiles.md) | [Workflow Model](Workflow.md) | [Safety and Gates](Safety-and-Gates.md) | [MCP Tools Reference](MCP-Tools.md) | [Operator Runbooks](Runbooks.md) | [Open Decisions](Open-Decisions.md) | [Project History](History.md)
|
||||
|
||||
The LLM is not the role — the **MCP execution profile** is the role. Profiles
|
||||
bind an authenticated Gitea identity to an allowed operation set.
|
||||
|
||||
## Reference profiles (prgs)
|
||||
|
||||
### Author / implementer
|
||||
|
||||
- **Profile:** `prgs-author`
|
||||
- **Typical identity:** `jcwalker3`
|
||||
- **Allowed:** branch create/push, PR create, issue comment/create/close, repo commit, read.
|
||||
- **Forbidden:** PR approve, merge, request_changes.
|
||||
|
||||
### Reviewer / merger
|
||||
|
||||
- **Profile:** `prgs-reviewer`
|
||||
- **Typical identity:** `sysadmin`
|
||||
- **Allowed:** PR review/approve/merge/request_changes, issue comment, read.
|
||||
- **Forbidden:** branch push, PR create, repo commit.
|
||||
|
||||
## Configuration
|
||||
|
||||
Profiles are defined in the canonical JSON config (`GITEA_MCP_CONFIG`, typically
|
||||
`~/.config/gitea-tools/profiles.json`). Launchers are thin: they set
|
||||
`GITEA_MCP_PROFILE` and point at the config file. Credentials resolve from
|
||||
keychain or env references — never inline in client configs.
|
||||
|
||||
See `docs/gitea-execution-profiles.md` in the repository for the full model.
|
||||
|
||||
## Profile switching
|
||||
|
||||
Use separate MCP server namespaces (`gitea-tools` author vs `gitea-reviewer`)
|
||||
or distinct launcher entries. Runtime in-place profile switching is disabled by
|
||||
default (fail closed).
|
||||
@@ -0,0 +1,34 @@
|
||||
# MCP Tools Reference
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md) | [Operator Guide](Operator-Guide.md) | [Repositories Map](Repositories.md) | [Identity and Profiles](Identity-and-Profiles.md) | [Workflow Model](Workflow.md) | [Safety and Gates](Safety-and-Gates.md) | [MCP Tools Reference](MCP-Tools.md) | [Operator Runbooks](Runbooks.md) | [Open Decisions](Open-Decisions.md) | [Project History](History.md)
|
||||
|
||||
## Identity and capability
|
||||
|
||||
- `gitea_whoami` — authenticated user and active profile metadata.
|
||||
- `gitea_get_profile` / `gitea_get_runtime_context` — allowed and forbidden operations.
|
||||
- `gitea_resolve_task_capability` — required pre-flight for gated mutations.
|
||||
- `gitea_route_task_session` — role/session router before task execution.
|
||||
|
||||
## Author tools
|
||||
|
||||
- `gitea_create_issue`, `gitea_create_issue_comment`, `gitea_close_issue`
|
||||
- `gitea_mark_issue`, `gitea_set_issue_labels`, `gitea_lock_issue`
|
||||
- `gitea_create_pr`, `gitea_edit_pr`, `gitea_commit_files`
|
||||
- `gitea_delete_branch`
|
||||
|
||||
## Reviewer tools
|
||||
|
||||
- `gitea_check_pr_eligibility` — read-only eligibility check.
|
||||
- `gitea_dry_run_pr_review` — validation-phase review mechanics.
|
||||
- `gitea_mark_final_review_decision` — mark validation complete.
|
||||
- `gitea_submit_pr_review` / `gitea_review_pr` — gated live review.
|
||||
- `gitea_merge_pr` — gated merge (only merge path).
|
||||
|
||||
## Read tools
|
||||
|
||||
- `gitea_list_prs`, `gitea_view_pr`, `gitea_list_issues`, `gitea_view_issue`
|
||||
- `gitea_get_file`, `gitea_list_labels`, `gitea_mirror_refs`
|
||||
|
||||
See the repository `README.md` for the full tool table and client setup.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Open Decisions
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md) | [Operator Guide](Operator-Guide.md) | [Repositories Map](Repositories.md) | [Identity and Profiles](Identity-and-Profiles.md) | [Workflow Model](Workflow.md) | [Safety and Gates](Safety-and-Gates.md) | [MCP Tools Reference](MCP-Tools.md) | [Operator Runbooks](Runbooks.md) | [Open Decisions](Open-Decisions.md) | [Project History](History.md)
|
||||
|
||||
Pending architectural and workflow decisions:
|
||||
|
||||
- **Operation-scoped role selection (#228)** — Move from launcher-profile-dependent routing to per-operation profile resolution.
|
||||
- **Gitea-Tools wiki for dadeschools remote** — This bootstrap covers `prgs`; dadeschools instance wiki parity is undecided.
|
||||
- **Server-side self-merge block** — Complement tool gates with Gitea branch protection where available.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Operator Guide
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md) | [Operator Guide](Operator-Guide.md) | [Repositories Map](Repositories.md) | [Identity and Profiles](Identity-and-Profiles.md) | [Workflow Model](Workflow.md) | [Safety and Gates](Safety-and-Gates.md) | [MCP Tools Reference](MCP-Tools.md) | [Operator Runbooks](Runbooks.md) | [Open Decisions](Open-Decisions.md) | [Project History](History.md)
|
||||
|
||||
Handbook for LLM operators and human developers using the Gitea-Tools MCP server.
|
||||
|
||||
## Key rules
|
||||
|
||||
1. **Verify identity first** — Run `gitea_whoami` and confirm the active profile before any mutation.
|
||||
2. **Resolve task capability** — Call `gitea_resolve_task_capability` for the intended task before gated tools.
|
||||
3. **One unit of work per session** — Implement one claimed issue *or* review/merge one PR; do not mix author and reviewer mutations in one session.
|
||||
4. **No self-review / no self-merge** — The authenticated Gitea user must not approve or merge a PR they authored.
|
||||
5. **Follow the gates** — Prompts express intent; MCP tools enforce safety. Never bypass gates via prompt instructions.
|
||||
|
||||
## Supported Gitea instances
|
||||
|
||||
| Remote | Host | Default org/repo |
|
||||
|--------|------|------------------|
|
||||
| `dadeschools` | `gitea.dadeschools.net` | `Contractor / Timesheet` |
|
||||
| `prgs` | `gitea.prgs.cc` | `Scaled-Tech-Consulting / Timesheet` |
|
||||
|
||||
Always pass `remote` explicitly on tool calls. The server default is `dadeschools`; forgetting `remote` on a `prgs` task hits the wrong host.
|
||||
|
||||
## New session checklist
|
||||
|
||||
1. `gitea_whoami` — confirm authenticated user and profile.
|
||||
2. `gitea_get_runtime_context` — allowed/forbidden operations for this session.
|
||||
3. `gitea_resolve_task_capability` — prove the session may perform the planned task.
|
||||
4. For reviewer work: dry-run validation (`gitea_dry_run_pr_review`) before live review mutations.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Repositories Map
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md) | [Operator Guide](Operator-Guide.md) | [Repositories Map](Repositories.md) | [Identity and Profiles](Identity-and-Profiles.md) | [Workflow Model](Workflow.md) | [Safety and Gates](Safety-and-Gates.md) | [MCP Tools Reference](MCP-Tools.md) | [Operator Runbooks](Runbooks.md) | [Open Decisions](Open-Decisions.md) | [Project History](History.md)
|
||||
|
||||
Active MCP Control Plane repositories (authoritative inventory for wiki publication gate #224 / #87):
|
||||
|
||||
| Repository | Purpose | Wiki required |
|
||||
|------------|---------|---------------|
|
||||
| `Scaled-Tech-Consulting/Gitea-Tools` | Gitea MCP server, execution profiles, workflow tooling | Yes — live Gitea Wiki on Wiki tab |
|
||||
| `Scaled-Tech-Consulting/mcp-control-plane` | Orchestrators, audit trails, multi-service controller workflows | Yes — live Gitea Wiki on Wiki tab |
|
||||
|
||||
Repo-tracked `docs/wiki/` is the source of truth; the Gitea Wiki is a mirror.
|
||||
Wiki-related issues cannot be closed until the live Wiki is verified — see
|
||||
[Safety and Gates](Safety-and-Gates.md) and [Runbooks](Runbooks.md).
|
||||
|
||||
### Gitea-Tools
|
||||
|
||||
- **Repository:** `Scaled-Tech-Consulting/Gitea-Tools`
|
||||
- **Purpose:** Gitea MCP server, profile configuration, CLI scripts, safety gates.
|
||||
- **Base branch:** `master`
|
||||
|
||||
### mcp-control-plane
|
||||
|
||||
- **Repository:** `Scaled-Tech-Consulting/mcp-control-plane`
|
||||
- **Purpose:** Controller workflows, Jenkins/GlitchTip integrations, audit orchestration.
|
||||
- **Base branch:** `master`
|
||||
|
||||
## Wiki publication status (#224 readiness gate)
|
||||
|
||||
| Repository | `docs/wiki/` source | Gitea Wiki published | Proof |
|
||||
|---|---|---|---|
|
||||
| `Scaled-Tech-Consulting/Gitea-Tools` | yes (10 pages) | pending publication — operator-confirmed sync required | pending |
|
||||
| `Scaled-Tech-Consulting/mcp-control-plane` | yes (10 pages) | published (verified 2026-07-06) | [Wiki Home](https://gitea.prgs.cc/Scaled-Tech-Consulting/mcp-control-plane/wiki/Home) |
|
||||
|
||||
Update this table whenever a wiki is published, re-synced, or found stale.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Operator Runbooks
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md) | [Operator Guide](Operator-Guide.md) | [Repositories Map](Repositories.md) | [Identity and Profiles](Identity-and-Profiles.md) | [Workflow Model](Workflow.md) | [Safety and Gates](Safety-and-Gates.md) | [MCP Tools Reference](MCP-Tools.md) | [Operator Runbooks](Runbooks.md) | [Open Decisions](Open-Decisions.md) | [Project History](History.md)
|
||||
|
||||
## PR review and merge
|
||||
|
||||
1. `gitea_resolve_task_capability(task="review_pr")`
|
||||
2. `gitea_check_pr_eligibility` for review and merge actions.
|
||||
3. Validate locally: tests, `py_compile`, `git diff --check`.
|
||||
4. `gitea_mark_final_review_decision` → approve via `gitea_review_pr`.
|
||||
5. `gitea_merge_pr` with pinned head SHA and `confirmation="MERGE PR <n>"`.
|
||||
|
||||
## Gitea Wiki sync
|
||||
|
||||
The Gitea Wiki mirrors `docs/wiki/` (source of truth). After merging wiki changes:
|
||||
|
||||
1. Preview (no network):
|
||||
```bash
|
||||
scripts/sync-gitea-wiki.sh
|
||||
```
|
||||
2. Operator-confirmed push:
|
||||
```bash
|
||||
GITEA_WIKI_SYNC_CONFIRM="SYNC WIKI Gitea-Tools" scripts/sync-gitea-wiki.sh --push
|
||||
```
|
||||
3. If clone fails on first run, bootstrap Home via Gitea API or UI, then re-run.
|
||||
|
||||
The script mirrors only `docs/wiki/*.md`, never deletes wiki pages, and never
|
||||
prints credentials.
|
||||
|
||||
## Wiki Publication Readiness Gate (#224)
|
||||
|
||||
Actual Gitea Wiki publication is a **required repo readiness gate**.
|
||||
|
||||
1. **Closure prevention** — No wiki issue may close on markdown/helper work alone.
|
||||
Closing requires live-Wiki proof: Wiki Home link plus page listing or wiki git log.
|
||||
2. **Reviewer checklist** — PR template requires verifying the repo **Wiki tab**.
|
||||
3. **Publication authority** — `--push` requires exact `GITEA_WIKI_SYNC_CONFIRM` phrase.
|
||||
4. **Per-repo status** — Update [Repositories Map](Repositories.md) when published.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Safety and Gates
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md) | [Operator Guide](Operator-Guide.md) | [Repositories Map](Repositories.md) | [Identity and Profiles](Identity-and-Profiles.md) | [Workflow Model](Workflow.md) | [Safety and Gates](Safety-and-Gates.md) | [MCP Tools Reference](MCP-Tools.md) | [Operator Runbooks](Runbooks.md) | [Open Decisions](Open-Decisions.md) | [Project History](History.md)
|
||||
|
||||
*Prompts express intent; MCP tools enforce safety.*
|
||||
|
||||
## Primary gates
|
||||
|
||||
1. **Fail closed** — Unknown tasks, missing capability resolution, or profile mismatches block mutations.
|
||||
2. **Task capability map** — `gitea_resolve_task_capability` must precede gated issue/PR mutations.
|
||||
3. **Issue lock** — `gitea_lock_issue` required before author implementation on a tracked issue.
|
||||
4. **Head SHA pinning** — Reviews and merges refuse when the PR head moved.
|
||||
5. **Explicit merge confirmation** — `gitea_merge_pr` requires `confirmation="MERGE PR <n>"`.
|
||||
6. **No self-review / self-merge** — Authenticated user must differ from PR author for approve/merge.
|
||||
7. **Review decision lock** — Live review mutations require validation-phase dry-run and `gitea_mark_final_review_decision`.
|
||||
8. **Redaction** — Tokens, passwords, and keychain material never appear in tool output.
|
||||
9. **Wiki publication (#224)** — `docs/wiki/` and the sync helper are prerequisites only. Closing a wiki issue requires live Gitea Wiki proof on the repo Wiki tab. See [Runbooks](Runbooks.md#wiki-publication-readiness-gate-224).
|
||||
@@ -0,0 +1,28 @@
|
||||
# Workflow Model
|
||||
|
||||
## Navigation
|
||||
|
||||
- [Home](Home.md) | [Operator Guide](Operator-Guide.md) | [Repositories Map](Repositories.md) | [Identity and Profiles](Identity-and-Profiles.md) | [Workflow Model](Workflow.md) | [Safety and Gates](Safety-and-Gates.md) | [MCP Tools Reference](MCP-Tools.md) | [Operator Runbooks](Runbooks.md) | [Open Decisions](Open-Decisions.md) | [Project History](History.md)
|
||||
|
||||
## Step 1: Review queue first (reviewer profile)
|
||||
|
||||
1. `gitea_resolve_task_capability(task="review_pr")`
|
||||
2. List open PRs; pick the oldest eligible PR (not self-authored, mergeable).
|
||||
3. Pin head SHA; validate diff scope and run tests locally.
|
||||
4. `gitea_mark_final_review_decision` → `gitea_review_pr` / `gitea_submit_pr_review`
|
||||
5. `gitea_merge_pr` only with `confirmation="MERGE PR <n>"` and pinned head SHA.
|
||||
|
||||
## Step 2: Implement issues (author profile)
|
||||
|
||||
1. `gitea_resolve_task_capability` for the author task.
|
||||
2. `gitea_lock_issue` before implementation mutations.
|
||||
3. Claim with `gitea_mark_issue` / `status:in-progress` label.
|
||||
4. Branch, implement, test, push, `gitea_create_pr`.
|
||||
5. Release claim when done; never self-review the PR.
|
||||
|
||||
## Step 3: Operator follow-ups
|
||||
|
||||
Wiki publication, credential provisioning, and cross-repo mirror operations are
|
||||
operator-confirmed actions — see [Runbooks](Runbooks.md).
|
||||
|
||||
Full Gitea-specific runbooks: `docs/llm-workflow-runbooks.md` in the repository.
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# sync-gitea-wiki.sh — mirror the repo-tracked docs/wiki/ pages into the
|
||||
# Gitea native wiki. docs/wiki/ remains the source of truth; the Gitea Wiki
|
||||
# is a read convenience mirrored FROM it, never edited directly.
|
||||
#
|
||||
# scripts/sync-gitea-wiki.sh dry-run (default): print the plan
|
||||
# scripts/sync-gitea-wiki.sh --push actually sync, ONLY with the exact
|
||||
# confirmation below
|
||||
#
|
||||
# Safety contract:
|
||||
# - Dry-run is the default and performs no network or repository-mutating
|
||||
# operation (only a local read of the origin remote URL).
|
||||
# - A push requires GITEA_WIKI_SYNC_CONFIRM to equal exactly
|
||||
# "SYNC WIKI <repo-name>" (repo name derived from the origin remote).
|
||||
# Anything else refuses before any clone happens.
|
||||
# - The wiki remote is derived from the local origin remote; nothing is
|
||||
# hardcoded here and no credential material is read, printed, or stored
|
||||
# by this script — git's own configured auth is used as-is.
|
||||
# - Only *.md pages from docs/wiki/ are mirrored; nothing else is touched
|
||||
# and no page is deleted from the wiki by this script.
|
||||
|
||||
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
repo_root="$(cd "$here/.." && pwd)"
|
||||
wiki_src="$repo_root/docs/wiki"
|
||||
|
||||
[ -d "$wiki_src" ] || { echo "error: $wiki_src not found" >&2; exit 1; }
|
||||
|
||||
if git -C "$repo_root" remote get-url origin >/dev/null 2>&1; then
|
||||
origin_url="$(git -C "$repo_root" remote get-url origin)"
|
||||
elif git -C "$repo_root" remote get-url prgs >/dev/null 2>&1; then
|
||||
origin_url="$(git -C "$repo_root" remote get-url prgs)"
|
||||
else
|
||||
echo "error: configure an origin or prgs git remote" >&2
|
||||
exit 1
|
||||
fi
|
||||
repo_name="$(basename "$origin_url" .git)"
|
||||
wiki_remote="${origin_url%.git}.wiki.git"
|
||||
expected_confirm="SYNC WIKI $repo_name"
|
||||
|
||||
pages=()
|
||||
while IFS= read -r -d '' f; do
|
||||
pages+=("$(basename "$f")")
|
||||
done < <(find "$wiki_src" -maxdepth 1 -name '*.md' -print0 | sort -z)
|
||||
|
||||
mode="${1:-}"
|
||||
|
||||
if [ "$mode" != "--push" ]; then
|
||||
echo "dry-run: would sync ${#pages[@]} pages from docs/wiki/ to the '$repo_name' Gitea Wiki:"
|
||||
for p in "${pages[@]}"; do
|
||||
echo " $p"
|
||||
done
|
||||
echo "dry-run: no git or network operation performed."
|
||||
echo "To sync for real: GITEA_WIKI_SYNC_CONFIRM=\"$expected_confirm\" $0 --push"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "${GITEA_WIKI_SYNC_CONFIRM:-}" != "$expected_confirm" ]; then
|
||||
echo "refused: --push requires GITEA_WIKI_SYNC_CONFIRM to equal exactly:" >&2
|
||||
echo " $expected_confirm" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
workdir="$(mktemp -d)"
|
||||
trap 'rm -rf "$workdir"' EXIT
|
||||
|
||||
echo "cloning wiki repository for '$repo_name'"
|
||||
if ! git clone --quiet -- "$wiki_remote" "$workdir/wiki" 2>/dev/null; then
|
||||
echo "error: could not clone the wiki repository. If this repo's wiki has" >&2
|
||||
echo "never been initialized, create its first page once in the Gitea UI" >&2
|
||||
echo "(Wiki tab -> New Page), then re-run this script." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp "$wiki_src"/*.md "$workdir/wiki/"
|
||||
|
||||
if git -C "$workdir/wiki" status --porcelain | grep -q .; then
|
||||
git -C "$workdir/wiki" add -A
|
||||
git -C "$workdir/wiki" commit --quiet -m "docs: sync from repo docs/wiki (source of truth)"
|
||||
echo "pushing wiki update for '$repo_name'"
|
||||
git -C "$workdir/wiki" push --quiet
|
||||
echo "done: ${#pages[@]} pages synced."
|
||||
else
|
||||
echo "done: wiki already up to date; nothing pushed."
|
||||
fi
|
||||
@@ -0,0 +1,112 @@
|
||||
"""Checks for the Gitea Wiki sync helper (issue #224).
|
||||
|
||||
The repo-tracked ``docs/wiki/`` stays the source of truth; the helper
|
||||
mirrors it into the Gitea native wiki only when explicitly invoked.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
SCRIPT = REPO_ROOT / "scripts" / "sync-gitea-wiki.sh"
|
||||
|
||||
REQUIRED_PAGES = [
|
||||
"Home.md",
|
||||
"Operator-Guide.md",
|
||||
"Repositories.md",
|
||||
"Identity-and-Profiles.md",
|
||||
"Workflow.md",
|
||||
"Safety-and-Gates.md",
|
||||
"MCP-Tools.md",
|
||||
"Runbooks.md",
|
||||
"Open-Decisions.md",
|
||||
"History.md",
|
||||
]
|
||||
|
||||
|
||||
def _run(*args, env_extra=None):
|
||||
env = dict(os.environ)
|
||||
env.pop("GITEA_WIKI_SYNC_CONFIRM", None)
|
||||
if env_extra:
|
||||
env.update(env_extra)
|
||||
return subprocess.run(
|
||||
[str(SCRIPT), *args], capture_output=True, text=True, env=env,
|
||||
cwd=str(REPO_ROOT), timeout=30)
|
||||
|
||||
|
||||
def test_script_exists_and_is_executable():
|
||||
assert SCRIPT.is_file(), "missing scripts/sync-gitea-wiki.sh"
|
||||
assert os.access(SCRIPT, os.X_OK), "sync script is not executable"
|
||||
|
||||
|
||||
def test_dry_run_is_default_and_lists_every_page():
|
||||
result = _run()
|
||||
assert result.returncode == 0, result.stderr
|
||||
out = result.stdout
|
||||
assert "dry-run" in out.lower()
|
||||
for page in REQUIRED_PAGES:
|
||||
assert page in out, f"dry-run plan does not list {page}"
|
||||
|
||||
|
||||
def test_dry_run_does_not_push_or_clone():
|
||||
result = _run()
|
||||
blob = (result.stdout + result.stderr).lower()
|
||||
assert "pushing" not in blob
|
||||
assert "cloning" not in blob
|
||||
|
||||
|
||||
def test_push_refused_without_exact_confirmation():
|
||||
result = _run("--push")
|
||||
assert result.returncode != 0
|
||||
blob = result.stdout + result.stderr
|
||||
assert "GITEA_WIKI_SYNC_CONFIRM" in blob
|
||||
assert "cloning" not in blob.lower()
|
||||
|
||||
|
||||
def test_push_refused_with_wrong_confirmation():
|
||||
result = _run("--push", env_extra={"GITEA_WIKI_SYNC_CONFIRM": "yes please"})
|
||||
assert result.returncode != 0
|
||||
assert "cloning" not in (result.stdout + result.stderr).lower()
|
||||
|
||||
|
||||
def test_script_embeds_no_service_urls_or_secrets():
|
||||
text = SCRIPT.read_text(encoding="utf-8")
|
||||
for marker in ("http://", "https://", "token ", "Authorization", "ghp_", "keychain"):
|
||||
assert marker not in text, f"script embeds {marker!r}"
|
||||
|
||||
|
||||
def test_runbook_documents_wiki_sync():
|
||||
runbooks = (REPO_ROOT / "docs" / "wiki" / "Runbooks.md").read_text(encoding="utf-8")
|
||||
assert "sync-gitea-wiki" in runbooks
|
||||
home = (REPO_ROOT / "docs" / "wiki" / "Home.md").read_text(encoding="utf-8")
|
||||
assert "source of truth" in home
|
||||
template = (REPO_ROOT / ".gitea" / "pull_request_template.md").read_text(encoding="utf-8")
|
||||
assert "sync-gitea-wiki" in template
|
||||
|
||||
|
||||
def test_wiki_pages_have_no_local_file_links():
|
||||
for path in (REPO_ROOT / "docs" / "wiki").glob("*.md"):
|
||||
text = path.read_text(encoding="utf-8")
|
||||
assert "file://" not in text, f"{path.name} contains a file:// link"
|
||||
|
||||
|
||||
def test_pr_template_carries_wiki_publication_gate():
|
||||
template = (REPO_ROOT / ".gitea" / "pull_request_template.md").read_text(encoding="utf-8")
|
||||
assert "Wiki tab" in template
|
||||
assert "#224" in template
|
||||
assert "not sufficient to close a wiki issue" in template
|
||||
|
||||
|
||||
def test_runbooks_document_publication_gate_and_closure_rule():
|
||||
runbooks = (REPO_ROOT / "docs" / "wiki" / "Runbooks.md").read_text(encoding="utf-8")
|
||||
assert "Wiki Publication Readiness Gate (#224)" in runbooks or "Wiki publication readiness gate (#224)" in runbooks.lower()
|
||||
assert "Closure prevention" in runbooks
|
||||
assert "GITEA_WIKI_SYNC_CONFIRM" in runbooks
|
||||
|
||||
|
||||
def test_repositories_map_tracks_wiki_publication_status():
|
||||
repositories = (REPO_ROOT / "docs" / "wiki" / "Repositories.md").read_text(encoding="utf-8")
|
||||
assert "Wiki publication status" in repositories or "Wiki Publication Status" in repositories
|
||||
for repo in ("mcp-control-plane", "Gitea-Tools"):
|
||||
assert repo in repositories
|
||||
assert "Gitea Wiki published" in repositories
|
||||
Reference in New Issue
Block a user