# 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/*.yml 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/*.yml; 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/*.yml'):
              contract = yaml.safe_load(open(contract_file))
              jsonschema.validate(contract, schema)
              print(f'{contract_file}: valid contract')
          "