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 d122d0386d6 Fix config lint warnings for remove_if_equals rules 
(#66370)
d122d0386d6 is described below

commit d122d0386d684dd449d6581dd5b4244e30f7e607
Author: Henry Chen <[email protected]>
AuthorDate: Sun Jul 5 06:26:33 2026 +0800

    Fix config lint warnings for remove_if_equals rules (#66370)
---
 .../src/airflowctl/ctl/commands/config_command.py  | 32 +++++++----
 .../ctl/commands/test_config_command.py            | 67 ++++++++++++++++++++++
 2 files changed, 88 insertions(+), 11 deletions(-)

diff --git a/airflow-ctl/src/airflowctl/ctl/commands/config_command.py 
b/airflow-ctl/src/airflowctl/ctl/commands/config_command.py
index 20147484d94..b83600697ad 100644
--- a/airflow-ctl/src/airflowctl/ctl/commands/config_command.py
+++ b/airflow-ctl/src/airflowctl/ctl/commands/config_command.py
@@ -67,10 +67,10 @@ class ConfigChange:
     breaking: bool = False
     remove_if_equals: str | bool | int | float | None = None
 
-    def message(self, api_client=NEW_API_CLIENT) -> str | None:
+    def message(self, all_configs: Config) -> str | None:
         """Generate a message for this configuration change."""
         if self.default_change:
-            value = self._get_option_value(api_client.configs.list())
+            value = self._get_option_value(all_configs)
             if value != self.new_default:
                 return (
                     f"Changed default value of `{self.config.option}` in 
`{self.config.section}` "
@@ -86,14 +86,15 @@ class ConfigChange:
                 f"`{self.config.option}` configuration parameter renamed to 
`{self.renamed_to.option}` "
                 f"in the `{self.config.section}` section."
             )
-        if self.was_removed and not self.remove_if_equals:
-            return (
-                f"Removed{' deprecated' if self.was_deprecated else ''} 
`{self.config.option}` configuration parameter "
-                f"from `{self.config.section}` section."
-                f"{self.suggestion}"
-            )
+        if self.was_removed:
+            if self.remove_if_equals is None:
+                return self._removed_message
+
+            value = self._get_option_value(all_configs)
+            if value == str(self.remove_if_equals):
+                return self._removed_message
         if self.is_invalid_if is not None:
-            value = self._get_option_value(api_client.configs.list())
+            value = self._get_option_value(all_configs)
             if value == self.is_invalid_if:
                 return (
                     f"Invalid value `{self.is_invalid_if}` set for 
`{self.config.option}` configuration parameter "
@@ -109,6 +110,14 @@ class ConfigChange:
                         return option.value if isinstance(option.value, str) 
else str(option.value)
         return None
 
+    @property
+    def _removed_message(self) -> str:
+        return (
+            f"Removed{' deprecated' if self.was_deprecated else ''} 
`{self.config.option}` configuration parameter "
+            f"from `{self.config.section}` section."
+            f"{self.suggestion}"
+        )
+
 
 CONFIGS_CHANGES = [
     # admin
@@ -805,8 +814,9 @@ def lint(args, api_client=NEW_API_CLIENT) -> None:
                     None,
                 )
                 if target_option:
-                    if configuration.message(api_client=api_client) is not 
None:
-                        
lint_issues.append(configuration.message(api_client=api_client))
+                    msg = configuration.message(all_configs)
+                    if msg is not None:
+                        lint_issues.append(msg)
 
         if lint_issues:
             rich.print("[red]Found issues in your airflow.cfg:[/red]")
diff --git a/airflow-ctl/tests/airflow_ctl/ctl/commands/test_config_command.py 
b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_config_command.py
index 731e30137c7..77705a4c63c 100644
--- a/airflow-ctl/tests/airflow_ctl/ctl/commands/test_config_command.py
+++ b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_config_command.py
@@ -19,6 +19,8 @@ from __future__ import annotations
 import os
 from unittest.mock import patch
 
+import pytest
+
 from airflowctl.api.client import ClientKind
 from airflowctl.api.datamodels.generated import Config, ConfigOption, 
ConfigSection
 from airflowctl.ctl import cli_parser
@@ -158,6 +160,71 @@ class TestCliConfigCommands:
             in calls[1]
         )
 
+    @pytest.mark.parametrize(
+        ("remove_if_equals", "config_value", "expected_has_issue"),
+        [
+            pytest.param("matching_value", "matching_value", True, 
id="non-empty-match"),
+            pytest.param("", "", True, id="empty-string-match"),
+            pytest.param("", "non_matching_value", False, 
id="empty-string-no-match"),
+        ],
+    )
+    def test_lint_handles_remove_if_equals_rules(
+        self, api_client_maker, remove_if_equals, config_value, 
expected_has_issue
+    ):
+        with (
+            patch("airflowctl.api.client.Credentials.load"),
+            patch.dict(os.environ, {"AIRFLOW_CLI_TOKEN": "TEST_TOKEN"}),
+            patch.dict(os.environ, {"AIRFLOW_CLI_ENVIRONMENT": "TEST_CONFIG"}),
+            patch("rich.print") as mock_rich_print,
+            patch(
+                "airflowctl.ctl.commands.config_command.CONFIGS_CHANGES",
+                [
+                    ConfigChange(
+                        config=ConfigParameter("test_section", "test_option"),
+                        was_removed=True,
+                        remove_if_equals=remove_if_equals,
+                    ),
+                ],
+            ),
+        ):
+            response_config = Config(
+                sections=[
+                    ConfigSection(
+                        name="test_section",
+                        options=[
+                            ConfigOption(
+                                key="test_option",
+                                value=config_value,
+                            )
+                        ],
+                    )
+                ]
+            )
+
+            api_client = api_client_maker(
+                path="/api/v2/config",
+                response_json=response_config.model_dump(),
+                expected_http_status_code=200,
+                kind=ClientKind.CLI,
+            )
+
+            config_command.lint(
+                self.parser.parse_args(["config", "lint"]),
+                api_client=api_client,
+            )
+
+        calls = [call[0][0] for call in mock_rich_print.call_args_list]
+        if expected_has_issue:
+            assert "[red]Found issues in your airflow.cfg:[/red]" in calls[0]
+            assert (
+                "- [yellow]Removed deprecated `test_option` configuration 
parameter from `test_section` section.[/yellow]"
+                in calls[1]
+            )
+        else:
+            assert (
+                "[green]No issues found in your airflow.cfg. It is ready for 
Airflow 3![/green]" in calls[0]
+            )
+
     @patch("airflowctl.api.client.Credentials.load")
     @patch.dict(os.environ, {"AIRFLOW_CLI_TOKEN": "TEST_TOKEN"})
     @patch.dict(os.environ, {"AIRFLOW_CLI_ENVIRONMENT": "TEST_CONFIG"})

Reply via email to