This directory contains CI workflows and scripts to validate greffon catalog entries, both automatically on PRs and manually before submitting.
Every pull request to main triggers the Validate Greffon Catalog workflow with two jobs:
Runs on every PR. Checks all greffons in the catalog for:
- File structure: each
{name}/{version}/dir must containmetadata.jsonanddocker-compose.yml(plus optionalsmoke_test.json) - Compose validity: valid YAML, non-empty
services, no hardcodedcontainer_name - Metadata schema: required fields (
name,description,configurations), correct types - Configuration destinations: valid
type(env/json/file), required keys per type - Cross-references:
envdestinations reference services that exist in the compose file;json/filedestinations reference volumes that exist in the compose file
Only runs when greffon files actually changed. For each changed greffon:
- Spins up the manager (Django with SQLite + mocked Vault) and a real greffer
- Imports the greffon into the catalog database
- Creates an instance (with
required_configfromsmoke_test.jsonif needed) and starts it on the greffer - Polls until the instance reaches STARTED status (120s timeout)
- Smoke test: if
smoke_test.jsonexists, hits the greffon's HTTP endpoint and verifies it responds correctly (expected status code, expected body content) - Stops the instance and moves to the next greffon
If any greffon fails to start or fails its smoke test, the workflow fails with a detailed error message.
Optional file that defines how to verify a greffon actually works after deployment:
{
"path": "/status.php",
"expected_status": [200],
"expected_body_contains": "installed",
"required_config": {
"BASE_URL": "http://localhost:8000"
}
}| Field | Required | Description |
|---|---|---|
path |
Yes | HTTP path to hit (e.g. /, /api/v1/ping) |
expected_status |
Yes | List of acceptable HTTP status codes |
expected_body_contains |
No | String to search for in the response body (case-insensitive), null to skip |
required_config |
No | Config values needed for the greffon to start (key = config title, value = config value) |
- Static validation failures: look for
ERROR:lines with the specific check that failed (e.g.,missing required file,references container 'foo' not found in services) - Integration test failures: look for
FAIL:lines. Common causes:- Image pull timeout (increase timeout or use smaller images)
- Compose syntax issues that YAML parsing doesn't catch (e.g., invalid
depends_on) - Services that crash on startup (check container logs in the workflow output)
Run these checks locally before submitting a PR to catch issues early.
# Validate your specific greffon
python .github/scripts/validate_catalog.py --dir mygreffon/1.0
# Or validate everything
python .github/scripts/validate_catalog.py --allRequires Python 3.9+ and pyyaml:
pip install pyyamlVerify your services start without errors:
docker compose -f mygreffon/1.0/docker-compose.yml upCheck that:
- All services start without crashing
- No missing images or build errors
- Services can communicate with each other
At least one service must expose a port. The greffer reads these ports to set up the nginx reverse proxy:
services:
myapp:
image: myapp:latest
ports:
- "8080:80" # Required: greffer uses thisFor each entry in metadata.json configurations:
envdestinations: thecontainerfield must match a service name indocker-compose.ymljson/filedestinations: thevolumefield must match a top-level volume name indocker-compose.ymlschemashould be valid JSON Schema (the manager-front uses RJSF to render forms from it)default_valueshould match the schema structure
For the most thorough validation, test with the full greffon platform:
# From the main greffon repo
./scripts/setup-dev.sh
# Your greffon will be imported automatically if it's in the catalog
# Then test it via the UI at https://app.greffon.localCopy this into your PR description:
### Greffon Validation Checklist
- [ ] `metadata.json` and `docker-compose.yml` present in `{name}/{version}/`
- [ ] `docker compose up` starts without errors
- [ ] Configuration destinations reference valid services/volumes
- [ ] No hardcoded `container_name` in compose
- [ ] Named volumes used (not bind mounts)
- [ ] At least one service exposes a port
- [ ] `smoke_test.json` added with path, expected status, and body check
- [ ] `python .github/scripts/validate_catalog.py --dir {name}/{version}` passesEach greffon version directory contains:
mygreffon/1.0/
docker-compose.yml # What to deploy (services, ports, volumes)
metadata.json # Catalog entry (name, logo, configs for the UI)
smoke_test.json # How to verify it works (HTTP check for CI)
| Script | Purpose |
|---|---|
scripts/validate_catalog.py |
Static validation of metadata + compose + smoke_test |
scripts/ci_greffer_smoke.py |
Integration test: deploy each greffon through the public greffer (no manager/PAT) and run its Playwright smoke spec |