This is an automated email from the ASF dual-hosted git repository.
gopidesu 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 67596f9432e Add release date to provider docs (#50622)
67596f9432e is described below
commit 67596f9432ecebf19710b8a72b67e1e76e8cd8be
Author: GPK <[email protected]>
AuthorDate: Sat Jul 26 00:01:54 2025 +0100
Add release date to provider docs (#50622)
* Add release date to providers index
* Add release date to providers index
* Use release version to find release date
* Update review suggestions
---
.../templates/PROVIDER_INDEX_TEMPLATE.rst.jinja2 | 2 +
.../templates/PROVIDER_README_TEMPLATE.rst.jinja2 | 1 +
.../extra_provider_files_with_substitutions.py | 50 +++++++++++++++++++++-
3 files changed, 52 insertions(+), 1 deletion(-)
diff --git
a/dev/breeze/src/airflow_breeze/templates/PROVIDER_INDEX_TEMPLATE.rst.jinja2
b/dev/breeze/src/airflow_breeze/templates/PROVIDER_INDEX_TEMPLATE.rst.jinja2
index fb857bbe6ae..9670dfa98d5 100644
--- a/dev/breeze/src/airflow_breeze/templates/PROVIDER_INDEX_TEMPLATE.rst.jinja2
+++ b/dev/breeze/src/airflow_breeze/templates/PROVIDER_INDEX_TEMPLATE.rst.jinja2
@@ -36,6 +36,8 @@
Release: {{ RELEASE }}{{ VERSION_SUFFIX }}
+Release Date: `|PypiReleaseDate|`
+
Provider package
----------------
diff --git
a/dev/breeze/src/airflow_breeze/templates/PROVIDER_README_TEMPLATE.rst.jinja2
b/dev/breeze/src/airflow_breeze/templates/PROVIDER_README_TEMPLATE.rst.jinja2
index ab3210d866b..9392a0247ea 100644
---
a/dev/breeze/src/airflow_breeze/templates/PROVIDER_README_TEMPLATE.rst.jinja2
+++
b/dev/breeze/src/airflow_breeze/templates/PROVIDER_README_TEMPLATE.rst.jinja2
@@ -43,6 +43,7 @@ Package ``{{ PACKAGE_PIP_NAME }}``
Release: ``{{ RELEASE }}{{ VERSION_SUFFIX }}``
+Release Date: `|PypiReleaseDate|`
{{ PROVIDER_DESCRIPTION | safe }}
diff --git
a/devel-common/src/sphinx_exts/extra_provider_files_with_substitutions.py
b/devel-common/src/sphinx_exts/extra_provider_files_with_substitutions.py
index 065ba6a27bd..6526b1e3bef 100644
--- a/devel-common/src/sphinx_exts/extra_provider_files_with_substitutions.py
+++ b/devel-common/src/sphinx_exts/extra_provider_files_with_substitutions.py
@@ -16,8 +16,51 @@
# under the License.
from __future__ import annotations
+import os
+from datetime import datetime
from pathlib import Path
+from packaging.version import Version
+
+
+def _get_rc_matching_version(releases: dict, version: str):
+ """
+ Get the latest release candidate version matching the given version.
+ """
+
+ matching_versions = (v for v in releases.keys() if Version(v).base_version
== version)
+ latest_version = max(matching_versions, key=Version, default=None)
+
+ return releases.get(latest_version, []) if latest_version else []
+
+
+def get_release_date(package_name: str, version) -> str:
+ """Get the release date of the current version."""
+ if package_name == "":
+ return ""
+ import requests
+
+ resp = requests.get(f"https://pypi.org/pypi/{package_name}/json")
+ resp_json = resp.json()
+ releases = resp_json.get("releases", {})
+ release_info = releases.get(version, [])
+
+ # If no exact version found, try to find the latest release candidate
version
+ if not release_info and len(releases) > 0:
+ release_info = _get_rc_matching_version(releases, version)
+
+ if release_info:
+ release_date =
datetime.fromisoformat(release_info[0].get("upload_time")).date()
+ return str(release_date)
+
+ return "Release date unknown"
+
+
+def _manual_substitution(line: str, replacements: dict[str, str]) -> str:
+ for value, repl in replacements.items():
+ line = line.replace(value, repl)
+ return line
+
def fix_provider_references(app, exception):
"""Sphinx "build-finished" event handler."""
@@ -26,13 +69,18 @@ def fix_provider_references(app, exception):
if exception or not isinstance(app.builder,
builders.StandaloneHTMLBuilder):
return
+ substitutions = {
+ "|version|": app.config.version,
+ "|PypiReleaseDate|":
get_release_date(os.environ.get("AIRFLOW_PACKAGE_NAME", ""),
app.config.version),
+ }
+
# Replace `|version|` in the files that require manual substitution
for path in Path(app.outdir).rglob("*.html"):
if path.exists():
lines = path.read_text().splitlines(True)
with path.open("w") as output_file:
for line in lines:
- output_file.write(line.replace("|version|",
app.config.version))
+ output_file.write(_manual_substitution(line,
substitutions))
def setup(app):