From a555ebb48aeff59682558e0b364bf5c5dd5906e6 Mon Sep 17 00:00:00 2001 From: Shahar Epstein <60007259+shahar1@users.noreply.github.com> Date: Fri, 24 Jul 2026 09:46:49 +0300 Subject: [PATCH 1/4] Stop labelling operator-init exemption removals for backport to v3-3-test The operator-init exemptions list lives under scripts/, so every PR that fixes an operator and drops its line from the list gets a backport-to-v3-3-test label. Those removals track work that only happens on main and are never backported, so the label is pure noise for the release manager triaging the backport queue. --- .github/boring-cyborg.yml | 9 +++++++++ scripts/ci/prek/boring_cyborg.py | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/boring-cyborg.yml b/.github/boring-cyborg.yml index e1535a247cec3..3e3a4f7b3e3bc 100644 --- a/.github/boring-cyborg.yml +++ b/.github/boring-cyborg.yml @@ -369,6 +369,15 @@ labelPRBasedOnFilePath: backport-to-v3-3-test: paths: - scripts/**/* + # The exemptions list only ever shrinks as operators are fixed on main, so those + # removals must never be backported. Patterns follow gitignore semantics, which + # cannot re-include a file whose parent directory is excluded — hence the chain + # of directory re-includes leading down to the file. + - "!scripts/ci/" + - scripts/ci/* + - "!scripts/ci/prek/" + - scripts/ci/prek/* + - "!scripts/ci/prek/validate_operators_init_exemptions.txt" - dev/**/* - .github/**/* - Dockerfile.ci diff --git a/scripts/ci/prek/boring_cyborg.py b/scripts/ci/prek/boring_cyborg.py index 5e9ef359ffb7c..366ee2db83e6f 100755 --- a/scripts/ci/prek/boring_cyborg.py +++ b/scripts/ci/prek/boring_cyborg.py @@ -55,8 +55,11 @@ else: patterns = rule for pattern in patterns: + # Patterns follow gitignore semantics: `!` re-includes and a trailing `/` restricts + # to directories. Both still have to point at something that exists. + glob_pattern = pattern.removeprefix("!").rstrip("/") try: - next(Path(AIRFLOW_ROOT_PATH).glob(pattern)) + next(Path(AIRFLOW_ROOT_PATH).glob(glob_pattern)) continue except StopIteration: yaml_path = f"{CONFIG_KEY}.{label}" From a32e7a5a27e4646ab86837b80c98f0b8efeb4858 Mon Sep 17 00:00:00 2001 From: Shahar Epstein <60007259+shahar1@users.noreply.github.com> Date: Fri, 24 Jul 2026 09:51:11 +0300 Subject: [PATCH 2/4] Drop redundant re-ignore patterns from the exemptions exclusion --- .github/boring-cyborg.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/boring-cyborg.yml b/.github/boring-cyborg.yml index 3e3a4f7b3e3bc..99038c9eccc8f 100644 --- a/.github/boring-cyborg.yml +++ b/.github/boring-cyborg.yml @@ -371,12 +371,10 @@ labelPRBasedOnFilePath: - scripts/**/* # The exemptions list only ever shrinks as operators are fixed on main, so those # removals must never be backported. Patterns follow gitignore semantics, which - # cannot re-include a file whose parent directory is excluded — hence the chain - # of directory re-includes leading down to the file. + # cannot re-include a file whose parent directory is excluded — so both parent + # directories have to be re-included before the file itself. - "!scripts/ci/" - - scripts/ci/* - "!scripts/ci/prek/" - - scripts/ci/prek/* - "!scripts/ci/prek/validate_operators_init_exemptions.txt" - dev/**/* - .github/**/* From 666d15a2cd2e054dcdc556f45125536c625c6da3 Mon Sep 17 00:00:00 2001 From: Shahar Epstein <60007259+shahar1@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:01:10 +0300 Subject: [PATCH 3/4] Move operator-init exemptions list to generated/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The list lived under scripts/, which is one of the paths that earns a backport-to-v3-3-test label, so every PR that fixes an operator and drops its line was flagged for a backport that never applies — the burn-down only happens on main. Sitting next to known_airflow_exceptions.txt also puts the two prek allowlists in the same place. --- .github/boring-cyborg.yml | 7 ------- .../validate_operators_init_exemptions.txt | 0 scripts/ci/prek/boring_cyborg.py | 5 +---- scripts/ci/prek/validate_operators_init.py | 5 +++-- 4 files changed, 4 insertions(+), 13 deletions(-) rename {scripts/ci/prek => generated}/validate_operators_init_exemptions.txt (100%) diff --git a/.github/boring-cyborg.yml b/.github/boring-cyborg.yml index 99038c9eccc8f..e1535a247cec3 100644 --- a/.github/boring-cyborg.yml +++ b/.github/boring-cyborg.yml @@ -369,13 +369,6 @@ labelPRBasedOnFilePath: backport-to-v3-3-test: paths: - scripts/**/* - # The exemptions list only ever shrinks as operators are fixed on main, so those - # removals must never be backported. Patterns follow gitignore semantics, which - # cannot re-include a file whose parent directory is excluded — so both parent - # directories have to be re-included before the file itself. - - "!scripts/ci/" - - "!scripts/ci/prek/" - - "!scripts/ci/prek/validate_operators_init_exemptions.txt" - dev/**/* - .github/**/* - Dockerfile.ci diff --git a/scripts/ci/prek/validate_operators_init_exemptions.txt b/generated/validate_operators_init_exemptions.txt similarity index 100% rename from scripts/ci/prek/validate_operators_init_exemptions.txt rename to generated/validate_operators_init_exemptions.txt diff --git a/scripts/ci/prek/boring_cyborg.py b/scripts/ci/prek/boring_cyborg.py index 366ee2db83e6f..5e9ef359ffb7c 100755 --- a/scripts/ci/prek/boring_cyborg.py +++ b/scripts/ci/prek/boring_cyborg.py @@ -55,11 +55,8 @@ else: patterns = rule for pattern in patterns: - # Patterns follow gitignore semantics: `!` re-includes and a trailing `/` restricts - # to directories. Both still have to point at something that exists. - glob_pattern = pattern.removeprefix("!").rstrip("/") try: - next(Path(AIRFLOW_ROOT_PATH).glob(glob_pattern)) + next(Path(AIRFLOW_ROOT_PATH).glob(pattern)) continue except StopIteration: yaml_path = f"{CONFIG_KEY}.{label}" diff --git a/scripts/ci/prek/validate_operators_init.py b/scripts/ci/prek/validate_operators_init.py index b8893700c9037..c30dcfd00e7ff 100755 --- a/scripts/ci/prek/validate_operators_init.py +++ b/scripts/ci/prek/validate_operators_init.py @@ -28,13 +28,14 @@ from pathlib import Path from typing import Any +from common_prek_utils import AIRFLOW_ROOT_PATH from rich.console import Console from rich.markup import escape console = Console(color_system="standard", width=200) # Pre-existing violations exempted from the checks; burn-down tracked at # https://github.com/apache/airflow/issues/70296 -EXEMPTIONS_PATH = Path(__file__).parent / "validate_operators_init_exemptions.txt" +EXEMPTIONS_PATH = AIRFLOW_ROOT_PATH / "generated" / "validate_operators_init_exemptions.txt" BASE_CLASS_NAME_SUFFIXES = ("BaseOperator", "BaseSensorOperator") # Helper callables used as template_fields values, mapped to the fields the helper injects # on top of the explicit arguments. Injected fields are owned and assigned by the base class, @@ -512,7 +513,7 @@ def main(): console.print( f"[red]Stale exemption for {class_name} — the class has no findings anymore " f"(or is not detected as an operator); remove its entry from " - f"{EXEMPTIONS_PATH.name}[/red]" + f"{EXEMPTIONS_PATH.relative_to(AIRFLOW_ROOT_PATH)}[/red]" ) return err From 775e730b02938ce5f1b83f8447cc802e1bc88fef Mon Sep 17 00:00:00 2001 From: Shahar Epstein <60007259+shahar1@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:06:17 +0300 Subject: [PATCH 4/4] Print the exemptions file path without resolving against the repo root --- scripts/ci/prek/validate_operators_init.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/ci/prek/validate_operators_init.py b/scripts/ci/prek/validate_operators_init.py index c30dcfd00e7ff..8c8b1814a7503 100755 --- a/scripts/ci/prek/validate_operators_init.py +++ b/scripts/ci/prek/validate_operators_init.py @@ -35,7 +35,8 @@ console = Console(color_system="standard", width=200) # Pre-existing violations exempted from the checks; burn-down tracked at # https://github.com/apache/airflow/issues/70296 -EXEMPTIONS_PATH = AIRFLOW_ROOT_PATH / "generated" / "validate_operators_init_exemptions.txt" +EXEMPTIONS_FILE = "generated/validate_operators_init_exemptions.txt" +EXEMPTIONS_PATH = AIRFLOW_ROOT_PATH / EXEMPTIONS_FILE BASE_CLASS_NAME_SUFFIXES = ("BaseOperator", "BaseSensorOperator") # Helper callables used as template_fields values, mapped to the fields the helper injects # on top of the explicit arguments. Injected fields are owned and assigned by the base class, @@ -513,7 +514,7 @@ def main(): console.print( f"[red]Stale exemption for {class_name} — the class has no findings anymore " f"(or is not detected as an operator); remove its entry from " - f"{EXEMPTIONS_PATH.relative_to(AIRFLOW_ROOT_PATH)}[/red]" + f"{EXEMPTIONS_FILE}[/red]" ) return err