Integration structure and configuration validator.
Requires: Python 3.13+
This script validates that integration directories follow the required folder structure, naming conventions, and configuration schema. It checks for required files, validates config.json structure and content, verifies auth configuration, inspects action definitions, and detects potentially unused OAuth scopes.
This is the most comprehensive validation tool in the tooling suite, covering structural and configuration correctness rather than code quality (which is handled by check_code.py).
# Validate specific integrations
python scripts/validate_integration.py <dir> [dir ...]
# Validate all integrations (auto-discovers integration folders at repo root)
python scripts/validate_integration.py| Argument | Required | Description |
|---|---|---|
dir |
No | One or more integration directories to validate. If omitted, auto-discovers all integration folders at the repository root. |
| Code | Meaning |
|---|---|
0 |
All validations passed (possibly with warnings) |
1 |
One or more validation errors found |
2 |
An error occurred (folder not found, missing arguments) |
# Validate a single integration
python scripts/validate_integration.py my-integration
# Validate multiple integrations
python scripts/validate_integration.py my-integration another-api
# Validate all integrations in the repo
python scripts/validate_integration.py
# Combine with get_changed_dirs.py
python scripts/validate_integration.py $(python scripts/get_changed_dirs.py origin/main)The validator runs 8 checks in sequence for each integration directory:
| Check | Severity | Description |
|---|---|---|
| Lowercase | Error | Folder name must be all lowercase |
| No spaces | Error | Folder name cannot contain spaces |
| Valid characters | Warning | Should only contain a-z, 0-9, and - |
✅ my-integration (correct)
✅ shopify-admin (correct)
❌ My-Integration (uppercase)
❌ my integration (spaces)
⚠️ my_integration (underscores - warning only)
Checks that all mandatory files exist in the integration directory:
| File | Severity | Description |
|---|---|---|
config.json |
Error | Integration configuration |
requirements.txt |
Error | Python dependencies |
README.md |
Error | Integration documentation |
icon.png or icon.svg |
Error | Integration icon — must be exactly 512x512 pixels |
__init__.py |
Warning | Python package init — optional for modular integrations with an actions/ subdirectory (adding it causes circular imports) |
| Field | Type | Description |
|---|---|---|
name |
string | Integration identifier |
version |
string | Semantic version format (x.y.z) |
description |
string | Clear description of the integration |
entry_point |
string | Main Python file (must exist on disk) |
actions |
object | At least one action must be defined |
| Check | Severity | Description |
|---|---|---|
display_name present and non-empty |
Warning | Human-readable name for the integration |
Validates based on auth.type:
| Auth Type | Required Fields | Description |
|---|---|---|
platform |
provider, scopes (array) |
OAuth2-based authentication |
custom |
fields.properties |
API key or token-based authentication |
| (omitted) | — | No authentication (public APIs) |
For each action defined in config.json:
| Check | Severity | Description |
|---|---|---|
| Action key is lowercase | Warning | Should be snake_case |
display_name present |
Warning | Human-readable name |
description present |
Warning | What the action does |
input_schema present |
Warning | JSON Schema for input |
output_schema present |
Warning | JSON Schema for output |
Verifies that __init__.py contains only import and __all__ statements:
# ✅ Correct
from .my_integration import my_integration
__all__ = ["my_integration"]
# ❌ Too much code
from .my_integration import my_integration
import logging
logger = logging.getLogger(__name__)
__all__ = ["my_integration"]Allowed patterns:
from .module import name__all__ = [...]
| Check | Severity | Description |
|---|---|---|
autohive-integrations-sdk present |
Error | SDK dependency is mandatory |
| Version pinned and not deprecated | Warning | Should pin SDK version (e.g., ~=2.0.0); deprecated versions warn |
| Check | Severity | Description |
|---|---|---|
tests/ directory exists |
Error | Test directory required |
tests/__init__.py exists |
Error | Test package init |
tests/context.py or tests/conftest.py exists |
Error | Test import/fixture setup (either one satisfies this check) |
tests/test_*.py exists |
Error | At least one test file |
Inspects all .py files in the integration directory (not just the entry point) for expected patterns. This supports modular integrations where action handlers are split across multiple files.
| Check | Severity | Description |
|---|---|---|
Integration imported |
Warning | Should import from SDK |
ActionHandler imported |
Warning | Should import from SDK |
Integration.load() called |
Warning | Standard loading pattern |
Note: Action decorator matching (config ↔ code) is handled by
check_config_sync.py, which uses AST parsing for more accurate bidirectional validation.
For integrations using platform (OAuth2) authentication, the validator uses a heuristic to detect scopes that may not be needed:
- Extract keywords from each scope (e.g.,
read:sites→["read", "sites"]) - Collect text from all action names, descriptions, and display names
- Check if meaningful keywords (length > 3, not generic like
read/write) appear in action text - Report scopes with no keyword matches as potentially unused
This is a heuristic check and may produce false positives — the warning asks the developer to verify manually.
flowchart TD
A[Parse arguments or auto-discover folders] --> B{For each integration folder}
B --> C[Check folder name]
C --> D[Check required files]
D --> E[Validate config.json]
E --> F[Check __init__.py minimality]
F --> G[Check requirements.txt]
G --> H[Check tests/ folder]
H --> I[Check main Python file]
I --> J[Check for unused scopes]
J --> K[Print results]
K --> B
B --> L[Print summary]
L --> M{Any errors?}
M -->|Yes| N[Exit 1]
M -->|No| O[Exit 0]
When no arguments are provided, the script auto-discovers integration folders at the repository root by:
- Iterating all directories in the repository root
- Skipping known infrastructure directories (
.github,.git,scripts,tests,template-structure,__pycache__,.vscode,.idea,node_modules) - Skipping hidden directories (starting with
.) - Including directories that contain
config.jsonor any.pyfile
============================================================
Integration: my-integration
============================================================
Errors (2):
❌ Missing required file: icon.png or icon.svg (Integration icon)
❌ requirements.txt must include 'autohive-integrations-sdk'
Warnings (1):
⚠️ Version should follow semantic versioning (x.y.z): '1.0'
============================================================
SUMMARY
============================================================
Integrations validated: 3
Total errors: 2
Total warnings: 1
❌ Validation FAILED - please fix errors before submitting PR
| Severity | Effect | When Used |
|---|---|---|
| Error | Fails validation (exit 1) | Missing required files, invalid config structure, missing SDK dependency |
| Warning | Passes validation (exit 0) | Style issues, missing optional fields, potential unused scopes |
Called by the validate-integration.yml workflow (on pull requests) as the Structure Check step:
- name: Structure Check
if: steps.changed.outputs.dirs != ''
run: python scripts/validate_integration.py ${{ steps.changed.outputs.dirs }}The script is also exercised by the self-test.yml workflow, which runs it against the test examples in tests/examples/ as a regression guard whenever scripts/ or tests/ change.