# ACDL Platform Test Pipeline — GitHub Actions (production) # # Runs on PRs to main. Replaces ci.yml for PRs (ci.yml stays for push-to-main). # Four stages: lint, unit-test, integration-test, schema-validation. # # Shell reproducibility: scripts/run_ci.sh runs lint + test + check-only locally. # The integration-test stage runs run_platform.sh --check-only for every # contracts/*.yaml file. The schema-validation stage validates schemas, module # interfaces, compositions, and example contracts. name: acdl-platform-test on: pull_request: branches: [main] jobs: lint: name: Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Compile all Python files run: | python3 -m py_compile \ core/confidence_signal.py \ core/outbox_writer.py \ core/contract_resolver.py \ core/environment_check.py \ core/output_publisher.py \ core/lambda/contract_ingestor.py \ adapters/terraform/adapter.py \ adapters/terraform/policy/checkov_adapter.py \ adapters/wiz/wiz_adapter.py \ adapters/kyverno/kyverno_adapter.py \ scripts/push_consumer_image.py unit-test: name: Unit tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install test dependencies run: pip install -r requirements-test.txt - name: Run pytest run: python3 -m pytest tests/ -v --tb=short integration-test: name: Integration test (all sample contracts) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install runtime dependencies run: pip install jsonschema pyyaml boto3 - name: Run platform check-only for every sample contract run: | for contract in contracts/*.yaml; do echo "--- Testing $contract ---" bash scripts/run_platform.sh --check-only "$contract" done schema-validation: name: Schema + module validation runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install dependencies run: pip install jsonschema pyyaml - name: Validate all schemas run: | python3 -c " import json, glob, jsonschema for schema_file in glob.glob('schemas/*.json'): if 'contract.schema' in schema_file: continue # has no self-validation schema = json.load(open(schema_file)) # self-validate if it has a \$id try: jsonschema.Draft202012Validator.check_schema(schema) except jsonschema.SchemaError as e: raise SystemExit(f'{schema_file}: {e}') print(f'{schema_file}: valid') " - name: Validate all module interfaces against stack.schema.json run: | python3 -c " import json, glob, jsonschema, os stack_schema = json.load(open('schemas/stack.schema.json')) for iface_file in glob.glob('modules/l1/*/interface.json'): try: iface = json.load(open(iface_file)) # Validate basic structure (name, version, kind, type, inputs, outputs) assert 'name' in iface, f'{iface_file}: missing name' assert 'version' in iface, f'{iface_file}: missing version' assert 'kind' in iface, f'{iface_file}: missing kind' assert iface['kind'] == 'l1', f'{iface_file}: expected kind=l1' assert 'type' in iface, f'{iface_file}: missing type' assert 'inputs' in iface, f'{iface_file}: missing inputs' assert 'outputs' in iface, f'{iface_file}: missing outputs' print(f'{iface_file}: valid L1') except Exception as e: raise SystemExit(f'{iface_file}: {e}') for comp_file in glob.glob('modules/l2/*/composition.json'): try: comp = json.load(open(comp_file)) assert 'name' in comp, f'{comp_file}: missing name' assert 'version' in comp, f'{comp_file}: missing version' assert 'kind' in comp, f'{comp_file}: missing kind' assert comp['kind'] == 'l2', f'{comp_file}: expected kind=l2' assert 'children' in comp, f'{comp_file}: missing children' assert 'wires' in comp, f'{comp_file}: missing wires' assert 'outputs' in comp, f'{comp_file}: missing outputs' print(f'{comp_file}: valid L2') except Exception as e: raise SystemExit(f'{comp_file}: {e}') " - name: Validate module example contracts run: | python3 -c " import json, yaml, glob, jsonschema schema = json.load(open('schemas/contract.schema.json')) # Validate example contracts if they exist for example in glob.glob('modules/*/*/examples/*.yaml'): try: contract = yaml.safe_load(open(example)) jsonschema.validate(contract, schema) print(f'{example}: valid contract') except Exception as e: print(f'{example}: SKIP (not a contract or invalid: {e})') # Also validate all sample contracts in contracts/ for contract_file in glob.glob('contracts/*.yaml'): contract = yaml.safe_load(open(contract_file)) jsonschema.validate(contract, schema) print(f'{contract_file}: valid contract') "