This is an automated email from the ASF dual-hosted git repository. asorokoumov pushed a commit to branch fix-config-file in repository https://gitbox.apache.org/repos/asf/otava.git
commit 456f83c0cc372680e003f1c2faed4164c813b6e7 Author: Alex Sorokoumov <[email protected]> AuthorDate: Tue Mar 10 20:09:36 2026 -0700 Fix --config-file parser broken by configargparse 1.7.3 configargparse 1.7.3 changed how env var args are inserted into the arg list, causing `OTAVA_CONFIG` env var expansion to land after the subcommand positional arg. The subparser then rejects `--config-file` as unrecognized. The fix is to add `--config-file` to the parent subparser. --- otava/config.py | 8 ++++++ otava/main.py | 18 +++++++------ tests/cli_help_test.py | 70 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 63 insertions(+), 33 deletions(-) diff --git a/otava/config.py b/otava/config.py index 126fe0e..d9cd986 100644 --- a/otava/config.py +++ b/otava/config.py @@ -182,6 +182,14 @@ def add_service_option_groups(parser) -> None: BigQueryConfig.add_parser_args(parser.add_argument_group('BigQuery Options', 'Options for BigQuery configuration')) +def create_subparser_parent() -> configargparse.ArgumentParser: + """Create a parent parser for subparsers that accepts --config-file and service options.""" + parent = configargparse.ArgumentParser(add_help=False) + parent.add_argument('--config-file', help='Otava config file path', env_var="OTAVA_CONFIG") + add_service_option_groups(parent) + return parent + + def create_config_parser() -> configargparse.ArgumentParser: parser = configargparse.ArgumentParser( add_help=False, diff --git a/otava/main.py b/otava/main.py index a017123..8748ae2 100644 --- a/otava/main.py +++ b/otava/main.py @@ -457,33 +457,35 @@ def create_otava_cli_parser() -> argparse.ArgumentParser: allow_abbrev=False, # required for correct parsing of nested values from config file ) + subparser_parent = config.create_subparser_parent() + subparsers = parser.add_subparsers(dest="command") list_tests_parser = subparsers.add_parser( "list-tests", help="list available tests", + parents=[subparser_parent], ) - config.add_service_option_groups(list_tests_parser) list_tests_parser.add_argument("group", help="name of the group of the tests", nargs="*") list_metrics_parser = subparsers.add_parser( "list-metrics", help="list available metrics for a test", + parents=[subparser_parent], ) - config.add_service_option_groups(list_metrics_parser) list_metrics_parser.add_argument("test", help="name of the test") - list_groups_parser = subparsers.add_parser( + subparsers.add_parser( "list-groups", help="list available groups of tests", + parents=[subparser_parent], ) - config.add_service_option_groups(list_groups_parser) analyze_parser = subparsers.add_parser( "analyze", help="analyze performance test results", + parents=[subparser_parent], ) analyze_parser.add_argument("tests", help="name of the test or group of the tests", nargs="+") - config.add_service_option_groups(analyze_parser) analyze_parser.add_argument( "--update-grafana", help="Update Grafana dashboards with appropriate annotations of change points", @@ -523,8 +525,8 @@ def create_otava_cli_parser() -> argparse.ArgumentParser: remove_annotations_parser = subparsers.add_parser( "remove-annotations", + parents=[subparser_parent], ) - config.add_service_option_groups(remove_annotations_parser) remove_annotations_parser.add_argument( "tests", help="name of the test or test group", nargs="*" ) @@ -532,11 +534,11 @@ def create_otava_cli_parser() -> argparse.ArgumentParser: "--force", help="don't ask questions, just do it", dest="force", action="store_true" ) - validate_parser = subparsers.add_parser( + subparsers.add_parser( "validate", help="validates the tests and metrics defined in the configuration", + parents=[subparser_parent], ) - config.add_service_option_groups(validate_parser) return parser diff --git a/tests/cli_help_test.py b/tests/cli_help_test.py index c89724a..ad4dddd 100644 --- a/tests/cli_help_test.py +++ b/tests/cli_help_test.py @@ -136,9 +136,10 @@ def test_otava_analyze_help_output(): # Python 3.13+ formats usage lines and option aliases differently if IS_PYTHON_313_PLUS: usage_and_options = """\ -usage: otava analyze [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL] - [--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD] - [--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME] +usage: otava analyze [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL] + [--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER] + [--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN] + [--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME] [--postgres-password POSTGRES_PASSWORD] [--postgres-database POSTGRES_DATABASE] @@ -159,6 +160,8 @@ positional arguments: options: -h, --help show this help message and exit + --config-file CONFIG_FILE + Otava config file path [env var: OTAVA_CONFIG] --update-grafana Update Grafana dashboards with appropriate annotations of change points --update-postgres Update PostgreSQL database results with change points --update-bigquery Update BigQuery database results with change points @@ -193,10 +196,11 @@ options: -M, --magnitude MAGNITUDE""" else: usage_and_options = """\ -usage: otava analyze [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL] - [--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD] - [--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME] - [--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME] +usage: otava analyze [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL] + [--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER] + [--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN] + [--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT] + [--postgres-username POSTGRES_USERNAME] [--postgres-password POSTGRES_PASSWORD] [--postgres-database POSTGRES_DATABASE] [--bigquery-project-id BIGQUERY_PROJECT_ID] @@ -217,6 +221,8 @@ positional arguments: options: -h, --help show this help message and exit + --config-file CONFIG_FILE + Otava config file path [env var: OTAVA_CONFIG] --update-grafana Update Grafana dashboards with appropriate annotations of change points --update-postgres Update PostgreSQL database results with change points --update-bigquery Update BigQuery database results with change points @@ -324,10 +330,11 @@ def test_otava_list_tests_help_output(): assert ( result.stdout == """\ -usage: otava list-tests [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL] - [--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD] - [--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME] - [--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME] +usage: otava list-tests [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL] + [--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER] + [--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN] + [--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT] + [--postgres-username POSTGRES_USERNAME] [--postgres-password POSTGRES_PASSWORD] [--postgres-database POSTGRES_DATABASE] [--bigquery-project-id BIGQUERY_PROJECT_ID] @@ -340,6 +347,8 @@ positional arguments: options: -h, --help show this help message and exit + --config-file CONFIG_FILE + Otava config file path [env var: OTAVA_CONFIG] Graphite Options: Options for Graphite configuration @@ -401,10 +410,11 @@ def test_otava_list_metrics_help_output(): assert ( result.stdout == """\ -usage: otava list-metrics [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL] - [--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD] - [--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME] - [--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME] +usage: otava list-metrics [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL] + [--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER] + [--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN] + [--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT] + [--postgres-username POSTGRES_USERNAME] [--postgres-password POSTGRES_PASSWORD] [--postgres-database POSTGRES_DATABASE] [--bigquery-project-id BIGQUERY_PROJECT_ID] @@ -417,6 +427,8 @@ positional arguments: options: -h, --help show this help message and exit + --config-file CONFIG_FILE + Otava config file path [env var: OTAVA_CONFIG] Graphite Options: Options for Graphite configuration @@ -479,10 +491,11 @@ def test_otava_list_groups_help_output(): assert ( result.stdout == """\ -usage: otava list-groups [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL] - [--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD] - [--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME] - [--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME] +usage: otava list-groups [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL] + [--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER] + [--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN] + [--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT] + [--postgres-username POSTGRES_USERNAME] [--postgres-password POSTGRES_PASSWORD] [--postgres-database POSTGRES_DATABASE] [--bigquery-project-id BIGQUERY_PROJECT_ID] @@ -491,6 +504,8 @@ usage: otava list-groups [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFA options: -h, --help show this help message and exit + --config-file CONFIG_FILE + Otava config file path [env var: OTAVA_CONFIG] Graphite Options: Options for Graphite configuration @@ -552,8 +567,8 @@ def test_otava_remove_annotations_help_output(): assert ( result.stdout == """\ -usage: otava remove-annotations [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL] - [--grafana-user GRAFANA_USER] +usage: otava remove-annotations [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL] + [--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT] @@ -570,6 +585,8 @@ positional arguments: options: -h, --help show this help message and exit + --config-file CONFIG_FILE + Otava config file path [env var: OTAVA_CONFIG] --force don't ask questions, just do it Graphite Options: @@ -632,10 +649,11 @@ def test_otava_validate_help_output(): assert ( result.stdout == """\ -usage: otava validate [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL] - [--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD] - [--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME] - [--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME] +usage: otava validate [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL] + [--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER] + [--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN] + [--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT] + [--postgres-username POSTGRES_USERNAME] [--postgres-password POSTGRES_PASSWORD] [--postgres-database POSTGRES_DATABASE] [--bigquery-project-id BIGQUERY_PROJECT_ID] @@ -644,6 +662,8 @@ usage: otava validate [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_ options: -h, --help show this help message and exit + --config-file CONFIG_FILE + Otava config file path [env var: OTAVA_CONFIG] Graphite Options: Options for Graphite configuration
