Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Publish Docs

on:
# The main CI workflow (ci-cd-ds-platform-utils.yaml) deliberately paths-ignores
# README.md and docs/**, so this workflow owns everything that feeds the docs site.
push:
branches:
- main
paths:
- "README.md"
- "docs/**"
- "mkdocs.yml"
- "scripts/mkdocs_hooks.py"
- "uv.lock"
- ".github/workflows/docs.yaml"
pull_request:
Comment on lines +4 to +16
types: [opened, synchronize]
paths:
- "README.md"
- "docs/**"
- "mkdocs.yml"
- "scripts/mkdocs_hooks.py"
- "uv.lock"
- ".github/workflows/docs.yaml"
workflow_dispatch:

# Read-only by default; only the deploy job widens this.
permissions:
contents: read

# One Pages deploy at a time. Do not cancel a deploy that is already publishing --
# a half-finished deploy would leave the live site in an inconsistent state.
concurrency:
group: pages
cancel-in-progress: false

jobs:
build:
name: Build Docs Site
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Set up uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-dependency-glob: "${{ github.workspace }}/uv.lock"

# --strict turns broken internal links into a build failure, so a PR that
# renames a doc cannot silently ship a dead link. --frozen forbids uv from
# resolving anything not already pinned in uv.lock.
- name: Build Site
run: uv run --frozen --group docs mkdocs build --strict

- name: Upload Pages Artifact
if: github.event_name != 'pull_request'
uses: actions/upload-pages-artifact@v3
with:
path: ./site

deploy:
name: Deploy to GitHub Pages
needs: build
# Pull requests build (to catch broken links) but never publish.
# if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
pages: write # to publish the Pages deployment
id-token: write # to let deploy-pages verify the artifact's origin
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy Artifact
id: deployment
uses: actions/deploy-pages@v4
69 changes: 69 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
site_name: ds-platform-utils
site_description: Utility library for Pattern Data Science.
site_url: https://patterninc.github.io/ds-platform-utils/
repo_url: https://github.com/patterninc/ds-platform-utils
repo_name: patterninc/ds-platform-utils
edit_uri: edit/main/docs/

# `index.md` is generated from README.md at build time -- see scripts/mkdocs_hooks.py
hooks:
- scripts/mkdocs_hooks.py

theme:
name: material
features:
- navigation.sections
- navigation.top
- navigation.tracking
- content.code.copy
- content.action.edit
- search.suggest
- search.highlight
- toc.follow
palette:
- media: "(prefers-color-scheme: light)"
scheme: default
primary: indigo
accent: indigo
toggle:
icon: material/weather-night
name: Switch to dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: indigo
accent: indigo
toggle:
icon: material/weather-sunny
name: Switch to light mode

nav:
- Home: index.md
- Metaflow API Docs:
- BatchInferencePipeline: metaflow/batch_inference_pipeline.md
- uv_pypi_base / uv_pypi: metaflow/pypi_packages.md
- make_pydantic_parser_fn: metaflow/make_pydantic_parser_fn.md
- publish: metaflow/publish.md
- publish_pandas: metaflow/publish_pandas.md
- query_pandas_from_snowflake: metaflow/query_pandas_from_snowflake.md
- restore_step_state: metaflow/restore_step_state.md
- Admin / Setup:
- Private repo access in Fast Bakery: metaflow/private_repo_access.md
- Table-ownership registry view: metaflow/table_ownership_registry.md

markdown_extensions:
- admonition
- attr_list
- def_list
- footnotes
- tables
- toc:
permalink: true
- pymdownx.details
- pymdownx.superfences
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.tabbed:
alternate_style: true

plugins:
- search
13 changes: 13 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ dev = [
"ipykernel>=6.30.0",
"pytest-xdist>=3.8.0",
]
# mkdocs<2 is a hard pin: MkDocs 2.0 removes the plugin system and theming that
# mkdocs-material and our build hook rely on, with no migration path.
Comment on lines +35 to +36
docs = [
"mkdocs>=1.6,<2",
"mkdocs-material>=9.5,<10",
]


[build-system]
Expand Down Expand Up @@ -148,6 +154,13 @@ help = "Run linting, formatting, projen synth, and other static code quality too
cmd = "pytest"
help = "Run all tests with optional additional arguments"

[tool.poe.tasks.docs-build]
shell = "uv run --group docs mkdocs build --strict"
help = "Build the documentation site into ./site (fails on broken links)"

[tool.poe.tasks.docs-serve]
shell = "uv run --group docs mkdocs serve"
help = "Serve the docs with live reload on http://localhost:8000"

[tool.poe.tasks.serve-coverage-report]
help = "Serve the coverage report on http://localhost:3333"
Expand Down
41 changes: 41 additions & 0 deletions scripts/mkdocs_hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Build hooks for the MkDocs documentation site.

The repo `README.md` is the single source of truth for the docs landing page, so it is
injected into the site as `index.md` at build time rather than being duplicated into
`docs/`. Its links are written to resolve on github.com (`docs/metaflow/publish.md`),
which must be rebased because the generated `index.md` sits at the docs root.
"""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import Files

REPO_ROOT = Path(__file__).parent.parent
README_PATH = REPO_ROOT / "README.md"

# `README.md` lives one level above `docs/`, so its links carry a `docs/` prefix that the
# generated `index.md` does not need: `](docs/metaflow/x.md)` -> `](metaflow/x.md)`.
GITHUB_LINK_PREFIX = "](docs/"
SITE_LINK_PREFIX = "]("


def on_files(files: Files, config: MkDocsConfig) -> Files:
"""Add the README to the site as the generated landing page, `index.md`."""
from mkdocs.structure.files import File

markdown = README_PATH.read_text(encoding="utf-8").replace(GITHUB_LINK_PREFIX, SITE_LINK_PREFIX)
index = File.generated(config, "index.md", content=markdown)

# Point "edit this page" at the README, not the nonexistent `docs/index.md`. MkDocs
# builds the URL as `edit_uri + file.edit_uri` and then urljoin()s it onto `repo_url`,
# which resolves the `..` -- so this yields `<repo>/edit/main/README.md`. Generated
# files default to no edit link at all, so this must be set explicitly.
index.edit_uri = "../README.md"

files.append(index)
return files
Loading
Loading