Skip to content

Commit 276bcf7

Browse files
authored
🔧 Update docs build setup, add support for sponsors, add sponsor GOVCERT.LU (#720)
1 parent cc11619 commit 276bcf7

File tree

11 files changed

+220
-21
lines changed

11 files changed

+220
-21
lines changed

Diff for: ‎.github/workflows/build-docs.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ jobs:
3030
- pyproject.toml
3131
- mkdocs.yml
3232
- mkdocs.insiders.yml
33+
- ./github/workflows/build-docs.yml
34+
- ./github/workflows/deploy-docs.yml
3335
3436
build-docs:
3537
needs:
@@ -69,12 +71,10 @@ jobs:
6971
with:
7072
key: mkdocs-cards-${{ github.ref }}
7173
path: .cache
74+
- name: Verify README
75+
run: python ./scripts/docs.py verify-readme
7276
- name: Build Docs
73-
if: github.event_name == 'pull_request' && github.secret_source != 'Actions'
74-
run: python -m poetry run mkdocs build
75-
- name: Build Docs with Insiders
76-
if: github.event_name != 'pull_request' || github.secret_source == 'Actions'
77-
run: python -m poetry run mkdocs build --config-file mkdocs.insiders.yml
77+
run: python ./scripts/docs.py build
7878
- uses: actions/upload-artifact@v3
7979
with:
8080
name: docs-site

Diff for: ‎README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ The key features are:
3838
* **Extensible**: You have all the power of SQLAlchemy and Pydantic underneath.
3939
* **Short**: Minimize code duplication. A single type annotation does a lot of work. No need to duplicate models in SQLAlchemy and Pydantic.
4040

41+
## Sponsors
42+
43+
<!-- sponsors -->
44+
45+
<a href="https://www.govcert.lu" target="_blank" title="This project is being supported by GOVCERT.LU"><img src="https://sqlmodel.tiangolo.com/img/sponsors/govcert.png"></a>
46+
47+
<!-- /sponsors -->
48+
4149
## SQL Databases in FastAPI
4250

4351
<a href="https://fastapi.tiangolo.com" target="_blank"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" style="width: 20%;"></a>
@@ -68,7 +76,7 @@ Successfully installed sqlmodel
6876

6977
## Example
7078

71-
For an introduction to databases, SQL, and everything else, see the <a href="https://sqlmodel.tiangolo.com" target="_blank">SQLModel documentation</a>.
79+
For an introduction to databases, SQL, and everything else, see the <a href="https://sqlmodel.tiangolo.com/databases/" target="_blank">SQLModel documentation</a>.
7280

7381
Here's a quick example. ✨
7482

Diff for: ‎data/sponsors.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
gold: []
2+
silver:
3+
- url: https://www.govcert.lu
4+
title: This project is being supported by GOVCERT.LU
5+
img: https://sqlmodel.tiangolo.com/img/sponsors/govcert.png
6+
bronze: []

Diff for: ‎docs/img/sponsors/govcert.png

9.83 KB
Loading

Diff for: ‎docs/index.md

+19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
<style>
2+
.md-content .md-typeset h1 { display: none; }
3+
</style>
4+
15
<p align="center">
26
<a href="https://sqlmodel.tiangolo.com"><img src="https://sqlmodel.tiangolo.com/img/logo-margin/logo-margin-vector.svg" alt="SQLModel"></a>
37
</p>
@@ -38,6 +42,21 @@ The key features are:
3842
* **Extensible**: You have all the power of SQLAlchemy and Pydantic underneath.
3943
* **Short**: Minimize code duplication. A single type annotation does a lot of work. No need to duplicate models in SQLAlchemy and Pydantic.
4044

45+
## Sponsors
46+
47+
<!-- sponsors -->
48+
49+
{% if sponsors %}
50+
{% for sponsor in sponsors.gold -%}
51+
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
52+
{% endfor -%}
53+
{%- for sponsor in sponsors.silver -%}
54+
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
55+
{% endfor %}
56+
{% endif %}
57+
58+
<!-- /sponsors -->
59+
4160
## SQL Databases in FastAPI
4261

4362
<a href="https://fastapi.tiangolo.com" target="_blank"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" style="width: 20%;"></a>

Diff for: ‎mkdocs.insiders.yml

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
INHERIT: mkdocs.yml
21
plugins:
3-
- search
4-
- social
2+
social:
3+
typeset:

Diff for: ‎mkdocs.maybe-insiders.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Define this here and not in the main mkdocs.yml file because that one could be auto
2+
# updated and written, and the script would remove the env var
3+
INHERIT: !ENV [INSIDERS_FILE, './mkdocs.no-insiders.yml']
4+
markdown_extensions:
5+
pymdownx.highlight:
6+
linenums: !ENV [LINENUMS, false]

Diff for: ‎mkdocs.no-insiders.yml

Whitespace-only changes.

Diff for: ‎mkdocs.yml

+16-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
INHERIT: ./mkdocs.maybe-insiders.yml
12
site_name: SQLModel
23
site_description: SQLModel, SQL databases in Python, designed for simplicity, compatibility, and robustness.
34
site_url: https://sqlmodel.tiangolo.com/
@@ -36,6 +37,11 @@ theme:
3637
repo_name: tiangolo/sqlmodel
3738
repo_url: https://github.com/tiangolo/sqlmodel
3839
edit_uri: ''
40+
plugins:
41+
search: null
42+
markdownextradata:
43+
data: ./data
44+
3945
nav:
4046
- SQLModel: index.md
4147
- features.md
@@ -98,30 +104,28 @@ nav:
98104
- release-notes.md
99105

100106
markdown_extensions:
101-
- markdown.extensions.attr_list
102-
- markdown.extensions.tables
103-
- markdown.extensions.md_in_html
104-
- toc:
107+
markdown.extensions.attr_list:
108+
markdown.extensions.tables:
109+
markdown.extensions.md_in_html:
110+
toc:
105111
permalink: true
106-
- pymdownx.superfences:
112+
pymdownx.superfences:
107113
custom_fences:
108114
- name: mermaid
109115
class: mermaid
110116
format: !!python/name:pymdownx.superfences.fence_code_format ''
111-
- pymdownx.betterem
112-
- pymdownx.highlight:
113-
linenums: !ENV [LINENUMS, false]
114-
- pymdownx.blocks.details
115-
- pymdownx.blocks.admonition:
117+
pymdownx.betterem:
118+
pymdownx.blocks.details:
119+
pymdownx.blocks.admonition:
116120
types:
117121
- note
118122
- info
119123
- tip
120124
- warning
121125
- danger
122-
- pymdownx.blocks.tab:
126+
pymdownx.blocks.tab:
123127
alternate_style: True
124-
- mdx_include
128+
mdx_include:
125129

126130
extra:
127131
analytics:

Diff for: ‎pyproject.toml

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ fastapi = "^0.103.2"
5050
ruff = "^0.1.2"
5151
# For FastAPI tests
5252
httpx = "0.24.1"
53+
typer-cli = "^0.0.13"
54+
mkdocs-markdownextradata-plugin = ">=0.1.7,<0.3.0"
5355

5456
[build-system]
5557
requires = ["poetry-core"]

Diff for: ‎scripts/docs.py

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import logging
2+
import os
3+
import re
4+
import subprocess
5+
from functools import lru_cache
6+
from http.server import HTTPServer, SimpleHTTPRequestHandler
7+
from importlib import metadata
8+
from pathlib import Path
9+
10+
import mkdocs.commands.build
11+
import mkdocs.commands.serve
12+
import mkdocs.config
13+
import mkdocs.utils
14+
import typer
15+
from jinja2 import Template
16+
17+
logging.basicConfig(level=logging.INFO)
18+
19+
mkdocs_name = "mkdocs.yml"
20+
en_docs_path = Path("")
21+
22+
app = typer.Typer()
23+
24+
25+
@lru_cache
26+
def is_mkdocs_insiders() -> bool:
27+
version = metadata.version("mkdocs-material")
28+
return "insiders" in version
29+
30+
31+
@app.callback()
32+
def callback() -> None:
33+
if is_mkdocs_insiders():
34+
os.environ["INSIDERS_FILE"] = "./mkdocs.insiders.yml"
35+
# For MacOS with insiders and Cairo
36+
os.environ["DYLD_FALLBACK_LIBRARY_PATH"] = "/opt/homebrew/lib"
37+
38+
39+
index_sponsors_template = """
40+
{% if sponsors %}
41+
{% for sponsor in sponsors.gold -%}
42+
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
43+
{% endfor -%}
44+
{%- for sponsor in sponsors.silver -%}
45+
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
46+
{% endfor %}
47+
{% endif %}
48+
"""
49+
50+
51+
def generate_readme_content() -> str:
52+
en_index = en_docs_path / "docs" / "index.md"
53+
content = en_index.read_text("utf-8")
54+
match_pre = re.search(r"</style>\n\n", content)
55+
match_start = re.search(r"<!-- sponsors -->", content)
56+
match_end = re.search(r"<!-- /sponsors -->", content)
57+
sponsors_data_path = en_docs_path / "data" / "sponsors.yml"
58+
sponsors = mkdocs.utils.yaml_load(sponsors_data_path.read_text(encoding="utf-8"))
59+
if not (match_start and match_end):
60+
raise RuntimeError("Couldn't auto-generate sponsors section")
61+
if not match_pre:
62+
raise RuntimeError("Couldn't find pre section (<style>) in index.md")
63+
frontmatter_end = match_pre.end()
64+
pre_end = match_start.end()
65+
post_start = match_end.start()
66+
template = Template(index_sponsors_template)
67+
message = template.render(sponsors=sponsors)
68+
pre_content = content[frontmatter_end:pre_end]
69+
post_content = content[post_start:]
70+
new_content = pre_content + message + post_content
71+
return new_content
72+
73+
74+
@app.command()
75+
def generate_readme() -> None:
76+
"""
77+
Generate README.md content from main index.md
78+
"""
79+
typer.echo("Generating README")
80+
readme_path = Path("README.md")
81+
new_content = generate_readme_content()
82+
readme_path.write_text(new_content, encoding="utf-8")
83+
84+
85+
@app.command()
86+
def verify_readme() -> None:
87+
"""
88+
Verify README.md content from main index.md
89+
"""
90+
typer.echo("Verifying README")
91+
readme_path = Path("README.md")
92+
generated_content = generate_readme_content()
93+
readme_content = readme_path.read_text("utf-8")
94+
if generated_content != readme_content:
95+
typer.secho(
96+
"README.md outdated from the latest index.md", color=typer.colors.RED
97+
)
98+
raise typer.Abort()
99+
typer.echo("Valid README ✅")
100+
101+
102+
@app.command()
103+
def live() -> None:
104+
"""
105+
Serve with livereload a docs site for a specific language.
106+
107+
This only shows the actual translated files, not the placeholders created with
108+
build-all.
109+
110+
Takes an optional LANG argument with the name of the language to serve, by default
111+
en.
112+
"""
113+
# Enable line numbers during local development to make it easier to highlight
114+
os.environ["LINENUMS"] = "true"
115+
mkdocs.commands.serve.serve(dev_addr="127.0.0.1:8008")
116+
117+
118+
@app.command()
119+
def build() -> None:
120+
"""
121+
Build the docs.
122+
"""
123+
insiders_env_file = os.environ.get("INSIDERS_FILE")
124+
print(f"Insiders file {insiders_env_file}")
125+
if is_mkdocs_insiders():
126+
print("Using insiders")
127+
print("Building docs")
128+
subprocess.run(["mkdocs", "build"], check=True)
129+
typer.secho("Successfully built docs", color=typer.colors.GREEN)
130+
131+
132+
@app.command()
133+
def serve() -> None:
134+
"""
135+
A quick server to preview a built site.
136+
137+
For development, prefer the command live (or just mkdocs serve).
138+
139+
This is here only to preview the documentation site.
140+
141+
Make sure you run the build command first.
142+
"""
143+
typer.echo("Warning: this is a very simple server.")
144+
typer.echo("For development, use the command live instead.")
145+
typer.echo("This is here only to preview the documentation site.")
146+
typer.echo("Make sure you run the build command first.")
147+
os.chdir("site")
148+
server_address = ("", 8008)
149+
server = HTTPServer(server_address, SimpleHTTPRequestHandler)
150+
typer.echo("Serving at: http://127.0.0.1:8008")
151+
server.serve_forever()
152+
153+
154+
if __name__ == "__main__":
155+
app()

0 commit comments

Comments
 (0)