diff --git a/.github/workflows/docs_delete_version.yaml b/.github/workflows/docs_delete_version.yaml new file mode 100644 index 00000000..fd51115d --- /dev/null +++ b/.github/workflows/docs_delete_version.yaml @@ -0,0 +1,96 @@ +# Docs Delete Version Workflow +# This workflow automatically deletes documentation versions when tags are deleted +# Reference documentation: +# - GitHub Actions: https://docs.github.com/en/actions +# - uv package manager: https://docs.astral.sh/uv/ +# - MkDocs: https://www.mkdocs.org/ +# - Mike: https://github.com/jimporter/mike + +name: Docs Delete Version + +# Trigger conditions: runs when tags are deleted +on: + delete: + # We will guard in the job to only run for tag deletions + +jobs: + delete_version: + name: Delete docs version on tag removal + # Only run when a tag is deleted (not branch deletion) + if: github.event.ref_type == 'tag' + # Use Ubuntu 22.04 as the runtime environment + runs-on: ubuntu-22.04 + + # Set permissions: need write permissions to update documentation + permissions: + contents: write # Allow writing to repository content + + # Concurrency control: ensures multiple workflows on the same tag do not run simultaneously + concurrency: + group: ${{ github.workflow }}-${{ github.event.ref }}-delete + cancel-in-progress: true # Cancel running identical workflows + + steps: + # Step 1: Checkout code + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch complete history, some tools may require this + + # Step 2: Setup Python environment + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.9' # Keep consistent with requirements in pyproject.toml + + # Step 3: Install uv package manager + # uv is an extremely fast Python package manager written in Rust + # Compared to pip, uv has significant advantages in dependency resolution and installation speed + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "latest" # Use the latest version of uv + enable-cache: false # Disable built-in cache to avoid conflicts with multiple uv.lock files + + # Step 4: Cache uv dependencies + # Caching can significantly reduce build time, especially for large projects + - name: Cache uv dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cache/uv + docs/.venv + key: ${{ runner.os }}-docs-uv-${{ hashFiles('docs/uv.lock') }}-${{ hashFiles('docs/pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-docs-uv- + ${{ runner.os }}-uv- + + # Step 5: Install dependencies and configure Git + - name: Install dependencies and configure Git + run: | + cd docs + uv sync + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Step 6: Delete docs version with mike + - name: Delete docs version with mike + run: | + cd docs + make delete-doc-version version=${{ github.event.ref }} + + # Step 7: Re-point latest alias to highest remaining tag (if any) + - name: Re-point latest alias to highest remaining tag (if any) + run: | + set -e + # Find highest remaining v* tag after deletion + REMAINING_TAG=$(uv run mike list | sort -V | tail -n 1) + if [ -z "$REMAINING_TAG" ]; then + echo "No remaining version tags; skipping latest alias update" + exit 0 + fi + echo "Re-pointing latest to ${REMAINING_TAG}" + cd docs + uv run mike alias --push --update "$REMAINING_TAG" latest + uv run mike set-default --push latest + diff --git a/.github/workflows/docs_deploy_pages.yaml b/.github/workflows/docs_deploy_pages.yaml new file mode 100644 index 00000000..42015f38 --- /dev/null +++ b/.github/workflows/docs_deploy_pages.yaml @@ -0,0 +1,98 @@ +# Docs Deploy Pages Workflow +# This workflow uses uv for Python dependency management and automatically builds and deploys MkDocs documentation to GitHub Pages +# Reference documentation: +# - GitHub Actions: https://docs.github.com/en/actions +# - uv package manager: https://docs.astral.sh/uv/ +# - MkDocs: https://www.mkdocs.org/ +# - GitHub Pages: https://docs.github.com/en/pages + +name: Docs Deploy Pages + +# Trigger conditions: runs when pushing to a tag +on: + push: + tags: + # This pattern matches release version numbers according to PEP 440 (e.g., v1.2.3, 1.2.3), excluding pre/post/dev versions + # Note: This is used to trigger this workflow only for release version tags + - 'v[0-9]*.[0-9]*.[0-9]*' + +jobs: + deploy: + # Use Ubuntu 22.04 as the runtime environment + runs-on: ubuntu-22.04 + + # Set permissions: need write permissions to deploy to GitHub Pages + permissions: + contents: write # Allow writing to repository content + pages: write # Allow writing to Pages + id-token: write # Allow writing ID token (for authentication) + + # Concurrency control: ensures multiple workflows on the same branch do not run simultaneously + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true # Cancel running identical workflows + + steps: + # Step 1: Checkout code + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch complete history, some tools may require this + + # Step 2: Setup Python environment + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.9' # Keep consistent with requirements in pyproject.toml + + # Step 3: Install uv package manager + # uv is an extremely fast Python package manager written in Rust + # Compared to pip, uv has significant advantages in dependency resolution and installation speed + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "latest" # Use the latest version of uv + enable-cache: false # Disable built-in cache to avoid conflicts with multiple uv.lock files + + # Step 4: Cache uv dependencies + # Caching can significantly reduce build time, especially for large projects + - name: Cache uv dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cache/uv + docs/.venv + key: ${{ runner.os }}-docs-uv-${{ hashFiles('docs/uv.lock') }}-${{ hashFiles('docs/pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-docs-uv- + ${{ runner.os }}-uv- + + # Step 5: Install dependencies and configure Git + - name: Install dependencies and configure Git + run: | + cd docs + uv sync + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Step 6: Build and deploy docs with mike + - name: Build and deploy docs with mike + run: | + cd docs + make build-doc-version version=${{ github.ref_name }} + + # Step 7: Ensure CNAME exists on gh-pages branch + - name: Ensure CNAME on gh-pages + run: | + set -e + DOMAIN=$(cat docs/CNAME 2>/dev/null) + git fetch origin gh-pages || true + git switch gh-pages + echo "$DOMAIN" > CNAME + git add CNAME + if git diff --cached --quiet; then + echo "CNAME unchanged" + else + git commit -m "chore: ensure CNAME for GitHub Pages" + git push origin gh-pages + fi \ No newline at end of file diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 00000000..b59a8bcb --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +docs.bridgic.ai diff --git a/docs/Makefile b/docs/Makefile index e5b1d578..553bde6f 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,6 +5,7 @@ HOST ?= 127.0.0.1 PORT ?= 8000 MKDOCS = uv run mkdocs +MIKE = uv run mike # Generate mkdocs.yml file from API reference documentation gen-mkdocs-yml: @@ -16,11 +17,28 @@ build-doc: @make gen-mkdocs-yml $(MKDOCS) build +require-version: + @if [ -z "$(version)" ]; then \ + echo "ERROR: version is required. Usage: make build-doc-version version=1.2.3"; \ + exit 1; \ + fi + +# build a specific version of the docs and point the latest alias to it +build-doc-version: require-version + @make gen-mkdocs-yml + $(MIKE) deploy --push --update-aliases $(version) latest + $(MIKE) set-default --push latest + +# Delete a deployed docs version and point the latest alias to the next highest version +delete-doc-version: require-version + @make gen-mkdocs-yml + $(MIKE) delete --push $(version) + # Start development server serve-doc: @uv sync @make gen-mkdocs-yml - $(MKDOCS) serve -a $(HOST):$(PORT) + $(MIKE) serve -a $(HOST):$(PORT) # Clean build artifacts clean: diff --git a/docs/overrides/main.html b/docs/overrides/main.html new file mode 100644 index 00000000..35591d61 --- /dev/null +++ b/docs/overrides/main.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block outdated %} + You're not viewing the latest version. + + Click here to go to latest. + +{% endblock %} \ No newline at end of file diff --git a/docs/pyproject.toml b/docs/pyproject.toml index 65435f13..c4dbfabe 100644 --- a/docs/pyproject.toml +++ b/docs/pyproject.toml @@ -19,4 +19,5 @@ dependencies = [ "mkdocs-literate-nav>=0.6.2", "mkdocs-section-index>=0.3.10", "pyyaml>=6.0.2", + "mike>=2.1.3", ] diff --git a/docs/scripts/mkdocs_template.yml b/docs/scripts/mkdocs_template.yml index 2993f666..c8f1133a 100644 --- a/docs/scripts/mkdocs_template.yml +++ b/docs/scripts/mkdocs_template.yml @@ -32,6 +32,7 @@ theme: name: material logo: assets/logo.png favicon: assets/favicon.ico + custom_dir: overrides features: # Navigation # navigation.instant enables client-side navigation for faster page transitions. @@ -151,6 +152,7 @@ plugins: - ../bridgic-integration/llms/bridgic-llms-openai - ../bridgic-integration/llms/bridgic-llms-openai-like - ../bridgic-integration/llms/bridgic-llms-vllm + - mike markdown_extensions: # Python Markdown @@ -215,6 +217,8 @@ extra: # - icon: fontawesome/brands/discord # link: https://discord.gg/bridgic generator: false + version: + provider: mike # Developer-facing validation messages: catch broken links/anchors early without breaking builds validation: diff --git a/docs/uv.lock b/docs/uv.lock index 801acc65..5590c10c 100644 --- a/docs/uv.lock +++ b/docs/uv.lock @@ -134,6 +134,7 @@ source = { virtual = "." } dependencies = [ { name = "black" }, { name = "griffe-fieldz" }, + { name = "mike" }, { name = "mkdocs" }, { name = "mkdocs-autorefs" }, { name = "mkdocs-gen-files" }, @@ -152,6 +153,7 @@ dependencies = [ requires-dist = [ { name = "black", specifier = ">=25.9.0" }, { name = "griffe-fieldz", specifier = ">=0.3.0" }, + { name = "mike", specifier = ">=2.1.3" }, { name = "mkdocs", specifier = ">=1.6.1" }, { name = "mkdocs-autorefs", specifier = ">=1.4.3" }, { name = "mkdocs-gen-files", specifier = ">=0.5.0" }, @@ -576,13 +578,25 @@ name = "importlib-metadata" version = "8.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp", marker = "python_full_version < '3.10'" }, + { name = "zipp" }, ] sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, ] +[[package]] +name = "importlib-resources" +version = "6.5.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cf/8c/f834fbf984f691b4f7ff60f50b514cc3de5cc08abfc3295564dd89c5e2e7/importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c", size = 44693, upload-time = "2025-01-03T18:51:56.698Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec", size = 37461, upload-time = "2025-01-03T18:51:54.306Z" }, +] + [[package]] name = "ipykernel" version = "6.30.1" @@ -984,6 +998,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" }, ] +[[package]] +name = "mike" +version = "2.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata" }, + { name = "importlib-resources" }, + { name = "jinja2" }, + { name = "mkdocs" }, + { name = "pyparsing" }, + { name = "pyyaml" }, + { name = "pyyaml-env-tag" }, + { name = "verspec" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ab/f7/2933f1a1fb0e0f077d5d6a92c6c7f8a54e6128241f116dff4df8b6050bbf/mike-2.1.3.tar.gz", hash = "sha256:abd79b8ea483fb0275b7972825d3082e5ae67a41820f8d8a0dc7a3f49944e810", size = 38119, upload-time = "2024-08-13T05:02:14.167Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/1a/31b7cd6e4e7a02df4e076162e9783620777592bea9e4bb036389389af99d/mike-2.1.3-py3-none-any.whl", hash = "sha256:d90c64077e84f06272437b464735130d380703a76a5738b152932884c60c062a", size = 33754, upload-time = "2024-08-13T05:02:12.515Z" }, +] + [[package]] name = "mistune" version = "3.1.4" @@ -1436,6 +1469,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e4/06/43084e6cbd4b3bc0e80f6be743b2e79fbc6eed8de9ad8c629939fa55d972/pymdown_extensions-10.16.1-py3-none-any.whl", hash = "sha256:d6ba157a6c03146a7fb122b2b9a121300056384eafeec9c9f9e584adfdb2a32d", size = 266178, upload-time = "2025-07-28T16:19:31.401Z" }, ] +[[package]] +name = "pyparsing" +version = "3.2.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/a5/181488fc2b9d093e3972d2a472855aae8a03f000592dbfce716a512b3359/pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6", size = 1099274, upload-time = "2025-09-21T04:11:06.277Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e", size = 113890, upload-time = "2025-09-21T04:11:04.117Z" }, +] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -1973,6 +2015,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] +[[package]] +name = "verspec" +version = "0.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/44/8126f9f0c44319b2efc65feaad589cadef4d77ece200ae3c9133d58464d0/verspec-0.1.0.tar.gz", hash = "sha256:c4504ca697b2056cdb4bfa7121461f5a0e81809255b41c03dda4ba823637c01e", size = 27123, upload-time = "2020-11-30T02:24:09.646Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl", hash = "sha256:741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31", size = 19640, upload-time = "2020-11-30T02:24:08.387Z" }, +] + [[package]] name = "watchdog" version = "6.0.0"