Skip to content

Commit 11e4f15

Browse files
committed
feat(cli): Enhance 'validate' command with verbose output
Adds a --verbose (-v) flag to the `validate` command. When enabled, the command now provides a detailed, step-by-step log of each validation check being performed. This improves the debugging experience by making it clear which checks are passing, failing, or being skipped, rather than only showing a final error summary.
1 parent 618c335 commit 11e4f15

1 file changed

Lines changed: 66 additions & 18 deletions

File tree

src/envars/cli.py

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -697,60 +697,108 @@ def validate_command(
697697
):
698698
"""Validates the envars.yml file for logical consistency."""
699699
manager = ctx.obj
700+
verbose = ctx.meta.get("verbose", False)
700701
errors = []
701702

702-
# Check that all variable values correspond to a defined variable
703+
if verbose:
704+
console.print("[dim]DEBUG: Running validation checks...[/dim]")
705+
706+
# Check 1: All variable values correspond to a defined variable
707+
value_errors = []
703708
defined_variable_names = set(manager.variables.keys())
704709
for vv in manager.variable_values:
705710
if vv.variable_name not in defined_variable_names:
706-
errors.append(f"Variable '{vv.variable_name}' has values but is not defined as a top-level variable.")
711+
value_errors.append(f"Variable '{vv.variable_name}' has values but is not defined as a top-level variable.")
712+
if not value_errors:
713+
if verbose:
714+
console.print("[dim]DEBUG: [PASS] All variable values have a corresponding definition.[/dim]")
715+
else:
716+
errors.extend(value_errors)
707717

708-
# Check that all variable names are uppercase
718+
# Check 2: All variable names are uppercase
719+
case_errors = []
709720
for var_name in manager.variables:
710721
if var_name.upper() != var_name:
711-
errors.append(f"Variable name '{var_name}' must be uppercase.")
722+
case_errors.append(f"Variable name '{var_name}' must be uppercase.")
723+
if not case_errors:
724+
if verbose:
725+
console.print("[dim]DEBUG: [PASS] All variable names are uppercase.[/dim]")
726+
else:
727+
errors.extend(case_errors)
712728

713-
# Check for missing descriptions if mandatory
729+
# Check 3: Missing descriptions if mandatory
714730
if manager.description_mandatory:
731+
desc_errors = []
715732
for var_name, var in manager.variables.items():
716733
if not var.description:
717-
errors.append(f"Variable '{var_name}' is missing a description.")
734+
desc_errors.append(f"Variable '{var_name}' is missing a description.")
735+
if not desc_errors:
736+
if verbose:
737+
console.print("[dim]DEBUG: [PASS] All mandatory descriptions are present.[/dim]")
738+
else:
739+
errors.extend(desc_errors)
740+
elif verbose:
741+
console.print("[dim]DEBUG: [SKIP] Description mandatory check is disabled.[/dim]")
718742

719-
# Check for default secrets
743+
# Check 4: Default secrets
720744
if not ignore_default_secrets:
745+
secret_errors = []
721746
for vv in manager.variable_values:
722747
if isinstance(vv.value, Secret) and vv.scope_type == "DEFAULT":
723-
errors.append(f"Variable '{vv.variable_name}' is a secret and cannot have a default value.")
748+
secret_errors.append(f"Variable '{vv.variable_name}' is a secret and cannot have a default value.")
749+
if not secret_errors:
750+
if verbose:
751+
console.print("[dim]DEBUG: [PASS] No default secrets found.[/dim]")
752+
else:
753+
errors.extend(secret_errors)
754+
elif verbose:
755+
console.print("[dim]DEBUG: [SKIP] Default secret check is ignored.[/dim]")
724756

725-
# Check for mismatched remote variables
757+
# Check 5: Mismatched remote variables
726758
if manager.cloud_provider:
759+
remote_errors = []
727760
for vv in manager.variable_values:
728761
if isinstance(vv.value, str):
729762
if manager.cloud_provider == "aws" and vv.value.startswith("gcp_secret_manager:"):
730-
errors.append(f"Variable '{vv.variable_name}' uses 'gcp_secret_manager:' with an AWS KMS key.")
763+
remote_errors.append(
764+
f"Variable '{vv.variable_name}' uses 'gcp_secret_manager:' with an AWS KMS key."
765+
)
731766
if manager.cloud_provider == "gcp" and (
732767
vv.value.startswith("parameter_store:") or vv.value.startswith("cloudformation_export:")
733768
):
734-
errors.append(
769+
remote_errors.append(
735770
f"Variable '{vv.variable_name}' uses 'parameter_store:' or 'cloudformation_export:' with a GCP"
736771
" KMS key."
737772
)
773+
if not remote_errors:
774+
if verbose:
775+
console.print("[dim]DEBUG: [PASS] No mismatched remote variables found.[/dim]")
776+
else:
777+
errors.extend(remote_errors)
778+
elif verbose:
779+
console.print("[dim]DEBUG: [SKIP] Remote variable check (no cloud provider configured).[/dim]")
738780

739-
# Check for circular dependencies
740-
all_vars = {}
741-
for vv in manager.variable_values:
742-
all_vars[vv.variable_name] = vv.value
781+
# Check 6: Circular dependencies
782+
all_vars = {vv.variable_name: vv.value for vv in manager.variable_values}
743783
try:
744784
_check_for_circular_dependencies(all_vars)
785+
if verbose:
786+
console.print("[dim]DEBUG: [PASS] No circular dependencies detected.[/dim]")
745787
except ValueError as e:
746788
errors.append(str(e))
747789

748-
# Check that all variable values match their validation rules
790+
# Check 7: All variable values match their validation rules
791+
validation_errors = []
749792
for vv in manager.variable_values:
750793
try:
751794
_validate_variable_value(manager, vv.variable_name, str(vv.value))
752795
except ValueError as e:
753-
errors.append(str(e))
796+
validation_errors.append(str(e))
797+
if not validation_errors:
798+
if verbose:
799+
console.print("[dim]DEBUG: [PASS] All variable values passed validation rules.[/dim]")
800+
else:
801+
errors.extend(validation_errors)
754802

755803
if errors:
756804
error_console.print("[bold red]Validation failed with the following errors:[/]")
@@ -762,4 +810,4 @@ def validate_command(
762810

763811

764812
if __name__ == "__main__":
765-
app()
813+
app()

0 commit comments

Comments
 (0)