Skip to content

Commit b2b18cd

Browse files
authored
fix: overhaul docs build process (#103)
Fixes the documentation build failure caused by attempting to checkout a non-existent `gh-pages` branch. This PR modernizes the documentation build and deployment workflow to use GitHub's current best practices for GitHub Pages deployment (2025).
1 parent 1cfb6b8 commit b2b18cd

File tree

3 files changed

+37
-93
lines changed

3 files changed

+37
-93
lines changed

.github/workflows/docs.yml

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
name: Documentation Build
22

33
on:
4-
release:
5-
types: [published]
64
push:
75
branches:
86
- main
97

8+
permissions:
9+
contents: read
10+
1011
jobs:
11-
docs:
12-
permissions:
13-
contents: write
12+
build:
1413
runs-on: ubuntu-latest
1514
steps:
1615
- uses: actions/checkout@v4
@@ -27,23 +26,25 @@ jobs:
2726
- name: Build documentation
2827
run: uv run python tools/build_docs.py docs-build
2928

30-
- name: Package documentation artifact
31-
run: tar -czvf docs-build.tar.gz docs-build
32-
33-
- name: Upload Release Asset
34-
if: github.event_name == 'release'
35-
uses: actions/upload-release-asset@v1
36-
env:
37-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
- name: Upload Pages artifact
30+
uses: actions/upload-pages-artifact@v4
3831
with:
39-
upload_url: ${{ github.event.release.upload_url }}
40-
asset_path: ./docs-build.tar.gz
41-
asset_name: docs-build-${{ github.ref_name }}.tar.gz
42-
asset_content_type: application/gzip
43-
44-
- name: Upload 'latest' docs artifact
45-
if: github.event_name == 'push'
46-
uses: actions/upload-artifact@v4
47-
with:
48-
name: latest-docs
49-
path: docs-build.tar.gz
32+
path: docs-build
33+
34+
deploy:
35+
needs: build
36+
37+
permissions:
38+
pages: write
39+
id-token: write
40+
41+
environment:
42+
name: github-pages
43+
url: ${{ steps.deployment.outputs.page_url }}
44+
45+
runs-on: ubuntu-latest
46+
47+
steps:
48+
- name: Deploy to GitHub Pages
49+
id: deployment
50+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,4 @@ CRUSH.md
6565
*.md
6666
!./README.md
6767
!./CONTRIBUTING.md
68+
docs-build

tools/build_docs.py

Lines changed: 11 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,34 @@
11
from __future__ import annotations
22

33
import argparse
4-
import importlib.metadata
5-
import json
6-
import os
74
import shutil
85
import subprocess
9-
from collections.abc import Generator
10-
from contextlib import contextmanager
116
from pathlib import Path
12-
from typing import TYPE_CHECKING, TypedDict, cast
13-
14-
if TYPE_CHECKING:
15-
from collections.abc import Generator
16-
17-
REDIRECT_TEMPLATE = """
18-
<!DOCTYPE HTML>
19-
<html lang="en-US">
20-
<head>
21-
<title>Page Redirection</title>
22-
<meta charset="UTF-8">
23-
<meta http-equiv="refresh" content="0; url={target}">
24-
<script type="text/javascript">window.location.href = "{target}"</script>
25-
</head>
26-
<body>
27-
You are being redirected. If this does not work, click <a href='{target}'>this link</a>
28-
</body>
29-
</html>
30-
"""
317

328
parser = argparse.ArgumentParser()
33-
parser.add_argument("--version", required=False)
349
parser.add_argument("output")
3510

3611

37-
class VersionSpec(TypedDict):
38-
versions: list[str]
39-
latest: str
40-
41-
42-
@contextmanager
43-
def checkout(branch: str) -> Generator[None]:
44-
subprocess.run(["git", "checkout", branch], check=True) # noqa: S607
45-
yield
46-
subprocess.run(["git", "checkout", "-"], check=True) # noqa: S607
47-
48-
49-
def load_version_spec() -> VersionSpec:
50-
versions_file = Path("docs/_static/versions.json")
51-
if versions_file.exists():
52-
return cast("VersionSpec", json.loads(versions_file.read_text()))
53-
return {"versions": [], "latest": ""}
54-
55-
56-
def build(output_dir: str, version: str | None) -> None:
57-
if version is None:
58-
version = importlib.metadata.version("sqlspec").rsplit(".")[0]
59-
else:
60-
os.environ["_SQLSPEC_DOCS_BUILD_VERSION"] = version
61-
12+
def build(output_dir: str) -> None:
6213
subprocess.run(["make", "docs"], check=True) # noqa: S607
6314

64-
Path(output_dir).mkdir()
65-
Path(output_dir).joinpath(".nojekyll").touch(exist_ok=True)
66-
67-
version_spec = load_version_spec()
68-
is_latest = version == version_spec["latest"]
69-
7015
docs_src_path = Path("docs/_build/html")
16+
output_path = Path(output_dir)
7117

72-
Path(output_dir).joinpath("index.html").write_text(REDIRECT_TEMPLATE.format(target="latest"))
73-
74-
if is_latest:
75-
shutil.copytree(docs_src_path, Path(output_dir) / "latest", dirs_exist_ok=True)
76-
shutil.copytree(docs_src_path, Path(output_dir) / version, dirs_exist_ok=True)
18+
output_path.mkdir(parents=True, exist_ok=True)
19+
output_path.joinpath(".nojekyll").touch(exist_ok=True)
7720

78-
# copy existing versions into our output dir to preserve them when cleaning the branch
79-
with checkout("gh-pages"):
80-
for other_version in [*version_spec["versions"], "latest"]:
81-
other_version_path = Path(other_version)
82-
other_version_target_path = Path(output_dir) / other_version
83-
if other_version_path.exists() and not other_version_target_path.exists():
84-
shutil.copytree(other_version_path, other_version_target_path)
21+
for item in docs_src_path.iterdir():
22+
dest = output_path / item.name
23+
if item.is_dir():
24+
shutil.copytree(item, dest, dirs_exist_ok=True)
25+
else:
26+
shutil.copy2(item, dest)
8527

8628

8729
def main() -> None:
8830
args = parser.parse_args()
89-
build(output_dir=args.output, version=args.version)
31+
build(output_dir=args.output)
9032

9133

9234
if __name__ == "__main__":

0 commit comments

Comments
 (0)