Skip to content

Commit 69b3b2e

Browse files
committed
docs: implement publishing pipeline (#617)
Add docs-publish.yml workflow that builds, validates, and deploys docs to orphan deployment branches (docs/staging from main, docs/production from releases). Replaces docs-autogen-pr.yml. Includes pre-commit hooks for MDX validation and docstring quality, docs/PUBLISHING.md strategy document, and .gitignore entries for generated API docs. Validation is soft-fail by default with strict_validation toggle. workflow_dispatch supports force_publish for testing.
1 parent 8003b44 commit 69b3b2e

5 files changed

Lines changed: 365 additions & 85 deletions

File tree

.github/workflows/docs-autogen-pr.yml

Lines changed: 0 additions & 84 deletions
This file was deleted.

.github/workflows/docs-publish.yml

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
name: Publish Documentation
2+
3+
# Builds, validates, and deploys documentation to orphan deployment branches.
4+
# Mintlify reads from these branches — main stays clean of generated artifacts.
5+
#
6+
# See docs/PUBLISHING.md for the full architecture and strategy.
7+
8+
on:
9+
push:
10+
branches: [main]
11+
paths:
12+
- "docs/**"
13+
- "mellea/**"
14+
- "cli/**"
15+
- "tooling/docs-autogen/**"
16+
- ".github/workflows/docs-publish.yml"
17+
18+
release:
19+
types: [published]
20+
21+
pull_request:
22+
paths:
23+
- "docs/**"
24+
- "mellea/**"
25+
- "cli/**"
26+
- "tooling/docs-autogen/**"
27+
- ".github/workflows/docs-publish.yml"
28+
29+
workflow_dispatch:
30+
inputs:
31+
force_publish:
32+
description: "Deploy even from a non-main context (for testing)"
33+
type: boolean
34+
default: false
35+
target_branch:
36+
description: "Override deploy target branch (default: docs/staging)"
37+
type: string
38+
default: "docs/staging"
39+
strict_validation:
40+
description: "Fail the build if validation checks fail"
41+
type: boolean
42+
default: false
43+
44+
permissions:
45+
contents: write
46+
47+
concurrency:
48+
group: docs-publish-${{ github.ref }}
49+
cancel-in-progress: true
50+
51+
env:
52+
UV_FROZEN: "1"
53+
54+
jobs:
55+
# ---------------------------------------------------------------------------
56+
# Build & Validate
57+
# ---------------------------------------------------------------------------
58+
build-and-validate:
59+
runs-on: ubuntu-latest
60+
timeout-minutes: 30
61+
62+
steps:
63+
- name: Checkout
64+
uses: actions/checkout@v4
65+
with:
66+
fetch-depth: 0
67+
68+
- name: Set up uv
69+
uses: astral-sh/setup-uv@v5
70+
with:
71+
enable-cache: true
72+
cache-dependency-glob: "uv.lock"
73+
74+
- name: Install dependencies
75+
run: uv sync --frozen --all-extras --group dev
76+
77+
# -- Generate API documentation ------------------------------------------
78+
79+
- name: Build wheel
80+
run: uv build --wheel
81+
82+
- name: Generate API documentation
83+
run: uv run python tooling/docs-autogen/build.py
84+
85+
# -- Validate static docs ------------------------------------------------
86+
87+
- name: Lint static docs (markdownlint)
88+
run: npx --yes markdownlint-cli "docs/docs/**/*.md" --config docs/docs/.markdownlint.json
89+
continue-on-error: ${{ inputs.strict_validation != true }}
90+
91+
# -- Validate generated API docs -----------------------------------------
92+
93+
- name: Validate MDX syntax and links
94+
run: uv run python tooling/docs-autogen/validate.py docs/docs/api --skip-coverage
95+
continue-on-error: ${{ inputs.strict_validation != true }}
96+
97+
- name: Audit API coverage
98+
run: uv run python tooling/docs-autogen/audit_coverage.py --docs-dir docs/docs/api --threshold 80
99+
continue-on-error: ${{ inputs.strict_validation != true }}
100+
101+
# -- Upload artifact for deploy job --------------------------------------
102+
103+
- name: Upload docs artifact
104+
if: success() || (inputs.strict_validation != true)
105+
uses: actions/upload-artifact@v4
106+
with:
107+
name: docs-site
108+
path: docs/docs/
109+
retention-days: 7
110+
111+
# ---------------------------------------------------------------------------
112+
# Deploy to orphan branch
113+
# ---------------------------------------------------------------------------
114+
deploy:
115+
needs: build-and-validate
116+
runs-on: ubuntu-latest
117+
timeout-minutes: 10
118+
119+
# Deploy on: push to main, release, or force_publish via dispatch.
120+
# Never deploy on regular PRs.
121+
if: >-
122+
github.event_name == 'push' ||
123+
github.event_name == 'release' ||
124+
(github.event_name == 'workflow_dispatch' && inputs.force_publish)
125+
126+
steps:
127+
- name: Download docs artifact
128+
uses: actions/download-artifact@v4
129+
with:
130+
name: docs-site
131+
path: docs-site/
132+
133+
- name: Determine target branch
134+
id: target
135+
run: |
136+
if [ "${{ github.event_name }}" = "release" ]; then
137+
echo "branch=docs/production" >> "$GITHUB_OUTPUT"
138+
elif [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ inputs.target_branch }}" ]; then
139+
echo "branch=${{ inputs.target_branch }}" >> "$GITHUB_OUTPUT"
140+
else
141+
echo "branch=docs/staging" >> "$GITHUB_OUTPUT"
142+
fi
143+
144+
- name: Add DO NOT EDIT warning
145+
run: |
146+
cat > docs-site/_DO_NOT_EDIT.md << 'EOF'
147+
# DO NOT EDIT THIS BRANCH
148+
149+
This branch is **fully automated**. Every file here is generated by
150+
the `docs-publish` GitHub Actions workflow and force-pushed on each run.
151+
152+
**Any manual edits will be overwritten without warning.**
153+
154+
To change documentation:
155+
- Static guides: edit files under `docs/docs/` on `main`
156+
- API reference: improve docstrings in Python source (`mellea/`, `cli/`)
157+
- Pipeline config: see `tooling/docs-autogen/` on `main`
158+
159+
For details, see `docs/PUBLISHING.md` on `main`.
160+
EOF
161+
162+
- name: Deploy to ${{ steps.target.outputs.branch }}
163+
uses: peaceiris/actions-gh-pages@v4
164+
with:
165+
github_token: ${{ secrets.GITHUB_TOKEN }}
166+
publish_branch: ${{ steps.target.outputs.branch }}
167+
publish_dir: docs-site/
168+
force_orphan: true
169+
user_name: "github-actions[bot]"
170+
user_email: "github-actions[bot]@users.noreply.github.com"
171+
commit_message: "docs: publish from ${{ github.sha }}"

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,3 +452,7 @@ pyrightconfig.json
452452
# AI agent configs
453453
.bob/
454454
.claude/
455+
456+
# Generated API documentation (built by tooling/docs-autogen/)
457+
docs/docs/api/
458+
docs/docs/api-reference.mdx

.pre-commit-config.yaml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,18 @@ repos:
3434
additional_dependencies:
3535
- tomli
3636

37-
37+
# Docs validation hooks — skip gracefully when generated docs are not present
38+
- repo: local
39+
hooks:
40+
- id: docs-mdx-validate
41+
name: Validate generated MDX docs
42+
entry: bash -c 'test -d docs/docs/api && uv run --no-sync python tooling/docs-autogen/validate.py docs/docs/api --skip-coverage || true'
43+
language: system
44+
pass_filenames: false
45+
files: (docs/docs/.*\.mdx$|tooling/docs-autogen/)
46+
- id: docs-docstring-quality
47+
name: Audit docstring quality (informational)
48+
entry: bash -c 'test -d docs/docs/api && uv run --no-sync python tooling/docs-autogen/audit_coverage.py --quality --no-methods --docs-dir docs/docs/api || true'
49+
language: system
50+
pass_filenames: false
51+
files: (mellea/.*\.py$|cli/.*\.py$)

0 commit comments

Comments
 (0)