GitHub Actions Integration
This page provides a GitHub Actions workflow for validating the AMP project structure and optionally running a model smoke test in CI.
Validation Workflow
name: Validate AMP
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install validation dependencies
run: pip install pyyaml
- name: Run structural validation
run: python scripts/validate_amp.py
smoke-test:
runs-on: ubuntu-latest
if: hashFiles('model/best-xgboost-model') != ''
needs: validate
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install dependencies
run: |
pip install numpy xgboost
- name: Run model smoke test
run: |
python -c "
import numpy as np
import xgboost as xgb
booster = xgb.Booster(model_file='model/best-xgboost-model')
sample = np.array([[-1.35980713, -0.0727811733, 2.53634674, 1.37815522,
-0.33832077, 0.462387778, 0.239598554, 0.0986979013,
0.36378697, 0.090794172, -0.551599533, -0.617800856,
-0.991389847, -0.311169354, 1.46817697, -0.470400525,
0.207971242, 0.0257905802, 0.40399296, 0.251412098,
-0.0183067779, 0.277837576, -0.11047391, 0.0669280749,
0.128539358, -0.189114844, 0.133558377, -0.0210530535,
149.62]])
prediction = booster.inplace_predict(sample)
assert 0.0 <= prediction[0] <= 1.0, f'Out of range: {prediction[0]}'
binary = 0 if prediction[0] <= 0.35 else 1
assert binary in (0, 1), f'Unexpected output: {binary}'
print(f'Prediction: {prediction[0]:.4f} -> {binary}')
print('Smoke test passed.')
"
Workflow Details
validate job
Runs on every push and pull request to master. Requires only pyyaml (no heavy ML dependencies). Executes a validation script that checks:
- Repository structure (S-rules)
- AMP configuration (A-rules)
- Dependency manifest (D-rules)
- Endpoint contract via AST parsing (E-rules)
- Cluster utility structure (C-rules)
smoke-test job
Runs only when the trained model file exists in the repository (model/best-xgboost-model). Installs numpy and xgboost, loads the model, runs a sample prediction, and asserts the output is valid.
This job is conditional — it will be skipped if the model has not been committed (e.g., during initial development before training).
Setting Up the Validation Script
The workflow assumes scripts/validate_amp.py exists. Create this file using the SDK code from Building a Validation SDK:
# scripts/validate_amp.py
# Paste the ValidationResult, ValidationIssue, Severity classes
# and all validate_* functions from the SDK guide,
# then add the __main__ block:
if __name__ == "__main__":
result = validate(".")
for issue in result.issues:
print(f"[{issue.severity.value.upper()}] {issue.rule}: {issue.message}")
if not result.passed:
raise SystemExit(1)
print("All validation checks passed.")
Extending the Workflow
To add custom validation rules:
- Define a new rule ID (e.g.,
X-001) and severity in the Validation Rules Reference. - Add a
validate_custom()function to the SDK. - Call it from the
validate()entry point.
To validate dependency versions (not just presence):
import re
def validate_pinned_versions(root, result):
content = (root / "requirements.txt").read_text()
for line in content.strip().splitlines():
line = line.strip()
if line and not line.startswith("#") and not line.startswith("-"):
if "==" not in line:
result.issues.append(ValidationIssue(
rule="D-W01", severity=Severity.WARNING,
message=f"Package not pinned: {line}",
path="requirements.txt",
))