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

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

commit caa07e2c12aee501639e44d2525542778973e865
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sun Sep 14 16:20:58 2025 +0000

    Separate GoLang precommit after prek supports monorepo setup (#54615)
    
    Prek 0.2.0 supports monorepo setup wieth separate pre-commit files
    and as the first step of separation we separate golang pre-commits.
    
    (cherry picked from commit d8e2c8559282508435647999fccd58c22c9108d9)
---
 .github/actions/install-prek/action.yml       |   2 +-
 .github/workflows/ci-amd.yml                  |   2 +-
 .pre-commit-config.yaml                       |  45 +----
 contributing-docs/08_static_code_checks.rst   |   4 +-
 {.github => dev}/.pre-commit-config.yaml      |   0
 go-sdk/.pre-commit-config.yaml                |  73 +++++++
 scripts/ci/prek/upgrade_important_versions.py | 262 +++++++++++++++-----------
 7 files changed, 235 insertions(+), 153 deletions(-)

diff --git a/.github/actions/install-prek/action.yml 
b/.github/actions/install-prek/action.yml
index cacd19f9639..9289c000aaa 100644
--- a/.github/actions/install-prek/action.yml
+++ b/.github/actions/install-prek/action.yml
@@ -64,7 +64,7 @@ runs:
       uses: 
apache/infrastructure-actions/stash/restore@1c35b5ccf8fba5d4c3fdf25a045ca91aa0cbc468
       with:
         # yamllint disable rule:line-length
-        key: cache-prek-v6-${{ inputs.platform }}-${{ inputs.python-version 
}}-${{inputs.skip-prek-hooks}}-${{ hashFiles('.pre-commit-config.yaml') }}
+        key: cache-prek-v6-${{ inputs.platform }}-${{ inputs.python-version 
}}-${{inputs.skip-prek-hooks}}-${{ hashFiles('**/.pre-commit-config.yaml') }}
         path: /tmp/
       id: restore-prek-cache
     - name: "Check if prek cache tarball exists"
diff --git a/.github/workflows/ci-amd.yml b/.github/workflows/ci-amd.yml
index e65bc71e0fc..e7bd7010858 100644
--- a/.github/workflows/ci-amd.yml
+++ b/.github/workflows/ci-amd.yml
@@ -193,7 +193,7 @@ jobs:
           skip-prek-hooks: ""
       - name: "Run pin-versions"
         run: >
-          prek -c .github/.pre-commit-config.yaml --all-files --verbose 
--hook-stage manual
+          prek -c dev/.pre-commit-config.yaml --all-files --verbose 
--hook-stage manual
           pin-versions
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 93a75476896..4f008939a76 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -19,8 +19,7 @@ default_stages: [pre-commit, pre-push]
 default_language_version:
   python: python3
   node: 22.19.0
-  golang: 1.24.0
-minimum_prek_version: '0.1.3'
+minimum_prek_version: '0.2.0'
 exclude: ^.*/.*_vendor/
 repos:
   - repo: meta
@@ -172,18 +171,6 @@ repos:
           - --fuzzy-match-generates-todo
         files: >
           
\.cfg$|\.conf$|\.ini$|\.ldif$|\.properties$|\.service$|\.tf$|Dockerfile.*$
-      - id: insert-license
-        name: Add license for all Go files
-        types: [go]
-        exclude: mocks/.*\.go$
-        args:
-          - --comment-style
-          - "|//|"
-          - --license-filepath
-          - scripts/ci/license-templates/LICENSE.txt
-          - --insert-license-after-regex
-          # We need this 'generated by' line at the top for `golines` to not 
format it
-          - '// Code generated by .*'
   - repo: local
     hooks:
       - id: check-min-python-version
@@ -1303,36 +1290,6 @@ repos:
         files: ^airflow-core/src/airflow/migrations/versions/.*\.py$
         exclude:
           
^airflow-core/src/airflow/migrations/versions/0028_3_0_0_drop_ab_user_id_foreign_key.py$
-      - id: go-mockery
-        name: Generate mocks for go
-        entry: -w /src/go-sdk vektra/mockery:3
-        files: ^go-sdk/
-        exclude: mocks/.*\.go$
-        types: [go]
-        pass_filenames: false
-        language: docker_image
-      - id: go-mod-tidy
-        name: Run go mod tidy
-        entry: bash -c "cd go-sdk && go mod tidy"
-        files: ^go-sdk/
-        exclude: mocks/.*\.go$
-        pass_filenames: false
-        language: system
-      - id: gofmt
-        name: Format go code
-        entry: golines --base-formatter=gofumpt --write-output --max-len=100 
--chain-split-dots
-        additional_dependencies: [github.com/segmentio/golines@latest, 
mvdan.cc/[email protected]]
-        files: ^go-sdk/
-        types: [go]
-        language: golang
-      - id: gci
-        name: Consistent import ordering for Go files
-        # Since this is invoked from the root folder, not go-sdk/, gci can't 
auto-detect the prefix
-        entry: gci write --skip-generated -s standard -s default -s 
"prefix(github.com/apache/airflow)"
-        additional_dependencies: [github.com/daixiang0/[email protected]]
-        files: ^go-sdk/
-        types: [go]
-        language: golang
       - id: ts-compile-lint-ui
         name: Compile / format / lint UI
         description: TS types generation / ESLint / Prettier new UI files
diff --git a/contributing-docs/08_static_code_checks.rst 
b/contributing-docs/08_static_code_checks.rst
index 5e910a31a6b..297b2492830 100644
--- a/contributing-docs/08_static_code_checks.rst
+++ b/contributing-docs/08_static_code_checks.rst
@@ -275,14 +275,14 @@ GitHub Actions in the CI workflows.
 
 This action requires ``GITHUB_TOKEN`` to be set, otherwise you might hit the 
rate limits with GitHub API, it
 is also configured in a separate ``.prek-config.yaml`` file in the
-``.github`` directory as it requires Python 3.11 to run. It is not run 
automatically
+``dev`` directory as it requires Python 3.11 to run. It is not run 
automatically
 when you commit the code but in runs as a separate job in the CI. However, you 
can run it
 manually by running:
 
 .. code-block:: bash
 
     export GITHUB_TOKEN=YOUR_GITHUB_TOKEN
-    prek -c .github/.pre-commit-config.yaml --all-files --hook-stage manual 
--verbose
+    prek -c dev/.pre-commit-config.yaml --all-files --hook-stage manual 
--verbose
 
 
 Mypy checks
diff --git a/.github/.pre-commit-config.yaml b/dev/.pre-commit-config.yaml
similarity index 100%
rename from .github/.pre-commit-config.yaml
rename to dev/.pre-commit-config.yaml
diff --git a/go-sdk/.pre-commit-config.yaml b/go-sdk/.pre-commit-config.yaml
new file mode 100644
index 00000000000..4154c080168
--- /dev/null
+++ b/go-sdk/.pre-commit-config.yaml
@@ -0,0 +1,73 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+---
+default_stages: [pre-commit, pre-push]
+default_language_version:
+  golang: 1.24.0
+minimum_prek_version: '0.0.28'
+repos:
+  - repo: meta
+    hooks:
+      - id: identity
+        name: Print checked files
+        description: Print input to the static check hooks for troubleshooting
+      - id: check-hooks-apply
+        name: Check if all hooks apply to the repository
+  - repo: https://github.com/Lucas-C/pre-commit-hooks
+    # replace hash with version once PR #103 merged comes in a release
+    rev: abdd8b62891099da34162217ecb3872d22184a51
+    hooks:
+      - id: insert-license
+        name: Add license for all Go files
+        types: [go]
+        exclude: mocks/.*\.go$
+        args:
+          - --comment-style
+          - "|//|"
+          - --license-filepath
+          - ../scripts/ci/license-templates/LICENSE.txt
+          - --insert-license-after-regex
+          # We need this 'generated by' line at the top for `golines` to not 
format it
+          - '// Code generated by .*'
+  - repo: local
+    hooks:
+      - id: go-mockery
+        name: Generate mocks for go
+        entry: vektra/mockery:3
+        exclude: mocks/.*\.go$
+        types: [go]
+        pass_filenames: false
+        language: docker_image
+      - id: go-mod-tidy
+        name: Run go mod tidy
+        entry: go mod tidy
+        types: [go]
+        exclude: mocks/.*\.go$
+        pass_filenames: false
+        language: golang
+      - id: gofmt
+        name: Format go code
+        entry: golines --base-formatter=gofumpt --write-output --max-len=100 
--chain-split-dots
+        additional_dependencies: [github.com/segmentio/golines@latest, 
mvdan.cc/[email protected]]
+        types: [go]
+        language: golang
+      - id: gci
+        name: Consistent import ordering for Go files
+        entry: gci write --skip-generated -s standard -s default -s localmodule
+        additional_dependencies: [github.com/daixiang0/[email protected]]
+        types: [go]
+        language: golang
diff --git a/scripts/ci/prek/upgrade_important_versions.py 
b/scripts/ci/prek/upgrade_important_versions.py
index 75dc99e1be2..779c692b70b 100755
--- a/scripts/ci/prek/upgrade_important_versions.py
+++ b/scripts/ci/prek/upgrade_important_versions.py
@@ -24,6 +24,13 @@
 #   "rich>=13.6.0",
 # ]
 # ///
+#
+# DEBUGGING
+# * You can set UPGRADE_ALL_BY_DEFAULT to "false" to only upgrade those 
versions that
+#   are set by UPGRADE_NNNNNNN (NNNNNN > thing to upgrade version)
+# * You can set VERBOSE="true" to see requests being made
+# * You can set UPGRADE_NNNNNNN_INCLUDE_PRE_RELEASES="true"
+
 from __future__ import annotations
 
 import os
@@ -79,46 +86,82 @@ for file in DOCKER_IMAGES_EXAMPLE_DIR_PATH.rglob("*.sh"):
     FILES_TO_UPDATE.append((file, False))
 
 
-def get_latest_pypi_version(package_name: str) -> str:
+def get_latest_pypi_version(package_name: str, should_upgrade: bool) -> str:
+    if not should_upgrade:
+        return ""
+    if VERBOSE:
+        console.print(f"[bright_blue]Fetching latest version for 
{package_name} from PyPI")
     response = requests.get(
         f"https://pypi.org/pypi/{package_name}/json";, headers={"User-Agent": 
"Python requests"}
     )
     response.raise_for_status()  # Ensure we got a successful response
     data = response.json()
-    latest_version = data["info"]["version"]  # The version info is under the 
'info' key
+    if os.environ.get(f"UPGRADE_{package_name.upper()}_INCLUDE_PRE_RELEASES", 
""):
+        latest_version = str(sorted([Version(version) for version in 
data["releases"].keys()])[-1])
+    else:
+        latest_version = data["info"]["version"]  # The version info is under 
the 'info' key
+    if VERBOSE:
+        console.print(f"[bright_blue]Latest version for {package_name}: 
{latest_version}")
     return latest_version
 
 
-def get_latest_python_version(python_major_minor: str, github_token: str | 
None) -> str | None:
-    latest_version = None
-    # Matches versions of vA.B.C and vA.B where C can only be numeric and v is 
optional
-    version_match = re.compile(rf"^v?{python_major_minor}\.?\d*$")
+def get_all_python_versions() -> list[Version]:
+    if VERBOSE:
+        console.print("[bright_blue]Fetching all released Python versions from 
python.org")
+    url = "https://www.python.org/api/v2/downloads/release/?is_published=true";
     headers = {"User-Agent": "Python requests"}
-    if github_token:
-        headers["Authorization"] = f"Bearer {github_token}"
-    for i in range(5):
-        response = requests.get(
-            
f"https://api.github.com/repos/python/cpython/tags?per_page=100&page={i + 1}",
-            headers=headers,
-        )
-        response.raise_for_status()  # Ensure we got a successful response
-        data = response.json()
-        versions = [str(tag["name"]) for tag in data if 
version_match.match(tag.get("name", ""))]
-        if versions:
-            latest_version = sorted(versions, key=Version, reverse=True)[0]
-            break
-    return latest_version[1:] if latest_version and 
latest_version.startswith("v") else latest_version
+    response = requests.get(url, headers=headers)
+    response.raise_for_status()
+    data = response.json()
+    versions = []
+    matcher = re.compile(r"^Python ([\d.]+$)")
+    for release in data:
+        release_name = release["name"]
+        match = matcher.match(release_name)
+        if match:
+            versions.append(Version(match.group(1)))
+    return versions
+
+
+def get_latest_python_version(python_major_minor: str, all_versions: 
list[Version]) -> str:
+    """
+    Fetch the latest released Python version for a given major.minor (e.g. 
'3.12') using python.org API.
+    Much faster than paginating through all GitHub tags.
+    """
+    # Only consider releases matching the major.minor.patch pattern
+    matching = [
+        version for version in all_versions if python_major_minor == 
f"{version.major}.{version.minor}"
+    ]
+    if not matching:
+        console.print(f"[bright_red]No released Python versions found for 
{python_major_minor}")
+        sys.exit(1)
+    # Sort and return the latest version
+    latest_version = sorted(matching)[-1]
+    if VERBOSE:
+        console.print(f"[bright_blue]Latest version for {python_major_minor}: 
{latest_version}")
+    return str(latest_version)
 
 
 def get_latest_golang_version() -> str:
+    if not UPGRADE_GOLANG:
+        return ""
+    if VERBOSE:
+        console.print("[bright_blue]Fetching latest Go version from go.dev")
     response = requests.get("https://go.dev/dl/?mode=json";)
     response.raise_for_status()  # Ensure we got a successful response
     versions = response.json()
     stable_versions = [release["version"].replace("go", "") for release in 
versions if release["stable"]]
-    return sorted(stable_versions, key=Version, reverse=True)[0]
+    latest_version = sorted(stable_versions, key=Version, reverse=True)[0]
+    if VERBOSE:
+        console.print(f"[bright_blue]Latest version for Go: {latest_version}")
+    return latest_version
 
 
 def get_latest_lts_node_version() -> str:
+    if not UPGRADE_NODE_LTS:
+        return ""
+    if VERBOSE:
+        console.print("[bright_blue]Fetching latest LTS Node version from 
nodejs.org")
     response = requests.get("https://nodejs.org/dist/index.json";)
     response.raise_for_status()  # Ensure we got a successful response
     versions = response.json()
@@ -126,7 +169,10 @@ def get_latest_lts_node_version() -> str:
     lts_versions = [version["version"] for version in versions if 
version["version"].startswith(lts_prefix)]
     # The json array is sorted from newest to oldest, so the first element is 
the latest LTS version
     # Skip leading v in version
-    return lts_versions[0][1:]
+    latest_version = lts_versions[0][1:]
+    if VERBOSE:
+        console.print(f"[bright_blue]Latest version for LTS Node: 
{latest_version}")
+    return latest_version
 
 
 class Quoting(Enum):
@@ -138,38 +184,44 @@ class Quoting(Enum):
 
 
 PIP_PATTERNS: list[tuple[re.Pattern, Quoting]] = [
-    (re.compile(r"(AIRFLOW_PIP_VERSION=)([0-9.]+)"), Quoting.UNQUOTED),
-    (re.compile(r"(python -m pip install --upgrade pip==)([0-9.]+)"), 
Quoting.UNQUOTED),
-    (re.compile(r"(AIRFLOW_PIP_VERSION = )(\"[0-9.]+\")"), 
Quoting.DOUBLE_QUOTED),
-    (re.compile(r"(PIP_VERSION = )(\"[0-9.]+\")"), Quoting.DOUBLE_QUOTED),
-    (re.compile(r"(PIP_VERSION=)(\"[0-9.]+\")"), Quoting.DOUBLE_QUOTED),
-    (re.compile(r"(\| *`AIRFLOW_PIP_VERSION` *\| *)(`[0-9.]+`)( *\|)"), 
Quoting.REVERSE_SINGLE_QUOTED),
+    (re.compile(r"(AIRFLOW_PIP_VERSION=)([0-9.abrc]+)"), Quoting.UNQUOTED),
+    (re.compile(r"(python -m pip install --upgrade pip==)([0-9.abrc]+)"), 
Quoting.UNQUOTED),
+    (re.compile(r"(AIRFLOW_PIP_VERSION = )(\"[0-9.abrc]+\")"), 
Quoting.DOUBLE_QUOTED),
+    (re.compile(r"(PIP_VERSION = )(\"[0-9.abrc]+\")"), Quoting.DOUBLE_QUOTED),
+    (re.compile(r"(PIP_VERSION=)(\"[0-9.abrc]+\")"), Quoting.DOUBLE_QUOTED),
+    (re.compile(r"(\| *`AIRFLOW_PIP_VERSION` *\| *)(`[0-9.abrc]+`)( *\|)"), 
Quoting.REVERSE_SINGLE_QUOTED),
 ]
 
 PYTHON_PATTERNS: list[tuple[str, Quoting]] = [
-    (r"(\"{python_major_minor}\": \")([0-9.]+)(\")", Quoting.UNQUOTED),
+    (r"(\"{python_major_minor}\": \")([0-9.abrc]+)(\")", Quoting.UNQUOTED),
 ]
 
 GOLANG_PATTERNS: list[tuple[re.Pattern, Quoting]] = [
-    (re.compile(r"(GOLANG_MAJOR_MINOR_VERSION=)(\"[0-9.]+\")"), 
Quoting.DOUBLE_QUOTED),
-    (re.compile(r"(\| *`GOLANG_MAJOR_MINOR_VERSION` *\| *)(`[0-9.]+`)( *\|)"), 
Quoting.REVERSE_SINGLE_QUOTED),
+    (re.compile(r"(GOLANG_MAJOR_MINOR_VERSION=)(\"[0-9.abrc]+\")"), 
Quoting.DOUBLE_QUOTED),
+    (
+        re.compile(r"(\| *`GOLANG_MAJOR_MINOR_VERSION` *\| *)(`[0-9.abrc]+`)( 
*\|)"),
+        Quoting.REVERSE_SINGLE_QUOTED,
+    ),
 ]
 
 AIRFLOW_IMAGE_PYTHON_PATTERNS: list[tuple[re.Pattern, Quoting]] = [
-    (re.compile(r"(AIRFLOW_PYTHON_VERSION=)(\"[0-9.]+\")"), 
Quoting.DOUBLE_QUOTED),
-    (re.compile(r"(\| ``AIRFLOW_PYTHON_VERSION`` *\| )(``[0-9.]+``)( *\|)"), 
Quoting.REVERSE_DOUBLE_QUOTED),
+    (re.compile(r"(AIRFLOW_PYTHON_VERSION=)(\"[0-9.abrc]+\")"), 
Quoting.DOUBLE_QUOTED),
+    (
+        re.compile(r"(\| ``AIRFLOW_PYTHON_VERSION`` *\| )(``[0-9.abrc]+``)( 
*\|)"),
+        Quoting.REVERSE_DOUBLE_QUOTED,
+    ),
 ]
 
 UV_PATTERNS: list[tuple[re.Pattern, Quoting]] = [
-    (re.compile(r"(AIRFLOW_UV_VERSION=)([0-9.]+)"), Quoting.UNQUOTED),
-    (re.compile(r"(uv>=)([0-9.]+)"), Quoting.UNQUOTED),
-    (re.compile(r"(AIRFLOW_UV_VERSION = )(\"[0-9.]+\")"), 
Quoting.DOUBLE_QUOTED),
-    (re.compile(r"^(\s*UV_VERSION = )(\"[0-9.]+\")", re.MULTILINE), 
Quoting.DOUBLE_QUOTED),
-    (re.compile(r"^(\s*UV_VERSION=)(\"[0-9.]+\")", re.MULTILINE), 
Quoting.DOUBLE_QUOTED),
-    (re.compile(r"(\| *`AIRFLOW_UV_VERSION` *\| *)(`[0-9.]+`)( *\|)"), 
Quoting.REVERSE_SINGLE_QUOTED),
+    (re.compile(r"(AIRFLOW_UV_VERSION=)([0-9.abrc]+)"), Quoting.UNQUOTED),
+    (re.compile(r"(uv>=)([0-9.abrc]+)"), Quoting.UNQUOTED),
+    (re.compile(r"(AIRFLOW_UV_VERSION = )(\"[0-9.abrc]+\")"), 
Quoting.DOUBLE_QUOTED),
+    (re.compile(r"^(\s*UV_VERSION = )(\"[0-9.abrc]+\")", re.MULTILINE), 
Quoting.DOUBLE_QUOTED),
+    (re.compile(r"^(\s*UV_VERSION=)(\"[0-9.abrc]+\")", re.MULTILINE), 
Quoting.DOUBLE_QUOTED),
+    (re.compile(r"(\| *`AIRFLOW_UV_VERSION` *\| *)(`[0-9.abrd]+`)( *\|)"), 
Quoting.REVERSE_SINGLE_QUOTED),
     (
         re.compile(
-            r"(\")([0-9.]+)(\"  # Keep this comment to "
+            r"(\")([0-9.abrc]+)(\"  # Keep this comment to "
             r"allow automatic replacement of uv version)"
         ),
         Quoting.UNQUOTED,
@@ -177,18 +229,18 @@ UV_PATTERNS: list[tuple[re.Pattern, Quoting]] = [
 ]
 
 PREK_PATTERNS: list[tuple[re.Pattern, Quoting]] = [
-    (re.compile(r"(AIRFLOW_PREK_VERSION=)([0-9.]+)"), Quoting.UNQUOTED),
-    (re.compile(r"(AIRFLOW_PREK_VERSION = )(\"[0-9.]+\")"), 
Quoting.DOUBLE_QUOTED),
-    (re.compile(r"(prek>=)([0-9.]+)"), Quoting.UNQUOTED),
-    (re.compile(r"(PREK_VERSION = )(\"[0-9.]+\")"), Quoting.DOUBLE_QUOTED),
-    (re.compile(r"(PREK_VERSION=)(\"[0-9.]+\")"), Quoting.DOUBLE_QUOTED),
+    (re.compile(r"(AIRFLOW_PREK_VERSION=)([0-9.abrc]+)"), Quoting.UNQUOTED),
+    (re.compile(r"(AIRFLOW_PREK_VERSION = )(\"[0-9.abrc]+\")"), 
Quoting.DOUBLE_QUOTED),
+    (re.compile(r"(prek>=)([0-9.abrc]+)"), Quoting.UNQUOTED),
+    (re.compile(r"(PREK_VERSION = )(\"[0-9.abrc]+\")"), Quoting.DOUBLE_QUOTED),
+    (re.compile(r"(PREK_VERSION=)(\"[0-9.abrc]+\")"), Quoting.DOUBLE_QUOTED),
     (
-        re.compile(r"(\| *`AIRFLOW_PREK_VERSION` *\| *)(`[0-9.]+`)( *\|)"),
+        re.compile(r"(\| *`AIRFLOW_PREK_VERSION` *\| *)(`[0-9.abrc]+`)( *\|)"),
         Quoting.REVERSE_SINGLE_QUOTED,
     ),
     (
         re.compile(
-            r"(\")([0-9.]+)(\"  # Keep this comment to allow automatic "
+            r"(\")([0-9.abrc]+)(\"  # Keep this comment to allow automatic "
             r"replacement of prek version)"
         ),
         Quoting.UNQUOTED,
@@ -196,7 +248,7 @@ PREK_PATTERNS: list[tuple[re.Pattern, Quoting]] = [
 ]
 
 NODE_LTS_PATTERNS: list[tuple[re.Pattern, Quoting]] = [
-    (re.compile(r"( *node: )([0-9.]+)"), Quoting.UNQUOTED),
+    (re.compile(r"(^  node: )([0-9.abrc]+)^"), Quoting.UNQUOTED),
 ]
 
 
@@ -212,18 +264,25 @@ def get_replacement(value: str, quoting: Quoting) -> str:
     return value
 
 
-UPGRADE_UV: bool = os.environ.get("UPGRADE_UV", "true").lower() == "true"
-UPGRADE_PIP: bool = os.environ.get("UPGRADE_PIP", "true").lower() == "true"
-UPGRADE_PYTHON: bool = os.environ.get("UPGRADE_PYTHON", "true").lower() == 
"true"
-UPGRADE_GOLANG: bool = os.environ.get("UPGRADE_GOLANG", "true").lower() == 
"true"
-UPGRADE_PREK: bool = os.environ.get("UPGRADE_PREK", "true").lower() == "true"
-UPGRADE_NODE_LTS: bool = os.environ.get("UPGRADE_NODE_LTS", "true").lower() == 
"true"
-UPGRADE_HATCH: bool = os.environ.get("UPGRADE_HATCH", "true").lower() == "true"
-UPGRADE_PYYAML: bool = os.environ.get("UPGRADE_PYYAML", "true").lower() == 
"true"
-UPGRADE_GITPYTHON: bool = os.environ.get("UPGRADE_GITPYTHON", "true").lower() 
== "true"
-UPGRADE_RICH: bool = os.environ.get("UPGRADE_RICH", "true").lower() == "true"
-UPGRADE_RUFF: bool = os.environ.get("UPGRADE_RUFF", "true").lower() == "true"
-UPGRADE_MYPY: bool = os.environ.get("UPGRADE_MYPY", "true").lower() == "true"
+VERBOSE: bool = os.environ.get("VERBOSE", "false") == "true"
+UPGRADE_ALL_BY_DEFAULT: bool = os.environ.get("UPGRADE_ALL_BY_DEFAULT", 
"true") == "true"
+UPGRADE_ALL_BY_DEFAULT_STR: str = str(UPGRADE_ALL_BY_DEFAULT).lower()
+if UPGRADE_ALL_BY_DEFAULT:
+    if VERBOSE == "true":
+        console.print("[bright_blue]Upgrading all important versions")
+
+UPGRADE_GITPYTHON: bool = os.environ.get("UPGRADE_GITPYTHON", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_GOLANG: bool = os.environ.get("UPGRADE_GOLANG", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_HATCH: bool = os.environ.get("UPGRADE_HATCH", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_NODE_LTS: bool = os.environ.get("UPGRADE_NODE_LTS", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_PIP: bool = os.environ.get("UPGRADE_PIP", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_PREK: bool = os.environ.get("UPGRADE_PREK", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_PYTHON: bool = os.environ.get("UPGRADE_PYTHON", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_PYYAML: bool = os.environ.get("UPGRADE_PYYAML", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_RICH: bool = os.environ.get("UPGRADE_RICH", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_RUFF: bool = os.environ.get("UPGRADE_RUFF", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_UV: bool = os.environ.get("UPGRADE_UV", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
+UPGRADE_MYPY: bool = os.environ.get("UPGRADE_MYPY", 
UPGRADE_ALL_BY_DEFAULT_STR).lower() == "true"
 
 ALL_PYTHON_MAJOR_MINOR_VERSIONS = ["3.9", "3.10", "3.11", "3.12", "3.13"]
 DEFAULT_PROD_IMAGE_PYTHON_VERSION = "3.12"
@@ -260,51 +319,53 @@ if __name__ == "__main__":
     gh_token = 
retrieve_gh_token(description="airflow-upgrade-important-versions", 
scopes="public_repo")
     changed = False
     golang_version = get_latest_golang_version()
-    pip_version = get_latest_pypi_version("pip")
-    uv_version = get_latest_pypi_version("uv")
-    setuptools_version = get_latest_pypi_version("setuptools")
-    prek_version = get_latest_pypi_version("prek")
-    hatch_version = get_latest_pypi_version("hatch")
-    pyyaml_version = get_latest_pypi_version("PyYAML")
-    gitpython_version = get_latest_pypi_version("GitPython")
-    rich_version = get_latest_pypi_version("rich")
-    ruff_version = get_latest_pypi_version("ruff")
+    pip_version = get_latest_pypi_version("pip", UPGRADE_PIP)
+    uv_version = get_latest_pypi_version("uv", UPGRADE_UV)
+    prek_version = get_latest_pypi_version("prek", UPGRADE_PREK)
+    hatch_version = get_latest_pypi_version("hatch", UPGRADE_HATCH)
+    pyyaml_version = get_latest_pypi_version("PyYAML", UPGRADE_PYYAML)
+    gitpython_version = get_latest_pypi_version("GitPython", UPGRADE_GITPYTHON)
+    ruff_version = get_latest_pypi_version("ruff", UPGRADE_RUFF)
+    rich_version = get_latest_pypi_version("rich", UPGRADE_RICH)
+    mypy_version = get_latest_pypi_version("mypy", UPGRADE_MYPY)
     node_lts_version = get_latest_lts_node_version()
-    mypy_version = get_latest_pypi_version("mypy")
+    latest_python_versions: dict[str, str] = {}
+    latest_image_python_version = ""
+    if UPGRADE_PYTHON:
+        all_python_versions = get_all_python_versions() if UPGRADE_PYTHON else 
None
+        for python_major_minor_version in ALL_PYTHON_MAJOR_MINOR_VERSIONS:
+            latest_python_versions[python_major_minor_version] = 
get_latest_python_version(
+                python_major_minor_version, all_python_versions
+            )
+            if python_major_minor_version == DEFAULT_PROD_IMAGE_PYTHON_VERSION:
+                latest_image_python_version = 
latest_python_versions[python_major_minor_version]
+                console.print(
+                    f"[bright_blue]Latest image python 
{python_major_minor_version} version: {latest_image_python_version}"
+                )
     for file, keep_length in FILES_TO_UPDATE:
         console.print(f"[bright_blue]Updating {file}")
         file_content = file.read_text()
         new_content = file_content
         if UPGRADE_PIP:
-            console.print(f"[bright_blue]Latest pip version: {pip_version}")
             for line_pattern, quoting in PIP_PATTERNS:
                 new_content = replace_version(
                     line_pattern, get_replacement(pip_version, quoting), 
new_content, keep_length
                 )
         if UPGRADE_PYTHON:
-            for python_version in ALL_PYTHON_MAJOR_MINOR_VERSIONS:
-                latest_python_version = 
get_latest_python_version(python_version, gh_token)
-                if not latest_python_version:
-                    console.print(
-                        f"[red]Failed to get latest version for python 
{python_version}. Skipping.[/]"
-                    )
-                    sys.exit(1)
-                console.print(f"[bright_blue]Latest python {python_version} 
version: {latest_python_version}")
+            for python_major_minor_version in ALL_PYTHON_MAJOR_MINOR_VERSIONS:
+                latest_python_version = 
latest_python_versions[python_major_minor_version]
                 for line_format, quoting in PYTHON_PATTERNS:
-                    line_pattern = 
re.compile(line_format.format(python_major_minor=python_version))
-                    console.print(line_pattern)
+                    line_pattern = re.compile(
+                        
line_format.format(python_major_minor=python_major_minor_version)
+                    )
                     new_content = replace_version(
                         line_pattern,
                         get_replacement(latest_python_version, quoting),
                         new_content,
                         keep_length,
                     )
-                if python_version == DEFAULT_PROD_IMAGE_PYTHON_VERSION:
-                    console.print(
-                        f"[bright_blue]Latest image python {python_version} 
version: {latest_python_version}"
-                    )
+                if python_major_minor_version == 
DEFAULT_PROD_IMAGE_PYTHON_VERSION:
                     for line_pattern, quoting in AIRFLOW_IMAGE_PYTHON_PATTERNS:
-                        console.print(line_pattern)
                         new_content = replace_version(
                             line_pattern,
                             get_replacement(latest_python_version, quoting),
@@ -312,25 +373,21 @@ if __name__ == "__main__":
                             keep_length,
                         )
         if UPGRADE_GOLANG:
-            console.print(f"[bright_blue]Latest golang version: 
{golang_version}")
             for line_pattern, quoting in GOLANG_PATTERNS:
                 new_content = replace_version(
                     line_pattern, get_replacement(golang_version, quoting), 
new_content, keep_length
                 )
         if UPGRADE_UV:
-            console.print(f"[bright_blue]Latest uv version: {uv_version}")
             for line_pattern, quoting in UV_PATTERNS:
                 new_content = replace_version(
                     line_pattern, get_replacement(uv_version, quoting), 
new_content, keep_length
                 )
         if UPGRADE_PREK:
-            console.print(f"[bright_blue]Latest prek version: {prek_version}")
             for line_pattern, quoting in PREK_PATTERNS:
                 new_content = replace_version(
                     line_pattern, get_replacement(prek_version, quoting), 
new_content, keep_length
                 )
         if UPGRADE_NODE_LTS:
-            console.print(f"[bright_blue]Latest Node LTS version: 
{node_lts_version}")
             for line_pattern, quoting in NODE_LTS_PATTERNS:
                 new_content = replace_version(
                     line_pattern,
@@ -339,62 +396,57 @@ if __name__ == "__main__":
                     keep_length,
                 )
         if UPGRADE_HATCH:
-            console.print(f"[bright_blue]Latest hatch version: 
{hatch_version}")
             new_content = re.sub(
-                r"(HATCH_VERSION = )(\"[0-9.]+\")",
+                r"(HATCH_VERSION = )(\"[0-9.abrc]+\")",
                 f'HATCH_VERSION = "{hatch_version}"',
                 new_content,
             )
             new_content = re.sub(
-                r"(HATCH_VERSION=)(\"[0-9.]+\")",
+                r"(HATCH_VERSION=)(\"[0-9.abrc]+\")",
                 f'HATCH_VERSION="{hatch_version}"',
                 new_content,
             )
         if UPGRADE_PYYAML:
-            console.print(f"[bright_blue]Latest PyYAML version: 
{pyyaml_version}")
             new_content = re.sub(
-                r"(PYYAML_VERSION = )(\"[0-9.]+\")",
+                r"(PYYAML_VERSION = )(\"[0-9.abrc]+\")",
                 f'PYYAML_VERSION = "{pyyaml_version}"',
                 new_content,
             )
             new_content = re.sub(
-                r"(PYYAML_VERSION=)(\"[0-9.]+\")",
+                r"(PYYAML_VERSION=)(\"[0-9.abrc]+\")",
                 f'PYYAML_VERSION="{pyyaml_version}"',
                 new_content,
             )
         if UPGRADE_GITPYTHON:
-            console.print(f"[bright_blue]Latest GitPython version: 
{gitpython_version}")
             new_content = re.sub(
-                r"(GITPYTHON_VERSION = )(\"[0-9.]+\")",
+                r"(GITPYTHON_VERSION = )(\"[0-9.abrc]+\")",
                 f'GITPYTHON_VERSION = "{gitpython_version}"',
                 new_content,
             )
             new_content = re.sub(
-                r"(GITPYTHON_VERSION=)(\"[0-9.]+\")",
+                r"(GITPYTHON_VERSION=)(\"[0-9.abrc]+\")",
                 f'GITPYTHON_VERSION="{gitpython_version}"',
                 new_content,
             )
         if UPGRADE_RICH:
-            console.print(f"[bright_blue]Latest rich version: {rich_version}")
             new_content = re.sub(
-                r"(RICH_VERSION = )(\"[0-9.]+\")",
+                r"(RICH_VERSION = )(\"[0-9.abrc]+\")",
                 f'RICH_VERSION = "{rich_version}"',
                 new_content,
             )
             new_content = re.sub(
-                r"(RICH_VERSION=)(\"[0-9.]+\")",
+                r"(RICH_VERSION=)(\"[0-9.abrc]+\")",
                 f'RICH_VERSION="{rich_version}"',
                 new_content,
             )
         if UPGRADE_RUFF:
-            console.print(f"[bright_blue]Latest ruff version: {ruff_version}")
             new_content = re.sub(
-                r"(ruff==)([0-9.]+)",
+                r"(ruff==)([0-9.abrc]+)",
                 f"ruff=={ruff_version}",
                 new_content,
             )
             new_content = re.sub(
-                r"(ruff>=)([0-9.]+)",
+                r"(ruff>=)([0-9.abrc]+)",
                 f"ruff>={ruff_version}",
                 new_content,
             )

Reply via email to