This is an automated email from the ASF dual-hosted git repository.
dheerajturaga pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 8f5b2e7fbe0 Render the database ERD as a searchable Mermaid diagram
instead of an image (#72006)
8f5b2e7fbe0 is described below
commit 8f5b2e7fbe002449712fe79b831a4df34e166d99
Author: Jyun-An Chen <[email protected]>
AuthorDate: Tue Sep 15 07:33:30 2026 +0800
Render the database ERD as a searchable Mermaid diagram instead of an image
(#72006)
The ERD reference pages embedded the schema as an SVG image, so table and
column names weren't indexed by search engines or full-text search. The
generate_erd Sphinx extension already regenerates the diagram from the live
SQLAlchemy models on every doc build, so switching its output format doesn't
introduce any new staleness risk. eralchemy (already a doc-build dependency)
can emit Mermaid ER-diagram markup directly, removing the need for the
graphviz system package during doc generation.
---
.gitignore | 6 +-
airflow-core/docs/database-erd-ref.rst | 4 +-
contributing-docs/14_metadata_database_updates.rst | 2 +-
devel-common/src/sphinx_exts/generate_erd.py | 78 ++++++++--------------
providers/edge3/docs/database-erd-ref.rst | 4 +-
providers/fab/docs/database-erd-ref.rst | 4 +-
6 files changed, 37 insertions(+), 61 deletions(-)
diff --git a/.gitignore b/.gitignore
index 64575d323cb..113e360ce5c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,9 +11,9 @@ airflow.db
# Airflow temporary artifacts
airflow-core/src/airflow/git_version
# ERD diagrams (generated at doc build time)
-airflow-core/docs/img/airflow_erd.svg
-providers/fab/docs/img/fab_erd.svg
-providers/edge3/docs/img/edge3_erd.svg
+airflow-core/docs/img/airflow_erd.mmd
+providers/fab/docs/img/fab_erd.mmd
+providers/edge3/docs/img/edge3_erd.mmd
airflow-core/src/airflow/ui/coverage/
# and legacy ones
airflow/git_version
diff --git a/airflow-core/docs/database-erd-ref.rst
b/airflow-core/docs/database-erd-ref.rst
index abb808385e6..a5ce3b885ea 100644
--- a/airflow-core/docs/database-erd-ref.rst
+++ b/airflow-core/docs/database-erd-ref.rst
@@ -33,6 +33,6 @@ Here is the current Database schema diagram.
`db command <cli-and-env-variables-ref.html#db>`_ for the commands that you
can use to manage
the migrations.
-.. This image is automatically generated during documentation build by the
``generate_erd`` Sphinx extension.
+.. This diagram is automatically generated during documentation build by the
``generate_erd`` Sphinx extension.
-.. image:: img/airflow_erd.svg
+.. mermaid:: img/airflow_erd.mmd
diff --git a/contributing-docs/14_metadata_database_updates.rst
b/contributing-docs/14_metadata_database_updates.rst
index b16d1c7432b..8a3ec2f24ed 100644
--- a/contributing-docs/14_metadata_database_updates.rst
+++ b/contributing-docs/14_metadata_database_updates.rst
@@ -84,7 +84,7 @@ To resolve these conflicts:
.. note::
- The ERD diagram (``airflow_erd.svg``) is no longer committed to the
repository. It is
+ The ERD diagram (``airflow_erd.mmd``) is no longer committed to the
repository. It is
automatically generated during the documentation build by the
``generate_erd`` Sphinx extension.
Running migration CI tests locally
diff --git a/devel-common/src/sphinx_exts/generate_erd.py
b/devel-common/src/sphinx_exts/generate_erd.py
index 1d4a6930883..3ee260aa688 100644
--- a/devel-common/src/sphinx_exts/generate_erd.py
+++ b/devel-common/src/sphinx_exts/generate_erd.py
@@ -17,7 +17,8 @@
"""Sphinx extension to generate Airflow database ERD diagrams at doc build
time.
Detects which package is being built via the ``AIRFLOW_PACKAGE_NAME``
environment
-variable and generates the appropriate ERD:
+variable and generates the appropriate ERD as Mermaid ER-diagram markup,
consumed
+by the ``.. mermaid::`` directive from ``sphinxcontrib-mermaid``:
* ``apache-airflow`` — core Airflow models only
* ``apache-airflow-providers-fab`` — FAB auth-manager models only
@@ -27,31 +28,23 @@ variable and generates the appropriate ERD:
from __future__ import annotations
import os
-import shutil
-import sys
from pathlib import Path
from sphinx.util import logging
log = logging.getLogger(__name__)
-PLACEHOLDER_SVG = """\
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="800" height="100">
- <rect width="800" height="100" fill="#fff3cd" stroke="#ffc107"
stroke-width="2" rx="8"/>
- <text x="400" y="40" text-anchor="middle" font-family="sans-serif"
font-size="16" fill="#856404">
- ERD diagram not generated: eralchemy or graphviz system package is not
available.
- </text>
- <text x="400" y="70" text-anchor="middle" font-family="sans-serif"
font-size="14" fill="#856404">
- Install graphviz (e.g. "brew install graphviz") and eralchemy, then
rebuild the docs.
- </text>
-</svg>
+PLACEHOLDER_MERMAID = """\
+erDiagram
+ ERD_NOT_GENERATED {
+ string reason "eralchemy is not available"
+ }
"""
-def _write_placeholder(svg_path: str) -> None:
- """Write a placeholder SVG so the doc build does not break with a missing
image."""
- Path(svg_path).write_text(PLACEHOLDER_SVG)
+def _write_placeholder(mmd_path: str) -> None:
+ """Write placeholder Mermaid markup so the doc build does not break with
missing content."""
+ Path(mmd_path).write_text(PLACEHOLDER_MERMAID)
def _collect_core_metadata():
@@ -102,14 +95,14 @@ def _collect_edge3_metadata():
# Map package names to their metadata collector and output filename.
_PACKAGE_ERD_CONFIG: dict[str, tuple] = {
- "apache-airflow": (_collect_core_metadata, "airflow_erd.svg"),
- "apache-airflow-providers-fab": (_collect_fab_metadata, "fab_erd.svg"),
- "apache-airflow-providers-edge3": (_collect_edge3_metadata,
"edge3_erd.svg"),
+ "apache-airflow": (_collect_core_metadata, "airflow_erd.mmd"),
+ "apache-airflow-providers-fab": (_collect_fab_metadata, "fab_erd.mmd"),
+ "apache-airflow-providers-edge3": (_collect_edge3_metadata,
"edge3_erd.mmd"),
}
def builder_inited(app):
- """Generate the ERD diagram SVG from SQLAlchemy metadata during doc
build."""
+ """Generate the ERD diagram Mermaid markup from SQLAlchemy metadata during
doc build."""
package_name = os.environ.get("AIRFLOW_PACKAGE_NAME", "")
config = _PACKAGE_ERD_CONFIG.get(package_name)
if config is None:
@@ -119,52 +112,35 @@ def builder_inited(app):
src_dir = app.srcdir
img_dir = os.path.join(src_dir, "img")
- svg_path = os.path.join(img_dir, filename)
+ mmd_path = os.path.join(img_dir, filename)
os.makedirs(img_dir, exist_ok=True)
try:
- from eralchemy import render_er
+ from eralchemy.main import _intermediary_to_mermaid_er,
all_to_intermediary, filter_resources
except ImportError:
log.warning("eralchemy is not installed, skipping ERD diagram
generation")
- _write_placeholder(svg_path)
+ _write_placeholder(mmd_path)
return
- # eralchemy needs either pygraphviz or graphviz Python package, and both
need
- # the graphviz system package (the ``dot`` binary) to render SVG output.
- if not shutil.which("dot"):
- hint = (
- "On macOS, install it with: brew install graphviz"
- if sys.platform == "darwin"
- else "Install graphviz via your system package manager."
- )
- log.warning(
- "graphviz system package is not installed — the 'dot' command is
not on PATH. "
- "Skipping ERD diagram generation. %s",
- hint,
- )
- _write_placeholder(svg_path)
- return
-
- log.info("Generating ERD diagram for %s at %s", package_name, svg_path)
+ log.info("Generating ERD diagram for %s at %s", package_name, mmd_path)
try:
metadata = collector()
except ImportError:
log.warning("Could not import models for %s, skipping ERD generation",
package_name)
- _write_placeholder(svg_path)
+ _write_placeholder(mmd_path)
return
- render_er(
- metadata,
- svg_path,
- exclude_tables=["sqlite_sequence"],
+ # Bypass eralchemy's `render_er`/`intermediary_to_mermaid_er`: those wrap
the markup in an
+ # HTML comment plus a `mermaid.ink` image link, meant for GitHub-flavored
markdown READMEs.
+ # The `.. mermaid::` Sphinx directive needs the raw `erDiagram ...` markup
instead.
+ tables, relationships = all_to_intermediary(metadata)
+ tables, relationships = filter_resources(
+ tables, relationships, exclude_tables=["sqlite_sequence"],
sort_mode="alphabetical"
)
-
- if not os.path.exists(svg_path):
- log.warning("ERD diagram was not generated (eralchemy/graphviz error),
writing placeholder")
- _write_placeholder(svg_path)
- return
+ markup = _intermediary_to_mermaid_er(tables, relationships)
+ Path(mmd_path).write_text(markup)
log.info("ERD diagram generated successfully")
diff --git a/providers/edge3/docs/database-erd-ref.rst
b/providers/edge3/docs/database-erd-ref.rst
index 1ad8f7ba51e..b5a62900a29 100644
--- a/providers/edge3/docs/database-erd-ref.rst
+++ b/providers/edge3/docs/database-erd-ref.rst
@@ -28,6 +28,6 @@ Here is the current database schema diagram for the Edge3
provider tables.
The main purpose of this diagram is to help with troubleshooting and
understanding of the
internal Edge3 DB architecture in case you have any problems with the
database.
-.. This image is automatically generated during documentation build by the
``generate_erd`` Sphinx extension.
+.. This diagram is automatically generated during documentation build by the
``generate_erd`` Sphinx extension.
-.. image:: img/edge3_erd.svg
+.. mermaid:: img/edge3_erd.mmd
diff --git a/providers/fab/docs/database-erd-ref.rst
b/providers/fab/docs/database-erd-ref.rst
index ee35757c58e..b3183cd203a 100644
--- a/providers/fab/docs/database-erd-ref.rst
+++ b/providers/fab/docs/database-erd-ref.rst
@@ -30,6 +30,6 @@ Here is the current database schema diagram for the FAB auth
manager provider ta
when dealing with problems with migrations. See also :doc:`migrations-ref`
for
list of detailed database migrations.
-.. This image is automatically generated during documentation build by the
``generate_erd`` Sphinx extension.
+.. This diagram is automatically generated during documentation build by the
``generate_erd`` Sphinx extension.
-.. image:: img/fab_erd.svg
+.. mermaid:: img/fab_erd.mmd