This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-1-test by this push:
     new 9392cc12866 Fix unauthenticated GitHub API calls in `breeze ci upgrade`
9392cc12866 is described below

commit 9392cc128669b1d68da872b8ca20f4ea7bbc2138
Author: Jarek Potiuk <[email protected]>
AuthorDate: Fri Mar 20 09:21:21 2026 +0100

    Fix unauthenticated GitHub API calls in `breeze ci upgrade`
    
    Two GitHub API calls in upgrade_important_versions.py (for fetching
    latest releases of mprocs and openapi-generator) were not using the
    GitHub token, hitting the 60 req/hr unauthenticated rate limit.
    
    Also adds --github-token option to `breeze ci upgrade` so the token
    can be passed explicitly instead of relying on `gh auth token`.
    
    (cherry picked from commit f8b049982b17554e5f4182c19f2782cf651d2836)
---
 dev/breeze/doc/images/output_ci_upgrade.svg        | 24 +++++++++--------
 dev/breeze/doc/images/output_ci_upgrade.txt        |  2 +-
 .../src/airflow_breeze/commands/ci_commands.py     | 30 +++++++++++++---------
 .../airflow_breeze/commands/ci_commands_config.py  |  1 +
 scripts/ci/prek/upgrade_important_versions.py      | 12 ++++++++-
 5 files changed, 45 insertions(+), 24 deletions(-)

diff --git a/dev/breeze/doc/images/output_ci_upgrade.svg 
b/dev/breeze/doc/images/output_ci_upgrade.svg
index 58a7b5bc225..59236bc0f97 100644
--- a/dev/breeze/doc/images/output_ci_upgrade.svg
+++ b/dev/breeze/doc/images/output_ci_upgrade.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 513.5999999999999" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 538.0" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -43,7 +43,7 @@
 
     <defs>
     <clipPath id="breeze-ci-upgrade-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="462.59999999999997" />
+      <rect x="0" y="0" width="1463.0" height="487.0" />
     </clipPath>
     <clipPath id="breeze-ci-upgrade-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -99,9 +99,12 @@
 <clipPath id="breeze-ci-upgrade-line-17">
     <rect x="0" y="416.3" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-ci-upgrade-line-18">
+    <rect x="0" y="440.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="511.6" rx="8"/><text 
class="breeze-ci-upgrade-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;ci&#160;upgrade</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="536" rx="8"/><text 
class="breeze-ci-upgrade-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;ci&#160;upgrade</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -123,13 +126,14 @@
 </text><text class="breeze-ci-upgrade-r5" x="0" y="239.6" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-9)">│</text><text 
class="breeze-ci-upgrade-r1" x="512.4" y="239.6" textLength="927.2" 
clip-path="url(#breeze-ci-upgrade-line-9)">ask)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-ci-upgrade-r5" x="0" y="264" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-10)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="264" textLength="195.2" 
clip-path="url(#breeze-ci-upgrade-line-10)">--switch-to-base</text><text 
class="breeze-ci-upgrade-r1" x="219.6" y="264" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-10)">/</text><text 
class="breeze-ci-upgrade-r4" x="231.8" y="264" textLength="231.8" 
clip-path="url(#breeze-ci-upgrade [...]
 </text><text class="breeze-ci-upgrade-r5" x="0" y="288.4" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-11)">│</text><text 
class="breeze-ci-upgrade-r1" x="512.4" y="288.4" textLength="927.2" 
clip-path="url(#breeze-ci-upgrade-line-11)">specified,&#160;will&#160;ask)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-ci-upgrade-r5" x="0" y="312.8" textLength="1464" 
clip-path="url(#breeze-ci-upgrade-line-12)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-ci-upgrade-r1" x="1464" y="312.8" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-12)">
-</text><text class="breeze-ci-upgrade-r5" x="0" y="337.2" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-13)">╭─</text><text 
class="breeze-ci-upgrade-r5" x="24.4" y="337.2" textLength="195.2" 
clip-path="url(#breeze-ci-upgrade-line-13)">&#160;Common&#160;options&#160;</text><text
 class="breeze-ci-upgrade-r5" x="219.6" y="337.2" textLength="1220" 
