From 281fadc7d40db2cb944931972f26e929d32ce5d2 Mon Sep 17 00:00:00 2001 From: Eason09053360 <185830721+Eason09053360@users.noreply.github.com> Date: Sat, 12 Sep 2026 18:00:04 +0800 Subject: [PATCH] Fix invalid command path in permissions-cleanup help examples The examples printed by `airflow permissions-cleanup --help` told users to run the command under a `fab-auth-manager` group that has never existed, so copying any of them straight from the help output fails with exit code 2. Anyone reaching for the help text is by definition the person who does not already know the right invocation. --- .../airflow/providers/fab/cli/definition.py | 8 +++--- .../fab/tests/unit/fab/cli/test_definition.py | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/providers/fab/src/airflow/providers/fab/cli/definition.py b/providers/fab/src/airflow/providers/fab/cli/definition.py index 85e03757dae15..4707cdefe7dce 100644 --- a/providers/fab/src/airflow/providers/fab/cli/definition.py +++ b/providers/fab/src/airflow/providers/fab/cli/definition.py @@ -286,13 +286,13 @@ epilog=( "examples:\n" "To see what orphaned permissions would be cleaned up:\n" - " $ airflow fab-auth-manager permissions-cleanup --dry-run\n" + " $ airflow permissions-cleanup --dry-run\n" "To clean up all orphaned permissions:\n" - " $ airflow fab-auth-manager permissions-cleanup\n" + " $ airflow permissions-cleanup\n" "To clean up permissions for specific DAG:\n" - " $ airflow fab-auth-manager permissions-cleanup --dag-id my_dag\n" + " $ airflow permissions-cleanup --dag-id my_dag\n" "To clean up without confirmation:\n" - " $ airflow fab-auth-manager permissions-cleanup --yes" + " $ airflow permissions-cleanup --yes" ), ) diff --git a/providers/fab/tests/unit/fab/cli/test_definition.py b/providers/fab/tests/unit/fab/cli/test_definition.py index d6904683eab2b..4f60142c5a356 100644 --- a/providers/fab/tests/unit/fab/cli/test_definition.py +++ b/providers/fab/tests/unit/fab/cli/test_definition.py @@ -16,13 +16,31 @@ # under the License. from __future__ import annotations +import shlex + +import pytest + from airflow.providers.fab.cli.definition import ( + PERMISSIONS_CLEANUP_COMMAND, ROLES_COMMANDS, SYNC_PERM_COMMAND, USERS_COMMANDS, + get_parser, ) +def _extract_epilog_examples(command): + examples = [] + for line in (command.epilog or "").splitlines(): + stripped = line.strip() + if stripped.startswith("$ airflow "): + examples.append(stripped.removeprefix("$ ")) + if not examples: + # An empty parametrize set is silently skipped, which would hide the loss of this guard. + raise ValueError(f"No '$ airflow ...' example found in the {command.name} epilog") + return examples + + class TestCliDefinition: def test_users_commands(self): assert len(USERS_COMMANDS) == 8 @@ -32,3 +50,10 @@ def test_roles_commands(self): def test_sync_perm_command(self): assert SYNC_PERM_COMMAND.name == "sync-perm" + + @pytest.mark.parametrize( + "example", _extract_epilog_examples(PERMISSIONS_CLEANUP_COMMAND), ids=lambda e: e + ) + def test_permissions_cleanup_epilog_examples_are_runnable(self, example): + args = get_parser().parse_args(shlex.split(example)[1:]) + assert args.subcommand == PERMISSIONS_CLEANUP_COMMAND.name