diff --git a/copier.yaml b/copier.yaml index c7f206d..d60f498 100644 --- a/copier.yaml +++ b/copier.yaml @@ -79,4 +79,4 @@ publish_to_pypi: ############# Tasks ################## _tasks: - "ln -sf AGENTS.md CLAUDE.md" - - "bash -c '[[ -f site-docs/zensical.toml ]] && [[ ! -e zensical.toml ]] && ln -sf site-docs/zensical.toml . || echo No need to link zensical.toml'" + - "bash -c 'command -v uv >/dev/null && uv lock || echo uv not found, run uv lock before pushing'" diff --git a/template/.gitignore b/template/.gitignore index 354d9a8..f5ff83d 100644 --- a/template/.gitignore +++ b/template/.gitignore @@ -167,6 +167,7 @@ venv.bak/ # mkdocs documentation /site +/site-docs/site # mypy .mypy_cache/ diff --git a/template/Makefile.jinja b/template/Makefile.jinja index ba05e20..6652b2f 100644 --- a/template/Makefile.jinja +++ b/template/Makefile.jinja @@ -58,13 +58,30 @@ serve: ## Run the service @uv run python -m {{package_name}}.main {% endif %} {% if enable_docs_site %} +{% if project_type == 'cli' %} +.PHONY: cli-docs +cli-docs: ## Regenerate site-docs/docs/cli-reference.md from Typer --help + @echo "🚀 Regenerating CLI reference from --help" + @uv run python scripts/gen_cli_reference.py + +.PHONY: docs +docs: cli-docs ## Build the documentation site (regenerates CLI reference first) + @echo "🚀 Building documentation site" + @uv run zensical build -f site-docs/zensical.toml + +.PHONY: docs-serve +docs-serve: cli-docs ## Serve the documentation site locally + @echo "🚀 Serving documentation site" + @uv run zensical serve -f site-docs/zensical.toml +{% else %} .PHONY: docs docs: ## Build the documentation site @echo "🚀 Building documentation site" - @uv run zensical build + @uv run zensical build -f site-docs/zensical.toml .PHONY: docs-serve docs-serve: ## Serve the documentation site locally @echo "🚀 Serving documentation site" - @uv run zensical serve + @uv run zensical serve -f site-docs/zensical.toml +{% endif %} {% endif %} diff --git a/template/{% if enable_docs_site %}.github{% endif%}/workflows/docs.yaml.jinja b/template/{% if enable_docs_site %}.github{% endif%}/workflows/docs.yaml.jinja new file mode 100644 index 0000000..6f0d138 --- /dev/null +++ b/template/{% if enable_docs_site %}.github{% endif%}/workflows/docs.yaml.jinja @@ -0,0 +1,45 @@ +name: Documentation +on: + push: + branches: + - main + - master + pull_request: + workflow_dispatch: +permissions: + contents: read +concurrency: + group: pages + cancel-in-progress: false +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 + with: + python-version: 3.x + - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + - run: uv sync --frozen +{%- if project_type == 'cli' %} + - run: uv run python scripts/gen_cli_reference.py +{%- endif %} + - run: uv run zensical build --clean -f site-docs/zensical.toml + - uses: actions/upload-pages-artifact@v5 + with: + path: site-docs/site + + deploy: + needs: build + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: {{ '${{ steps.deployment.outputs.page_url }}' }} + steps: + - uses: actions/configure-pages@v6 + - uses: actions/deploy-pages@v5 + id: deployment diff --git a/template/{% if enable_docs_site %}.github{% endif%}/workflows/docs.yml b/template/{% if enable_docs_site %}.github{% endif%}/workflows/docs.yml deleted file mode 100644 index 47ee722..0000000 --- a/template/{% if enable_docs_site %}.github{% endif%}/workflows/docs.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Documentation -on: - push: - branches: - - master - - main -permissions: - contents: read - pages: write - id-token: write -jobs: - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - steps: - - uses: actions/configure-pages@v6 - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: 3.x - - run: pip install zensical - - run: zensical build --clean - - uses: actions/upload-pages-artifact@v5 - with: - path: site - - uses: actions/deploy-pages@v5 - id: deployment diff --git a/template/{% if enable_docs_site %}site-docs{% endif%}/docs/{% if project_type == 'cli' %}cli-reference.md{% endif %}.jinja b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/{% if project_type == 'cli' %}cli-reference.md{% endif %}.jinja new file mode 100644 index 0000000..fd2ac2a --- /dev/null +++ b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/{% if project_type == 'cli' %}cli-reference.md{% endif %}.jinja @@ -0,0 +1,12 @@ +--- +icon: lucide/book +description: Complete reference for every {{ project_name }} command, auto-generated from --help. +tags: + - reference + - cli +--- + +!!! info "Auto-generated" + This page is regenerated from `{{ project_name }} --help` by `make cli-docs`. + Run `make docs` (or `make cli-docs`) to populate it. Do not edit by hand — + your changes will be overwritten on the next build. diff --git a/template/{% if enable_docs_site %}site-docs{% endif%}/zensical.toml.jinja b/template/{% if enable_docs_site %}site-docs{% endif%}/zensical.toml.jinja index fb86620..933490f 100644 --- a/template/{% if enable_docs_site %}site-docs{% endif%}/zensical.toml.jinja +++ b/template/{% if enable_docs_site %}site-docs{% endif%}/zensical.toml.jinja @@ -3,12 +3,15 @@ site_name = "{{ project_name }}" site_url = "https://trobz.github.io/{{ project_name }}" site_description = "{{ project_description }}" site_author = "Trobz" -docs_dir = "site-docs/docs" +docs_dir = "docs" site_dir = "site" copyright = "Copyright © 2026 Trobz" nav = [ {Home = "index.md"}, {"Getting Started" = "getting-started.md"}, +{%- if project_type == 'cli' %} + {"CLI Reference" = "cli-reference.md"}, +{%- endif %} ] extra_css = [ "stylesheets/hero.css", @@ -25,7 +28,7 @@ path = "javascripts/hero-scene.js" [project.theme] language = "en" -custom_dir = "site-docs/overrides" +custom_dir = "overrides" features = [ "content.code.copy", "content.code.select", @@ -55,7 +58,7 @@ toggle.name = "Switch to light mode" [[project.extra.social]] icon = "fontawesome/brands/github" -link = "https://github.com/trobz/odoo-venv" +link = "https://github.com/{{ repository_namespace }}/{{ repository_name }}" [[project.extra.social]] icon = "fontawesome/brands/python" diff --git a/template/{% if project_type == 'cli' and enable_docs_site %}scripts{% endif %}/gen_cli_reference.py.jinja b/template/{% if project_type == 'cli' and enable_docs_site %}scripts{% endif %}/gen_cli_reference.py.jinja new file mode 100644 index 0000000..97a7d11 --- /dev/null +++ b/template/{% if project_type == 'cli' and enable_docs_site %}scripts{% endif %}/gen_cli_reference.py.jinja @@ -0,0 +1,53 @@ +"""Regenerate site-docs/docs/cli-reference.md from the Typer app. + +Invoked by `make cli-docs` (and transitively `make docs`). Keeps the public +docs site in sync with whatever flags/commands exist in {{ package_name }}.main +without manual edits — add a flag, run `make docs`, commit the diff. +""" + +from __future__ import annotations + +import re +import subprocess +from pathlib import Path + +OUT = Path(__file__).resolve().parent.parent / "site-docs" / "docs" / "cli-reference.md" + +HEADER = """--- +icon: lucide/book +description: Complete reference for every {{ project_name }} command, auto-generated from --help. +tags: + - reference + - cli +--- + +!!! info "Auto-generated" + This page is regenerated from `{{ project_name }} --help` by `make cli-docs`. + Do not edit by hand — your changes will be overwritten on the next build. + +""" + + +def main() -> None: + # `uv` is on PATH in the dev (`make`) and CI (`setup-uv`) environments. + body = subprocess.check_output( + ["uv", "run", "typer", "{{ package_name }}.main", "utils", "docs", "--name", "{{ project_name }}"], # noqa: S607 + text=True, + ) + # Typer emits `[default: X]`, `[required]`, etc. which Zensical/Markdown + # parses as link references. Escape the brackets so they render literally. + body = re.sub( + r"\[(default|env var|required)([^\]]*)\]", + lambda m: rf"\[{m.group(1)}{m.group(2)}\]", + body, + ) + OUT.write_text(HEADER + body) + try: + rel = OUT.relative_to(Path.cwd()) + except ValueError: + rel = OUT + print(f"Wrote {rel} ({len(body.splitlines())} lines from typer)") + + +if __name__ == "__main__": + main()