Some checks failed
Architecture Lint / Linter Tests (pull_request) Successful in 36s
Smoke Test / smoke (pull_request) Failing after 20s
Validate Config / YAML Lint (pull_request) Failing after 16s
Validate Config / JSON Validate (pull_request) Successful in 10s
Validate Config / Python Syntax & Import Check (pull_request) Failing after 1m15s
PR Checklist / pr-checklist (pull_request) Failing after 8m16s
Validate Config / Shell Script Lint (pull_request) Failing after 1m9s
Validate Config / Cron Syntax Check (pull_request) Successful in 18s
Validate Config / Deploy Script Dry Run (pull_request) Successful in 17s
Validate Config / Playbook Schema Validation (pull_request) Successful in 32s
Architecture Lint / Lint Repository (pull_request) Has been cancelled
Validate Config / Python Test Suite (pull_request) Has been cancelled
143 lines
4.5 KiB
Python
143 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Tests for deploy_config_validator.py"""
|
|
|
|
import json
|
|
import sys
|
|
import os
|
|
import pytest
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
|
from scripts.deploy_config_validator import (
|
|
validate_yaml_syntax,
|
|
validate_required_keys,
|
|
validate_provider_chain,
|
|
validate_value_types,
|
|
validate_config,
|
|
detect_config_type,
|
|
ValidationError,
|
|
)
|
|
|
|
|
|
class TestYAMLSyntax:
|
|
def test_valid_yaml(self):
|
|
data, errors = validate_yaml_syntax("key: value\nlist:\n - a\n - b\n")
|
|
assert data is not None
|
|
assert len(errors) == 0
|
|
|
|
def test_invalid_yaml(self):
|
|
data, errors = validate_yaml_syntax("key: [unclosed")
|
|
assert data is None
|
|
assert len(errors) > 0
|
|
|
|
def test_empty_yaml(self):
|
|
data, errors = validate_yaml_syntax("")
|
|
assert data is None
|
|
assert any("empty" in e.message for e in errors)
|
|
|
|
def test_tabs_warning(self):
|
|
data, errors = validate_yaml_syntax("key:\tvalue\n")
|
|
assert any("tab" in e.message for e in errors)
|
|
|
|
|
|
class TestRequiredKeys:
|
|
def test_missing_key(self):
|
|
errors = validate_required_keys({}, "hermes")
|
|
assert any("providers" in e.message for e in errors)
|
|
|
|
def test_wrong_type(self):
|
|
errors = validate_required_keys({"providers": "not-a-list"}, "hermes")
|
|
assert any("expected list" in e.message for e in errors)
|
|
|
|
def test_valid(self):
|
|
errors = validate_required_keys({"providers": []}, "hermes")
|
|
provider_errors = [e for e in errors if "providers" in e.message and "missing" in e.message]
|
|
assert len(provider_errors) == 0
|
|
|
|
|
|
class TestProviderChain:
|
|
def test_empty_providers(self):
|
|
errors = validate_provider_chain({"providers": []})
|
|
assert any("empty" in e.message for e in errors)
|
|
|
|
def test_missing_name(self):
|
|
errors = validate_provider_chain({"providers": [{"model": "test", "base_url": "http://x"}]})
|
|
assert any("name" in e.message and "missing" in e.message for e in errors)
|
|
|
|
def test_banned_provider(self):
|
|
errors = validate_provider_chain({"providers": [
|
|
{"name": "anthropic", "model": "claude-3", "base_url": "http://x"}
|
|
]})
|
|
assert any("banned provider" in e.message for e in errors)
|
|
|
|
def test_banned_model(self):
|
|
errors = validate_provider_chain({"providers": [
|
|
{"name": "test", "model": "claude-sonnet-4", "base_url": "http://x"}
|
|
]})
|
|
assert any("banned model" in e.message for e in errors)
|
|
|
|
def test_valid_providers(self):
|
|
errors = validate_provider_chain({"providers": [
|
|
{"name": "kimi-coding", "model": "kimi-k2.5", "base_url": "https://api.kimi.com/v1"}
|
|
]})
|
|
provider_errors = [e for e in errors if e.severity == "error"]
|
|
assert len(provider_errors) == 0
|
|
|
|
|
|
class TestValueTypes:
|
|
def test_string_port(self):
|
|
errors = validate_value_types({"port": "8080"})
|
|
assert any("port" in e.path and "number" in e.message for e in errors)
|
|
|
|
def test_valid_port(self):
|
|
errors = validate_value_types({"port": 8080})
|
|
port_errors = [e for e in errors if "port" in e.path]
|
|
assert len(port_errors) == 0
|
|
|
|
def test_bad_url(self):
|
|
errors = validate_value_types({"base_url": "not-a-url"})
|
|
assert any("URL" in e.message for e in errors)
|
|
|
|
|
|
class TestDetectConfigType:
|
|
def test_hermes(self):
|
|
t = detect_config_type({"providers": [], "display": {}})
|
|
assert t == "hermes"
|
|
|
|
def test_ansible(self):
|
|
t = detect_config_type({"all": {"children": {"wizards": {}}}})
|
|
assert t == "ansible_inventory"
|
|
|
|
def test_unknown(self):
|
|
t = detect_config_type({"random": "data"})
|
|
assert t == "any"
|
|
|
|
|
|
class TestFullValidation:
|
|
def test_valid_hermes_config(self):
|
|
text = """
|
|
providers:
|
|
- name: kimi-coding
|
|
model: kimi-k2.5
|
|
base_url: https://api.kimi.com/coding/v1
|
|
timeout: 120
|
|
display:
|
|
skin: default
|
|
"""
|
|
errors = validate_config(text, "hermes")
|
|
assert not any(e.severity == "error" for e in errors)
|
|
|
|
def test_banned_provider_catches(self):
|
|
text = """
|
|
providers:
|
|
- name: anthropic
|
|
model: claude-sonnet-4
|
|
base_url: https://api.anthropic.com
|
|
"""
|
|
errors = validate_config(text, "hermes")
|
|
assert any("banned" in e.message for e in errors)
|
|
|
|
def test_missing_providers(self):
|
|
text = "display:\n skin: default\n"
|
|
errors = validate_config(text, "hermes")
|
|
assert any("providers" in e.message and "missing" in e.message for e in errors)
|