clip-path="url(#breeze-ci-upgrade-line-13)">───────────────────────────────────────────────────────────────────────────────────────────
 [...]
-</text><text class="breeze-ci-upgrade-r5" x="0" y="361.6" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-14)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="361.6" textLength="97.6" 
clip-path="url(#breeze-ci-upgrade-line-14)">--answer</text><text 
class="breeze-ci-upgrade-r7" x="158.6" y="361.6" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-14)">-a</text><text 
class="breeze-ci-upgrade-r1" x="207.4" y="361.6" textLength="317.2" 
clip-path="url(#breeze-ci-upgrade [...]
-</text><text class="breeze-ci-upgrade-r5" x="0" y="386" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-15)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="386" textLength="109.8" 
clip-path="url(#breeze-ci-upgrade-line-15)">--verbose</text><text 
class="breeze-ci-upgrade-r7" x="158.6" y="386" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-15)">-v</text><text 
class="breeze-ci-upgrade-r1" x="207.4" y="386" textLength="585.6" 
clip-path="url(#breeze-ci-upgrade-line- [...]
-</text><text class="breeze-ci-upgrade-r5" x="0" y="410.4" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-16)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="410.4" textLength="109.8" 
clip-path="url(#breeze-ci-upgrade-line-16)">--dry-run</text><text 
class="breeze-ci-upgrade-r7" x="158.6" y="410.4" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-16)">-D</text><text 
class="breeze-ci-upgrade-r1" x="207.4" y="410.4" textLength="719.8" 
clip-path="url(#breeze-ci-upgra [...]
-</text><text class="breeze-ci-upgrade-r5" x="0" y="434.8" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-17)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="434.8" textLength="73.2" 
clip-path="url(#breeze-ci-upgrade-line-17)">--help</text><text 
class="breeze-ci-upgrade-r7" x="158.6" y="434.8" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-17)">-h</text><text 
class="breeze-ci-upgrade-r1" x="207.4" y="434.8" textLength="329.4" 
clip-path="url(#breeze-ci-upgrade-l [...]
-</text><text class="breeze-ci-upgrade-r5" x="0" y="459.2" textLength="1464" 
clip-path="url(#breeze-ci-upgrade-line-18)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-ci-upgrade-r1" x="1464" y="459.2" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-18)">
+</text><text class="breeze-ci-upgrade-r5" x="0" y="312.8" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-12)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="312.8" textLength="170.8" 
clip-path="url(#breeze-ci-upgrade-line-12)">--github-token</text><text 
class="breeze-ci-upgrade-r1" x="512.4" y="312.8" textLength="500.2" 
clip-path="url(#breeze-ci-upgrade-line-12)">The&#160;token&#160;used&#160;to&#160;authenticate&#160;to&#160;GitHub.</text><text
 class="breeze-ci-upgrade [...]
+</text><text class="breeze-ci-upgrade-r5" x="0" y="337.2" textLength="1464" 
clip-path="url(#breeze-ci-upgrade-line-13)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-ci-upgrade-r1" x="1464" y="337.2" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-13)">
+</text><text class="breeze-ci-upgrade-r5" x="0" y="361.6" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-14)">╭─</text><text 
class="breeze-ci-upgrade-r5" x="24.4" y="361.6" textLength="195.2" 
clip-path="url(#breeze-ci-upgrade-line-14)">&#160;Common&#160;options&#160;</text><text
 class="breeze-ci-upgrade-r5" x="219.6" y="361.6" textLength="1220" 
clip-path="url(#breeze-ci-upgrade-line-14)">───────────────────────────────────────────────────────────────────────────────────────────
 [...]
