Skip to content

Commit

Permalink
Add a validate-only flag to support web-init/CI usage
Browse files Browse the repository at this point in the history
  • Loading branch information
swrichards committed Dec 19, 2024
1 parent bad0d33 commit 438789f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,18 @@ Command Line
python manage.py setup_configuration --yaml-file /path/to/config.yaml
You can also validate that the configuration source can be successfully loaded,
without actually running the steps, by adding the ``validate-only`` flag:

.. code-block:: bash
python manage.py setup_configuration --yaml-file /path/to/config.yaml --validate-only
The command will either return 0 and a success message if the configuration file can
be loaded without issues, otherwise it will return a non-zero exit code and print any
validation errors. This can be useful e.g. in CI to confirm that your sources are
valid without actually running any steps.

Programmatically
^^^^^^^^^^^^^^^^

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,17 @@ def add_arguments(self, parser):
required=True,
help="Path to YAML file containing the configurations",
)
parser.add_argument(
"--validate-only",
action="store_true",
default=False,
help="Validate that all the step configurations can be successfully loaded "
"from source, without actually executing the steps.",
)

@transaction.atomic
def handle(self, **options):
validate_only = options["validate_only"]
yaml_file = Path(options["yaml_file"]).resolve()
if not yaml_file.exists():
raise CommandError(f"Yaml file `{yaml_file}` does not exist.")
Expand Down Expand Up @@ -74,6 +82,14 @@ def handle(self, **options):
f"Prerequisites for configuration are not fulfilled: {errors.as_text()}"
)

if validate_only:
self.stdout.write(
self.style.SUCCESS(
"All configuration values could be successfully read from source."
)
)
return

self.stdout.write("Executing steps...")

# 2. Configure steps
Expand Down
69 changes: 69 additions & 0 deletions tests/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,40 @@ def test_command_success(
step_execute_mock.assert_called_once_with(expected_step_config)


def test_command_success_with_validate_only_flag_does_not_run(
settings,
yaml_file_with_valid_configuration,
expected_step_config,
step_execute_mock,
):
"""
test happy flow
"""
assert User.objects.count() == 0
stdout = StringIO()

call_command(
"setup_configuration",
yaml_file=yaml_file_with_valid_configuration,
stdout=stdout,
validate_only=True,
)

output = stdout.getvalue().splitlines()
expected_output = [
f"Loading config settings from {yaml_file_with_valid_configuration}",
"The following steps are configured:",
"User Configuration",
"TestStep",
"All configuration values could be successfully read from source.",
]

assert output == expected_output

assert User.objects.count() == 0
step_execute_mock.assert_not_called()


def test_command_with_failing_requirements_reports_errors(
step_execute_mock, yaml_file_factory
):
Expand Down Expand Up @@ -181,6 +215,41 @@ def test_command_with_failing_requirements_reports_errors(
step_execute_mock.assert_not_called()


def test_command_with_failing_requirements_and_validate_reports_errors(
step_execute_mock, yaml_file_factory
):
yaml_path = yaml_file_factory(
{
"user_configuration_enabled": True,
"user_configuration": {
"username": 1874,
},
"some_extra_attrs": "should be allowed",
"test_step_is_enabled": True,
"test_step": {
"a_string": 42,
"username": None,
},
}
)

with pytest.raises(CommandError) as exc:
call_command(
"setup_configuration",
yaml_file=yaml_path,
validate_only=False,
)

assert (
"User Configuration: Failed to load config model for User Configuration"
in str(exc.value)
)
assert "Failed to load config model for TestStep" in str(exc.value)

assert User.objects.count() == 0
step_execute_mock.assert_not_called()


def test_command_with_failing_execute_reports_errors(
expected_step_config, step_execute_mock, yaml_file_with_valid_configuration
):
Expand Down

0 comments on commit 438789f

Please sign in to comment.