This is an automated email from the ASF dual-hosted git repository.
potiuk 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 9b3ed326f1c Add cooldown parameter to constraints-version-check
command (#64844)
9b3ed326f1c is described below
commit 9b3ed326f1ca46ed8d835342e8d9a2f41f188c13
Author: Jarek Potiuk <[email protected]>
AuthorDate: Tue Apr 7 17:35:19 2026 +0200
Add cooldown parameter to constraints-version-check command (#64844)
When checking for latest package versions, very recent releases may
not yet be stable or widely mirrored. This adds a --cooldown-days
parameter (default: 4 days) that excludes package versions released
within the cooldown period when determining the "latest" version.
---
...elease-management_constraints-version-check.svg | 32 ++++++++++------
...elease-management_constraints-version-check.txt | 2 +-
.../commands/release_management_commands.py | 9 +++++
.../commands/release_management_commands_config.py | 1 +
.../utils/constraints_version_check.py | 43 ++++++++++++++++++++--
5 files changed, 71 insertions(+), 16 deletions(-)
diff --git
a/dev/breeze/doc/images/output_release-management_constraints-version-check.svg
b/dev/breeze/doc/images/output_release-management_constraints-version-check.svg
index df0f1265600..5bc64a75459 100644
---
a/dev/breeze/doc/images/output_release-management_constraints-version-check.svg
+++
b/dev/breeze/doc/images/output_release-management_constraints-version-check.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 733.1999999999999"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 782.0"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -43,7 +43,7 @@
<defs>
<clipPath
id="breeze-release-management-constraints-version-check-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="682.1999999999999" />
+ <rect x="0" y="0" width="1463.0" height="731.0" />
</clipPath>
<clipPath id="breeze-release-management-constraints-version-check-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -126,9 +126,15 @@
<clipPath id="breeze-release-management-constraints-version-check-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-release-management-constraints-version-check-line-27">
+ <rect x="0" y="660.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-constraints-version-check-line-28">
+ <rect x="0" y="684.7" width="1464" height="24.65"/>
+ </clipPath>
</defs>
- <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="731.2" rx="8"/><text
class="breeze-release-management-constraints-version-check-title"
fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Command: release-management constraints-version-check</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="780" rx="8"/><text
class="breeze-release-management-constraints-version-check-title"
fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Command: release-management constraints-version-check</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -157,15 +163,17 @@
</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="410.4" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-16)">│</text><text
class="breeze-release-management-constraints-version-check-r7" x="414.8"
y="410.4" textLength="390.4"
clip-path="url(#breeze-release-management-constraints-version-check-line-16)">(full|diff-all|diff-constraints)</text><text
class="breeze-release-management-constraints-version-check-r5" x= [...]
</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="434.8" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-17)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="434.8" textLength="366"
clip-path="url(#breeze-release-management-constraints-version-check-line-17)">--package                 &#
[...]
</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="459.2" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-18)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="459.2" textLength="158.6"
clip-path="url(#breeze-release-management-constraints-version-check-line-18)">--explain-why</text><text
class="breeze-release-management-constraints-version-check-r1" x="183"
y="459.2" text [...]
-</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="483.6" textLength="1464"
clip-path="url(#breeze-release-management-constraints-version-check-line-19)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-constraints-version-check-r1" x="1464"
y="483.6" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-19)">
-</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="508" textLength="24.4"
clip-path="url(#breeze-release-management-constraints-version-check-line-20)">╭─</text><text
class="breeze-release-management-constraints-version-check-r5" x="24.4"
y="508" textLength="195.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-20)"> Build options. </text><text
class="breeze-release-management-constraints-version-check-r5" x="219. [...]
-</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="532.4" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-21)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="532.4" textLength="109.8"
clip-path="url(#breeze-release-management-constraints-version-check-line-21)">--builder</text><text
class="breeze-release-management-constraints-version-check-r1" x="158.6"
y="532.4" textLe [...]
-</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="556.8" textLength="1464"
clip-path="url(#breeze-release-management-constraints-version-check-line-22)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-constraints-version-check-r1" x="1464"
y="556.8" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-22)">
-</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="581.2" textLength="24.4"
clip-path="url(#breeze-release-management-constraints-version-check-line-23)">╭─</text><text
class="breeze-release-management-constraints-version-check-r5" x="24.4"
y="581.2" textLength="195.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-23)"> Common options </text><text
class="breeze-release-management-constraints-version-check-r5" x=" [...]
-</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="605.6" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-24)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="605.6" textLength="109.8"
clip-path="url(#breeze-release-management-constraints-version-check-line-24)">--verbose</text><text
class="breeze-release-management-constraints-version-check-r6" x="158.6"
y="605.6" textLe [...]
-</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="630" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-25)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="630" textLength="109.8"
clip-path="url(#breeze-release-management-constraints-version-check-line-25)">--dry-run</text><text
class="breeze-release-management-constraints-version-check-r6" x="158.6"
y="630" textLength=" [...]
-</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="654.4" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-26)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="654.4" textLength="109.8"
clip-path="url(#breeze-release-management-constraints-version-check-line-26)">--help   </text><text
class="breeze-release-management-constraints-version-check-r6" x="158.6" y
[...]
-</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="678.8" textLength="1464"
clip-path="url(#breeze-release-management-constraints-version-check-line-27)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-constraints-version-check-r1" x="1464"
y="678.8" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-27)">
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="483.6" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-19)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="483.6" textLength="366"
clip-path="url(#breeze-release-management-constraints-version-check-line-19)">--cooldown-days               </text><
[...]
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="508" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-20)">│</text><text
class="breeze-release-management-constraints-version-check-r5" x="414.8"
y="508" textLength="24.4"
clip-path="url(#breeze-release-management-constraints-version-check-line-20)">4]</text><text
class="breeze-release-management-constraints-version-check-r7" x="451.4"
y="508" textLength="109.8" [...]
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="532.4" textLength="1464"
clip-path="url(#breeze-release-management-constraints-version-check-line-21)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-constraints-version-check-r1" x="1464"
y="532.4" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-21)">
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="556.8" textLength="24.4"
clip-path="url(#breeze-release-management-constraints-version-check-line-22)">╭─</text><text
class="breeze-release-management-constraints-version-check-r5" x="24.4"
y="556.8" textLength="195.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-22)"> Build options. </text><text
class="breeze-release-management-constraints-version-check-r5" x=" [...]
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="581.2" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-23)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="581.2" textLength="109.8"
clip-path="url(#breeze-release-management-constraints-version-check-line-23)">--builder</text><text
class="breeze-release-management-constraints-version-check-r1" x="158.6"
y="581.2" textLe [...]
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="605.6" textLength="1464"
clip-path="url(#breeze-release-management-constraints-version-check-line-24)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-constraints-version-check-r1" x="1464"
y="605.6" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-24)">
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="630" textLength="24.4"
clip-path="url(#breeze-release-management-constraints-version-check-line-25)">╭─</text><text
class="breeze-release-management-constraints-version-check-r5" x="24.4"
y="630" textLength="195.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-25)"> Common options </text><text
class="breeze-release-management-constraints-version-check-r5" x="219. [...]
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="654.4" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-26)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="654.4" textLength="109.8"
clip-path="url(#breeze-release-management-constraints-version-check-line-26)">--verbose</text><text
class="breeze-release-management-constraints-version-check-r6" x="158.6"
y="654.4" textLe [...]
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="678.8" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-27)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="678.8" textLength="109.8"
clip-path="url(#breeze-release-management-constraints-version-check-line-27)">--dry-run</text><text
class="breeze-release-management-constraints-version-check-r6" x="158.6"
y="678.8" textLe [...]
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="703.2" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-28)">│</text><text
class="breeze-release-management-constraints-version-check-r4" x="24.4"
y="703.2" textLength="109.8"
clip-path="url(#breeze-release-management-constraints-version-check-line-28)">--help   </text><text
class="breeze-release-management-constraints-version-check-r6" x="158.6" y
[...]
+</text><text class="breeze-release-management-constraints-version-check-r5"
x="0" y="727.6" textLength="1464"
clip-path="url(#breeze-release-management-constraints-version-check-line-29)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-constraints-version-check-r1" x="1464"
y="727.6" textLength="12.2"
clip-path="url(#breeze-release-management-constraints-version-check-line-29)">
</text>
</g>
</g>
diff --git
a/dev/breeze/doc/images/output_release-management_constraints-version-check.txt
b/dev/breeze/doc/images/output_release-management_constraints-version-check.txt
index 5f4e9134458..5f03ceac2f5 100644
---
a/dev/breeze/doc/images/output_release-management_constraints-version-check.txt
+++
b/dev/breeze/doc/images/output_release-management_constraints-version-check.txt
@@ -1 +1 @@
-69595e717626710cce603db050e76a21
+9997441e5cb12ba360db1756028718d3
diff --git
a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
index 893f4167ebb..ca24ba0daf3 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
@@ -4253,6 +4253,13 @@ def publish_docs_to_s3(
default=False,
help="Show explanations for outdated packages.",
)
[email protected](
+ "--cooldown-days",
+ type=int,
+ default=4,
+ show_default=True,
+ help="Ignore package versions released within this many days (cooldown
period).",
+)
@option_github_token
@option_github_repository
@option_verbose
@@ -4263,6 +4270,7 @@ def version_check(
diff_mode,
package: tuple[str],
explain_why: bool,
+ cooldown_days: int,
github_token: str,
github_repository: str,
builder: str,
@@ -4288,6 +4296,7 @@ def version_check(
explain_why=explain_why,
github_token=github_token,
github_repository=github_repository,
+ cooldown_days=cooldown_days,
)
diff --git
a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
index e6a1fbfa9bf..6381bdadb31 100644
---
a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
+++
b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
@@ -515,6 +515,7 @@ RELEASE_MANAGEMENT_PARAMETERS: dict[str, list[dict[str, str
| list[str]]]] = {
"--diff-mode",
"--package",
"--explain-why",
+ "--cooldown-days",
],
},
{
diff --git a/dev/breeze/src/airflow_breeze/utils/constraints_version_check.py
b/dev/breeze/src/airflow_breeze/utils/constraints_version_check.py
index aea56854f85..9114b2d1089 100755
--- a/dev/breeze/src/airflow_breeze/utils/constraints_version_check.py
+++ b/dev/breeze/src/airflow_breeze/utils/constraints_version_check.py
@@ -24,7 +24,7 @@ import sys
import tempfile
import urllib.request
from contextlib import contextmanager
-from datetime import datetime
+from datetime import datetime, timedelta
from pathlib import Path
from typing import TYPE_CHECKING, Any
from urllib.error import HTTPError, URLError
@@ -168,6 +168,38 @@ def should_show_package(releases, latest_version,
constraints_date, mode, is_lat
return True
+def get_latest_version_with_cooldown(releases: dict[str, Any], cooldown_days:
int) -> str | None:
+ """Find the latest non-prerelease version whose release date is outside
the cooldown period.
+
+ Returns the version string, or None if no version qualifies.
+ """
+ from packaging import version
+
+ cutoff = datetime.now() - timedelta(days=cooldown_days)
+ candidates: list[tuple[version.Version, str]] = []
+ for v, release_files in releases.items():
+ if not release_files:
+ continue
+ try:
+ parsed_v = version.parse(v)
+ except version.InvalidVersion:
+ continue
+ if parsed_v.is_prerelease or parsed_v.is_devrelease:
+ continue
+ try:
+ upload_time = datetime.fromisoformat(
+ release_files[0]["upload_time_iso_8601"].replace("Z", "+00:00")
+ ).replace(tzinfo=None)
+ except (KeyError, IndexError, ValueError):
+ continue
+ if upload_time <= cutoff:
+ candidates.append((parsed_v, v))
+ if not candidates:
+ return None
+ candidates.sort(key=lambda x: x[0], reverse=True)
+ return candidates[0][1]
+
+
def get_first_newer_release_date_str(releases, current_version):
from packaging import version
@@ -210,9 +242,11 @@ def constraints_version_check(
explain_why: bool = False,
github_token: str | None = None,
github_repository: str | None = None,
+ cooldown_days: int = 4,
):
console_print(f"[bold cyan]Python version:[/] [white]{python}[/]")
- console_print(f"[bold cyan]Constraints mode:[/]
[white]{airflow_constraints_mode}[/]\n")
+ console_print(f"[bold cyan]Constraints mode:[/]
[white]{airflow_constraints_mode}[/]")
+ console_print(f"[bold cyan]Cooldown period:[/] [white]{cooldown_days}
days[/]\n")
with tempfile.TemporaryDirectory() as temp_dir:
constraints_file = Path(temp_dir) / "constraints.txt"
download_constraints_file(
@@ -248,6 +282,7 @@ def constraints_version_check(
python_version=python,
airflow_constraints_mode=airflow_constraints_mode,
github_repository=github_repository,
+ cooldown_days=cooldown_days,
)
print_table_footer(
@@ -386,6 +421,7 @@ def process_packages(
python_version: str,
airflow_constraints_mode: str,
github_repository: str | None,
+ cooldown_days: int = 4,
) -> tuple[int, int, list[str], dict[str, int]]:
@contextmanager
def preserve_pyproject_file(pyproject_path: Path):
@@ -417,8 +453,9 @@ def process_packages(
for pkg, pinned_version in packages:
try:
data = fetch_pypi_data(pkg)
- latest_version = data["info"]["version"]
releases = data["releases"]
+ latest_version_with_cooldown =
get_latest_version_with_cooldown(releases, cooldown_days)
+ latest_version = latest_version_with_cooldown or
data["info"]["version"]
latest_release_date = get_release_dates(releases, latest_version)
constraint_release_date = get_release_dates(releases,
pinned_version)
is_latest_version = pinned_version == latest_version