+</text><text class="breeze-ci-upgrade-r5" x="0" y="386" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-15)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="386" textLength="97.6" 
clip-path="url(#breeze-ci-upgrade-line-15)">--answer</text><text 
class="breeze-ci-upgrade-r7" x="158.6" y="386" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-15)">-a</text><text 
class="breeze-ci-upgrade-r1" x="207.4" y="386" textLength="317.2" 
clip-path="url(#breeze-ci-upgrade-line-15 [...]
+</text><text class="breeze-ci-upgrade-r5" x="0" y="410.4" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-16)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="410.4" textLength="109.8" 
clip-path="url(#breeze-ci-upgrade-line-16)">--verbose</text><text 
class="breeze-ci-upgrade-r7" x="158.6" y="410.4" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-16)">-v</text><text 
class="breeze-ci-upgrade-r1" x="207.4" y="410.4" textLength="585.6" 
clip-path="url(#breeze-ci-upgra [...]
+</text><text class="breeze-ci-upgrade-r5" x="0" y="434.8" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-17)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="434.8" textLength="109.8" 
clip-path="url(#breeze-ci-upgrade-line-17)">--dry-run</text><text 
class="breeze-ci-upgrade-r7" x="158.6" y="434.8" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-17)">-D</text><text 
class="breeze-ci-upgrade-r1" x="207.4" y="434.8" textLength="719.8" 
clip-path="url(#breeze-ci-upgra [...]
+</text><text class="breeze-ci-upgrade-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-18)">│</text><text 
class="breeze-ci-upgrade-r4" x="24.4" y="459.2" textLength="73.2" 
clip-path="url(#breeze-ci-upgrade-line-18)">--help</text><text 
class="breeze-ci-upgrade-r7" x="158.6" y="459.2" textLength="24.4" 
clip-path="url(#breeze-ci-upgrade-line-18)">-h</text><text 
class="breeze-ci-upgrade-r1" x="207.4" y="459.2" textLength="329.4" 
clip-path="url(#breeze-ci-upgrade-l [...]
+</text><text class="breeze-ci-upgrade-r5" x="0" y="483.6" textLength="1464" 
clip-path="url(#breeze-ci-upgrade-line-19)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-ci-upgrade-r1" x="1464" y="483.6" textLength="12.2" 
clip-path="url(#breeze-ci-upgrade-line-19)">
 </text>
     </g>
     </g>
