You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by me...@apache.org on 2026/07/14 20:35:26 UTC
(fineract-site) 01/03: automate /docs/VERSION updates
This is an automated email from the ASF dual-hosted git repository.
meonkeys pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/fineract-site.git
commit bb2276d2565e33293b6414d3bc9424c3c151d5d5
Author: Adam Monsen <ha...@gmail.com>
AuthorDate: Tue Jul 14 13:04:31 2026 -0700
automate /docs/VERSION updates
Coded by Claude (model=Sonnet 5, effort=High).
I reviewed and tested this.
---
README.md | 33 +++++++++++
scripts/generate_docs.py | 145 +++++++++++++++++++++++++++++++++++++++++++++++
scripts/site-tool.sh | 10 +++-
3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 58b811a..45894e4 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,39 @@ docker run --rm -v "${PWD}:/src" -w /src/site-src fineract-site build
docker run --rm -it -p 1313:1313 -v "${PWD}:/src" -w /src/site-src fineract-site serve
```
+## Updating `/docs/VERSION` from a Fineract backend clone
+
+`docs/VERSION` (e.g. `docs/1.16.0-SNAPSHOT`) holds the rendered Fineract API
+documentation built from the [apache/fineract](https://github.com/apache/fineract)
+backend. To refresh it:
+
+1. In your clone of `apache/fineract`, generate the docs:
+
+ ```bash
+ ./gradlew asciidoctor
+ ```
+
+ Make sure the clone's working tree is clean (`git status`) — the commit hash
+ is recorded so the copied doc can be traced back to the exact source commit.
+
+2. Run the `docs` command in the site tool image, mounting both repos:
+
+ ```bash
+ docker run --rm -u "$(id -u):$(id -g)" \
+ -v "$PWD:/src" \
+ -v /path/to/fineract:/fineract:ro \
+ -w /src \
+ fineract-site docs --version 1.16.0-SNAPSHOT
+ ```
+
+ The version can also be set via `FINERACT_DOC_VERSION`, and the backend
+ mount path via `FINERACT_REPO_DIR` (default `/fineract`).
+
+This copies `fineract-doc/build/docs/html/en/index.html` from the backend clone
+into `docs/VERSION/index.html`, then rewrites the Google Fonts and Font Awesome
+CDN links to point at the site's local `css/` stylesheets. Versions ending in
+`-SNAPSHOT` are overwritten; released versions are not.
+
## Verifying ASF project website compliance
Apache Whimsy periodically checks that the public homepage follows ASF conventions.
diff --git a/scripts/generate_docs.py b/scripts/generate_docs.py
new file mode 100644
index 0000000..3ffb3f9
--- /dev/null
+++ b/scripts/generate_docs.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+"""Copy generated Fineract API docs from a backend clone into docs/VERSION.
+
+Assumes the backend (apache/fineract) has already been built with
+`./gradlew asciidoctor` and is available at --backend-dir (or
+$FINERACT_REPO_DIR), e.g. mounted as a Docker volume.
+"""
+
+import argparse
+import os
+import shutil
+import subprocess
+import sys
+from pathlib import Path
+
+REPO_ROOT = Path(__file__).resolve().parent.parent
+DEFAULT_BACKEND_DIR = "/fineract"
+DOC_HTML_RELATIVE_PATH = Path("fineract-doc/build/docs/html/en/index.html")
+
+# Same substitution made by hand in commits like e70425660b42fc705760006141078e870df0a566.
+GOOGLE_FONTS_LINK = (
+ '<link rel="stylesheet" href="https://fonts.googleapis.com/css?family='
+ "Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,"
+ '400italic,700,700italic%7CDroid+Sans+Mono:400,700">'
+)
+LOCAL_STYLESHEET_LINK = '<link rel="stylesheet" href="../../css/stylesheet.css">'
+FONT_AWESOME_CDN_LINK = (
+ '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/'
+ 'font-awesome/4.7.0/css/font-awesome.min.css">'
+)
+FONT_AWESOME_LOCAL_LINK = '<link rel="stylesheet" href="../../css/font-awesome.min.css">'
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument(
+ "--version",
+ default=os.environ.get("FINERACT_DOC_VERSION"),
+ help="Doc version folder to write, e.g. 1.16.0-SNAPSHOT "
+ "(default: $FINERACT_DOC_VERSION)",
+ )
+ parser.add_argument(
+ "--backend-dir",
+ default=os.environ.get("FINERACT_REPO_DIR", DEFAULT_BACKEND_DIR),
+ help="Path to the apache/fineract clone "
+ f"(default: $FINERACT_REPO_DIR or {DEFAULT_BACKEND_DIR})",
+ )
+ args = parser.parse_args()
+ if not args.version:
+ parser.error("a version is required: pass --version or set FINERACT_DOC_VERSION")
+ return args
+
+
+def run_git(backend_dir, *git_args):
+ return subprocess.run(
+ ["git", "-C", str(backend_dir), *git_args],
+ check=True,
+ capture_output=True,
+ text=True,
+ )
+
+
+def require_clean_git_status(backend_dir):
+ result = run_git(backend_dir, "status", "--porcelain")
+ if result.stdout.strip():
+ sys.exit(
+ f"Backend clone at {backend_dir} is not clean (git status --porcelain "
+ "reported changes). Commit or stash them so the copied doc can be "
+ f"traced back to an exact commit:\n{result.stdout}"
+ )
+
+
+def get_commit_hash(backend_dir):
+ return run_git(backend_dir, "rev-parse", "HEAD").stdout.strip()
+
+
+def localize_stylesheets(html_path):
+ text = html_path.read_text(encoding="utf-8")
+ text = text.replace(GOOGLE_FONTS_LINK, LOCAL_STYLESHEET_LINK)
+ text = text.replace(FONT_AWESOME_CDN_LINK, FONT_AWESOME_LOCAL_LINK)
+ if not text.endswith("\n"):
+ text += "\n"
+ html_path.write_text(text, encoding="utf-8")
+
+
+def main():
+ args = parse_args()
+ backend_dir = Path(args.backend_dir)
+
+ if not backend_dir.is_dir():
+ sys.exit(f"Backend directory not found: {backend_dir}")
+
+ source_html = backend_dir / DOC_HTML_RELATIVE_PATH
+ if not source_html.is_file():
+ sys.exit(
+ f"{source_html} not found. Generate it first by running "
+ "'./gradlew asciidoctor' in the backend clone."
+ )
+
+ require_clean_git_status(backend_dir)
+ commit_hash = get_commit_hash(backend_dir)
+ print(f"Backend commit: {commit_hash}")
+
+ github_output = os.environ.get("GITHUB_OUTPUT")
+ if github_output:
+ with open(github_output, "a", encoding="utf-8") as f:
+ f.write(f"fineract_commit={commit_hash}\n")
+
+ dest_dir = REPO_ROOT / "docs" / args.version
+ dest_html = dest_dir / "index.html"
+ is_snapshot = args.version.endswith("-SNAPSHOT")
+
+ if dest_html.exists() and not is_snapshot:
+ sys.exit(
+ f"{dest_html} already exists and {args.version} is not a -SNAPSHOT "
+ "version. Refusing to overwrite a released doc."
+ )
+
+ dest_dir.mkdir(parents=True, exist_ok=True)
+ shutil.copy2(source_html, dest_html)
+ localize_stylesheets(dest_html)
+
+ print(f"Wrote {dest_html}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/site-tool.sh b/scripts/site-tool.sh
index 139e99d..f821c33 100644
--- a/scripts/site-tool.sh
+++ b/scripts/site-tool.sh
@@ -3,11 +3,12 @@ set -euo pipefail
usage() {
cat <<'EOF'
-Usage: site-tool <build|check|serve|shell> [args...]
+Usage: site-tool <build|check|docs|serve|shell> [args...]
Commands:
build Build site into /src/.build/site and run checks
check Run internal link check against /src/.build/site
+ docs Copy generated Fineract API docs into /src/docs/VERSION
test Run unit tests for whimsy checks
serve Run hugo server on port 1313
shell Open an interactive shell
@@ -52,6 +53,10 @@ run_tests() {
ruby "${REPO_ROOT}/scripts/test_run_whimsy_checks.rb"
}
+generate_docs() {
+ python3 "${REPO_ROOT}/scripts/generate_docs.py" "$@"
+}
+
serve_site() {
cd "${SITE_SRC_DIR}"
hugo server --bind 0.0.0.0 --baseURL "http://localhost:1313" --buildDrafts --disableFastRender "$@"
@@ -75,6 +80,9 @@ main() {
check)
run_checks
;;
+ docs)
+ generate_docs "$@"
+ ;;
test)
run_tests
;;