From 4f30a031bbfdef4105e3e11c2bb8fb3bcf4a5ec9 Mon Sep 17 00:00:00 2001 From: Koda YeenBean Date: Sun, 19 Jul 2026 22:34:26 +0100 Subject: [PATCH] fixing wiki generation (#38) Reviewed-on: https://git.ascheu.de/Koda/OpenUniFi/pulls/38 Co-authored-by: Koda YeenBean --- .gitea/workflows/documentation.yaml | 47 ++++++++++++++++++++++++++--- .gitea/workflows/release.yaml | 7 +++-- AGENTS.md | 6 ++-- README.md | 25 +++++++++------ scripts/docs/generate-wiki.py | 44 ++++++++++++++++----------- scripts/docs/publish-wiki.sh | 30 ++++++++---------- src/inform/packet.c | 1 - src/inform/payload.c | 1 - src/inform/response.c | 1 - src/wlan/legacy.c | 1 - src/wlan/provision.c | 1 - src/wlan/radio.c | 1 - src/wlan/uci.c | 2 -- 13 files changed, 105 insertions(+), 62 deletions(-) diff --git a/.gitea/workflows/documentation.yaml b/.gitea/workflows/documentation.yaml index a346616..a274b8b 100644 --- a/.gitea/workflows/documentation.yaml +++ b/.gitea/workflows/documentation.yaml @@ -1,9 +1,15 @@ -name: Validate source documentation +name: Generate and publish developer Wiki on: pull_request: + push: + branches: [main] workflow_dispatch: +concurrency: + group: openunifi-wiki + cancel-in-progress: false + permissions: code: read @@ -11,10 +17,41 @@ jobs: generated-wiki: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Check out source repository + uses: actions/checkout@v4 with: fetch-depth: 2 - - name: Check generated Gitea Wiki pages - run: ./scripts/docs/generate-wiki.py --check + path: source - name: Check patch whitespace - run: git diff --check HEAD^ + run: git -C source diff --check HEAD^ HEAD + - name: Validate documentation generator + run: | + mkdir -p "$RUNNER_TEMP/openuf-wiki" + python3 source/scripts/docs/generate-wiki.py --output "$RUNNER_TEMP/openuf-wiki" + python3 source/scripts/docs/generate-wiki.py --check --output "$RUNNER_TEMP/openuf-wiki" + - name: Check out Wiki repository + if: github.event_name != 'pull_request' + uses: actions/checkout@v4 + with: + repository: Koda/openunifi.wiki + token: ${{ secrets.GITEA_TOKEN }} + path: wiki + - name: Generate and verify Gitea Wiki pages + if: github.event_name != 'pull_request' + run: | + python3 source/scripts/docs/generate-wiki.py --output wiki + python3 source/scripts/docs/generate-wiki.py --check --output wiki + - name: Publish changed Wiki pages + if: github.event_name != 'pull_request' + working-directory: wiki + run: | + set -eu + git config user.name "openUF documentation bot" + git config user.email "actions@openuf.invalid" + git add -- Home.md Developer-Guide.md Call-Graph.md Runtime-Flow.md _Sidebar.md + if git diff --cached --quiet; then + echo "Gitea Wiki is already current" + exit 0 + fi + git commit -m "docs: update generated developer wiki" + git push origin HEAD diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index daa6e6a..be11d7f 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -22,8 +22,11 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Verify generated developer Wiki - run: ./scripts/docs/generate-wiki.py --check + - name: Validate documentation generator + run: | + mkdir -p "$RUNNER_TEMP/openuf-wiki" + python3 ./scripts/docs/generate-wiki.py --output "$RUNNER_TEMP/openuf-wiki" + python3 ./scripts/docs/generate-wiki.py --check --output "$RUNNER_TEMP/openuf-wiki" - name: Install metadata dependencies run: sudo apt-get update && sudo apt-get install --yes jq - name: Read release configuration diff --git a/AGENTS.md b/AGENTS.md index 9e52e7b..30588da 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -74,11 +74,11 @@ make package/OpenUniFi/compile packages installed; it is not a host-side substitute for the cross-build. Architecture pages for the Gitea Wiki are generated from the recursive C source -tree. After source or architecture changes, run: +tree into a separate checkout. After source or architecture changes, run: ```sh -./scripts/docs/generate-wiki.py -./scripts/docs/generate-wiki.py --check +./scripts/docs/generate-wiki.py --output /path/to/openunifi.wiki +./scripts/docs/generate-wiki.py --check --output /path/to/openunifi.wiki ``` There is currently no automated test suite. For documentation-only changes, diff --git a/README.md b/README.md index da65c50..a4498de 100644 --- a/README.md +++ b/README.md @@ -48,25 +48,32 @@ architecture map, invariants, and validation checklist. ## Developer documentation and Gitea Wiki -The publish-ready Gitea Wiki pages live in [`wiki/`](wiki/). They include a -developer guide, a generated Mermaid function-call graph, and runtime flow -charts. Refresh them after source or architecture changes: +The publish-ready pages live in the separate `Koda/openunifi.wiki` repository. +They include a developer guide, a generated Mermaid function-call graph, and +runtime flow charts. Check out that repository, then refresh it after source or +architecture changes: ```shell -./scripts/docs/generate-wiki.py +./scripts/docs/generate-wiki.py --output /path/to/openunifi.wiki ``` Use the same tool as a linter to reject stale pages, oversized C modules, missing documented entry points, or known non-English comment fragments: ```shell -./scripts/docs/generate-wiki.py --check +./scripts/docs/generate-wiki.py --check --output /path/to/openunifi.wiki ``` -Because Gitea stores Wiki pages in a separate Git repository, publishing is an -explicit authenticated step: `./scripts/docs/publish-wiki.sh`. The script -derives the `.wiki.git` URL from `origin` and accepts an explicit URL override. -No credentials are stored in this repository. +The generator uses only the Python 3 standard library, and the publisher uses +POSIX shell utilities and Git. Neither downloads or executes an x86-only helper, +so both run natively on ARM and x86 build agents. + +Publishing is an explicit authenticated step: `./scripts/docs/publish-wiki.sh`. +The script derives the lowercase `.wiki.git` repository URL from `origin`, +checks it out before generating, and accepts an explicit URL override. No +credentials are stored in this repository. The documentation workflow performs +the same two-checkout process and requires `GITEA_TOKEN` to have write access to +`Koda/openunifi.wiki`. ## Automated releases diff --git a/scripts/docs/generate-wiki.py b/scripts/docs/generate-wiki.py index 07bf88d..e7625c1 100755 --- a/scripts/docs/generate-wiki.py +++ b/scripts/docs/generate-wiki.py @@ -12,7 +12,6 @@ from pathlib import Path REPOSITORY_ROOT = Path(__file__).resolve().parents[2] SOURCE_ROOT = REPOSITORY_ROOT / "src" -DEFAULT_WIKI_ROOT = REPOSITORY_ROOT / "wiki" MAX_IMPLEMENTATION_LINES = 900 CONTROL_WORDS = { @@ -325,18 +324,22 @@ development packages installed. It is not a host-side test substitute. ## Documentation workflow -Generate pages after changing C code or architecture: +Check out the separate `openunifi.wiki` repository, then generate pages after +changing C code or architecture: ```sh -./scripts/docs/generate-wiki.py +./scripts/docs/generate-wiki.py --output /path/to/openunifi.wiki ``` Run the linter-style drift and structure check in CI or before committing: ```sh -./scripts/docs/generate-wiki.py --check +./scripts/docs/generate-wiki.py --check --output /path/to/openunifi.wiki ``` +The generator uses only the Python 3 standard library. The publisher uses POSIX +shell utilities and Git, so neither path depends on the runner CPU architecture. + The checker parses C functions recursively, rebuilds internal call edges, validates required runtime entry points, rejects known non-English comment fragments, and limits each implementation unit to @@ -344,21 +347,20 @@ fragments, and limits each implementation unit to ## Publishing to the Gitea Wiki -Gitea stores a repository Wiki in a separate Git repository whose URL normally -ends in `.wiki.git`. The generated `wiki/` directory is ready for that remote. -Run `scripts/docs/publish-wiki.sh` from a trusted machine with suitable -credentials. It derives the Wiki remote from `origin`; an explicit URL may be -passed when needed. The publisher regenerates and checks the pages, -updates only the generated Markdown files, commits changed pages, and pushes -them to the Wiki repository. +Gitea stores this documentation in the separate lowercase +`openunifi.wiki` repository. Run `scripts/docs/publish-wiki.sh` from a trusted +machine with suitable credentials. It derives that repository from `origin`; +an explicit URL may be passed when needed. The publisher checks out the Wiki +repository before generating, updates only the generated Markdown files, +commits changed pages, and pushes them back to the Wiki repository. """ def home_page() -> str: return """# openUF Developer Wiki -This Wiki is generated from the current source tree and maintained in the main -repository so architecture documentation changes can be reviewed with code. +This Wiki is generated from the current source tree and maintained in the +separate `openunifi.wiki` repository. - [[Developer Guide|Developer-Guide]] — architecture, invariants, extension points, build validation, and Wiki publishing. @@ -367,7 +369,8 @@ repository so architecture documentation changes can be reviewed with code. - [[Function Call Graph|Call-Graph]] — generated internal caller/callee graph and searchable function table. -Run `./scripts/docs/generate-wiki.py --check` to verify these pages are current. +Run `./scripts/docs/generate-wiki.py --check --output /path/to/openunifi.wiki` +from the source checkout to verify these pages are current. """ @@ -543,8 +546,10 @@ def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--check", action="store_true", help="fail if generated pages or source checks are stale") - parser.add_argument("--output", type=Path, default=DEFAULT_WIKI_ROOT, - help="Wiki output directory (default: repository wiki/)") + parser.add_argument( + "--output", type=Path, required=True, metavar="WIKI_CHECKOUT", + help="path to the checked-out openunifi.wiki repository", + ) arguments = parser.parse_args() functions = discover_functions() @@ -568,8 +573,11 @@ def main() -> int: for error in errors: print(f"documentation error: {error}", file=sys.stderr) if arguments.check: - print("run ./scripts/docs/generate-wiki.py to refresh pages", - file=sys.stderr) + print( + "run ./scripts/docs/generate-wiki.py --output " + f"{output} to refresh pages", + file=sys.stderr, + ) return 1 action = "verified" if arguments.check else "generated" diff --git a/scripts/docs/publish-wiki.sh b/scripts/docs/publish-wiki.sh index bd8fd3f..08489ab 100755 --- a/scripts/docs/publish-wiki.sh +++ b/scripts/docs/publish-wiki.sh @@ -17,10 +17,13 @@ if [ -z "$wiki_repository_url" ]; then echo "no origin remote found; pass the Gitea Wiki repository URL" >&2 exit 2 fi - case $origin_url in - *.git) wiki_repository_url=${origin_url%.git}.wiki.git ;; - *) wiki_repository_url=${origin_url}.wiki.git ;; - esac + source_repository_url=${origin_url%.git} + repository_parent=${source_repository_url%/*} + repository_name=${source_repository_url##*/} + wiki_repository_name=$( + printf '%s' "$repository_name" | tr '[:upper:]' '[:lower:]' + ) + wiki_repository_url="$repository_parent/$wiki_repository_name.wiki.git" fi cleanup() { @@ -28,20 +31,11 @@ cleanup() { } trap cleanup EXIT HUP INT TERM -"$script_directory/generate-wiki.py" -"$script_directory/generate-wiki.py" --check - git clone -- "$wiki_repository_url" "$temporary_directory/wiki" -for page in \ - Home.md \ - Developer-Guide.md \ - Call-Graph.md \ - Runtime-Flow.md \ - _Sidebar.md -do - cp -- "$repository_root/wiki/$page" "$temporary_directory/wiki/$page" -done +"$script_directory/generate-wiki.py" --output "$temporary_directory/wiki" +"$script_directory/generate-wiki.py" --check \ + --output "$temporary_directory/wiki" cd "$temporary_directory/wiki" git add -- Home.md Developer-Guide.md Call-Graph.md Runtime-Flow.md _Sidebar.md @@ -51,5 +45,7 @@ if git diff --cached --quiet; then exit 0 fi -git commit -m "docs: update generated developer wiki" +git -c user.name="openUF documentation bot" \ + -c user.email="actions@openuf.invalid" \ + commit -m "docs: update generated developer wiki" git push origin HEAD diff --git a/src/inform/packet.c b/src/inform/packet.c index 635c54e..11a0c37 100644 --- a/src/inform/packet.c +++ b/src/inform/packet.c @@ -145,4 +145,3 @@ char *inform_packet_parse(const unsigned char *data, size_t data_len, copy[body_len] = '\0'; return copy; } - diff --git a/src/inform/payload.c b/src/inform/payload.c index 5f67cf1..72b25c3 100644 --- a/src/inform/payload.c +++ b/src/inform/payload.c @@ -799,4 +799,3 @@ char *inform_build_payload(const openuf_state_t *st, json_object_put(root); return copy; } - diff --git a/src/inform/response.c b/src/inform/response.c index 3d23d21..e1baa57 100644 --- a/src/inform/response.c +++ b/src/inform/response.c @@ -358,4 +358,3 @@ void inform_handle_response(openuf_state_t *st, snprintf(action_out, 64, "unknown:%s", type); } - diff --git a/src/wlan/legacy.c b/src/wlan/legacy.c index 87a20a6..1b2e6e5 100644 --- a/src/wlan/legacy.c +++ b/src/wlan/legacy.c @@ -268,4 +268,3 @@ int wlan_apply_system_cfg(const char *system_cfg, json_object_put(root); return result; } - diff --git a/src/wlan/provision.c b/src/wlan/provision.c index 4a0d7c0..b722017 100644 --- a/src/wlan/provision.c +++ b/src/wlan/provision.c @@ -583,4 +583,3 @@ int wlan_apply_config(struct json_object *config_json, system("/etc/init.d/usteer restart >/dev/null 2>&1"); return 0; } - diff --git a/src/wlan/radio.c b/src/wlan/radio.c index fae7eb5..4a0082c 100644 --- a/src/wlan/radio.c +++ b/src/wlan/radio.c @@ -315,4 +315,3 @@ void wlan_apply_radio(struct json_object *radio_json, uci_unload(ctx, pkg); uci_free_context(ctx); } - diff --git a/src/wlan/uci.c b/src/wlan/uci.c index c77f5d6..8cd958c 100644 --- a/src/wlan/uci.c +++ b/src/wlan/uci.c @@ -306,5 +306,3 @@ void wlan_clear(void) uci_unload(ctx, pkg); uci_free_context(ctx); } - -