diff --git a/dev/breeze/doc/images/output_ci_upgrade.txt 
b/dev/breeze/doc/images/output_ci_upgrade.txt
index 2fb1cda8a68..5f05a990319 100644
--- a/dev/breeze/doc/images/output_ci_upgrade.txt
+++ b/dev/breeze/doc/images/output_ci_upgrade.txt
@@ -1 +1 @@
-098262cac189629f9ba74c4517b0b853
+e81724124d51a5dfddc0f2732e65a609
diff --git a/dev/breeze/src/airflow_breeze/commands/ci_commands.py 
b/dev/breeze/src/airflow_breeze/commands/ci_commands.py
index f9f65965c59..75d48cba1f4 100644
--- a/dev/breeze/src/airflow_breeze/commands/ci_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/ci_commands.py
@@ -37,6 +37,7 @@ from airflow_breeze.commands.common_options import (
     option_answer,
     option_dry_run,
     option_github_repository,
+    option_github_token,
     option_verbose,
 )
 from airflow_breeze.global_constants import (
@@ -450,7 +451,10 @@ def get_workflow_info(github_context: str, 
github_context_input: StringIO):
 @option_answer
 @option_verbose
 @option_dry_run
-def upgrade(target_branch: str, create_pr: bool | None, switch_to_base: bool | 
None):
+@option_github_token
+def upgrade(
+    target_branch: str, create_pr: bool | None, switch_to_base: bool | None, 
github_token: str | None
+):
     # Validate target_branch pattern
     target_branch_pattern = re.compile(r"^(main|v\d+-\d+-test)$")
     if not target_branch_pattern.match(target_branch):
@@ -606,24 +610,26 @@ def upgrade(target_branch: str, create_pr: bool | None, 
switch_to_base: bool | N
 
     get_console().print("[info]Running upgrade of important CI 
environment.[/]")
 
-    # Get GitHub token from gh CLI and set it in environment copy
-    gh_token_result = run_command(
-        ["gh", "auth", "token"],
-        capture_output=True,
-        text=True,
-        check=False,
-    )
+    # Resolve GitHub token: prefer --github-token / GITHUB_TOKEN env var, fall 
back to gh CLI
+    if not github_token:
+        gh_token_result = run_command(
+            ["gh", "auth", "token"],
+            capture_output=True,
+            text=True,
+            check=False,
+        )
+        if gh_token_result.returncode == 0 and gh_token_result.stdout.strip():
+            github_token = gh_token_result.stdout.strip()
 
     # Create a copy of the environment to pass to commands
     command_env = os.environ.copy()
 
-    if gh_token_result.returncode == 0 and gh_token_result.stdout.strip():
-        github_token = gh_token_result.stdout.strip()
+    if github_token:
         command_env["GITHUB_TOKEN"] = github_token
-        get_console().print("[success]GitHub token retrieved from gh CLI and 
set in environment.[/]")
+        get_console().print("[success]GitHub token set in environment.[/]")
     else:
         get_console().print(
-            "[warning]Could not retrieve GitHub token from gh CLI. "
+            "[warning]Could not retrieve GitHub token from --github-token or 
gh CLI. "
             "Commands may fail if they require authentication.[/]"
         )
 
diff --git a/dev/breeze/src/airflow_breeze/commands/ci_commands_config.py 
b/dev/breeze/src/airflow_breeze/commands/ci_commands_config.py
index 9f822c4365d..35cc09a465a 100644
--- a/dev/breeze/src/airflow_breeze/commands/ci_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/ci_commands_config.py
@@ -74,6 +74,7 @@ CI_PARAMETERS: dict[str, list[dict[str, str | list[str]]]] = {
                 "--target-branch",
                 "--create-pr",
                 "--switch-to-base",
+                "--github-token",
             ],
         }
     ],
diff --git a/scripts/ci/prek/upgrade_important_versions.py 
b/scripts/ci/prek/upgrade_important_versions.py
index 5b5d23b40b8..e435e29a049 100755
--- a/scripts/ci/prek/upgrade_important_versions.py
+++ b/scripts/ci/prek/upgrade_important_versions.py
@@ -48,6 +48,9 @@ from common_prek_utils import AIRFLOW_CORE_ROOT_PATH, 
AIRFLOW_ROOT_PATH, console
 
 DOCKER_IMAGES_EXAMPLE_DIR_PATH = AIRFLOW_ROOT_PATH / "docker-stack-docs" / 
"docker-examples"
 
+# Module-level GitHub token, set during main() via retrieve_gh_token()
+_github_token: str | None = None
+
 
 # List of files to update and whether to keep total length of the original 
value when replacing.
 FILES_TO_UPDATE: list[tuple[Path, bool]] = [
@@ -270,6 +273,9 @@ def get_latest_github_release_version(repo: str) -> str:
 
     url = f"https://api.github.com/repos/{repo}/releases/latest";
     headers = {"User-Agent": "Python requests"}
+    if _github_token:
+        headers["Authorization"] = f"Bearer {_github_token}"
+        headers["X-GitHub-Api-Version"] = "2022-11-28"
     response = requests.get(url, headers=headers)
     response.raise_for_status()
 
@@ -296,6 +302,9 @@ def get_latest_openapi_generator_version() -> str:
         console.print("[bright_blue]Fetching latest OpenAPI generator version 
from GitHub")
     url = 
"https://api.github.com/repos/OpenAPITools/openapi-generator/releases/latest";
     headers = {"User-Agent": "Python requests"}
+    if _github_token:
+        headers["Authorization"] = f"Bearer {_github_token}"
+        headers["X-GitHub-Api-Version"] = "2022-11-28"
     response = requests.get(url, headers=headers)
     response.raise_for_status()
     data = response.json()
@@ -833,7 +842,8 @@ def update_pyproject_build_requires(
 
 def main() -> None:
     """Main entry point for the version upgrade script."""
-    retrieve_gh_token(description="airflow-upgrade-important-versions", 
scopes="public_repo")
+    global _github_token
+    _github_token = 
retrieve_gh_token(description="airflow-upgrade-important-versions", 
scopes="public_repo")
 
     versions = fetch_all_package_versions()
     log_special_versions(versions)

Reply via email to