- CONTRIBUTING.md GSD-Task: S04/T01
11 KiB
Contributing to the Arcane Template Registry
Thank you for contributing! This registry is a curated collection of Docker Compose templates for Arcane. Template folders are the single source of truth — CI validates their structure, assembles registry.json from on-disk state, and publishes it to GitHub Pages.
Repository Overview
arcane-repo/
├── templates/ # One directory per template
│ ├── litellm/ # Example: LiteLLM proxy template
│ │ ├── arcane.json # Metadata (id, name, version, author, tags)
│ │ ├── docker-compose.yml # Compose service definition
│ │ ├── .env.example # Documented env var reference
│ │ └── README.md # Template documentation
│ └── ...
├── scripts/
│ └── build-registry.js # Validates and assembles registry.json
├── schema.json # JSON Schema for validation
├── .github/workflows/
│ ├── validate.yml # Runs on PRs touching templates/**
│ └── deploy.yml # Runs on push to main, publishes to Pages
└── README.md
Adding a New Template
1. Fork and Branch
Fork the repository, clone your fork, and create a feature branch:
git checkout -b add-<template-name>
2. Create the Template Directory
mkdir templates/<template-name>/
Replace <template-name> with a lowercase slug using hyphens only (e.g., my-app, custom-service). This name becomes the template id and must match the folder name exactly.
3. Write the Four Required Files
arcane.json
Template metadata file. The id field must match the folder name, version must be valid semver, and tags must be a non-empty array of unique strings.
{
"id": "my-app",
"name": "My App",
"description": "A clear description of what the template provides and its use case",
"version": "1.0.0",
"author": "Your Name or Organization",
"tags": ["category1", "category2"]
}
Conventions:
id— lowercase slug with hyphens only, must match folder nameversion— valid semver string (e.g.,1.0.0,1.2.3-beta.1)tags— non-empty array of unique strings; use descriptive categories likeai,llm,automation,workflow,low-code,database,monitoring- You do not need to include
compose_url,env_url,documentation_url, orcontent_hash— those are auto-generated by the CI build script - Do not include
$schemain template-levelarcane.json
docker-compose.yml
A valid Docker Compose file (version 3.8 or later). Follow these conventions:
version: '3.8'
services:
my-service:
image: ghcr.io/org/image:tag
container_name: my-service
hostname: my-service
ports:
- "${PORT:-8080}:8080"
volumes:
- my_data:/app/data
restart: unless-stopped
environment:
- API_KEY=${API_KEY:-}
volumes:
my_data:
name: my_data
Conventions:
- File name is
docker-compose.yml(notcompose.yml) - Reference env vars using
${VAR:-default}syntax with secure defaults where possible - Use
${VAR:?}mandatory-variable syntax for values that must be user-provided and have no safe default (e.g., encryption keys) - Always declare volumes under a top-level
volumes:key - Set
restart: unless-stopped - Use
-for environment variable prefixes, not=(e.g.,- API_KEY=${API_KEY:-})
.env.example
Documents all environment variables the compose file consumes. Include defaults, format hints, and comments:
# ── Configuration ──────────────────────────────────────────────────────
# Host port for the service (default: 8080)
PORT=8080
# API key for external service (required — generate a random key)
API_KEY=your-api-key
Conventions:
- Comment sections with dividers for readability
- Every
docker-compose.ymlvariable should appear here - Show default values where applicable
- Mark required variables with comments like
(required)
README.md
Documents what the template does and how to use it. Include at minimum:
- One-line description of the template
- Quick Start section with
cp .env.example .env, env setup, anddocker compose up -d - Environment variable reference table (Variable | Default | Description)
- Any post-start verification (e.g.,
curlcommand for health check)
See the LiteLLM template as a reference example.
4. Validate Locally
Before pushing, run the validation script to catch errors early:
node scripts/build-registry.js --validate-only
This checks every template directory for:
- Valid
arcane.jsonJSON syntax - Required fields:
id,name,description,version,author,tags idmatches the folder name and is a valid slug (^[a-z0-9-]+$)versionis valid semvertagsis a non-empty array of unique strings- Required files present:
docker-compose.yml,.env.example,README.md - No duplicate
idvalues across templates
5. Push and Open a PR
git add templates/<template-name>/
git commit -m "feat: add <template-name> template"
git push origin add-<template-name>
Open a pull request against the main branch. The Validate Templates workflow runs automatically on any PR that changes paths under templates/**.
6. After Merge
Once the PR merges to main, the Build and Deploy Registry workflow triggers:
- Runs
node scripts/build-registry.jsto generateregistry.json - Configures GitHub Pages
- Uploads the repository as a Pages artifact
- Deploys to GitHub Pages (~2 minutes total)
After deployment, the published registry is available at:
https://<org>.github.io/arcane-repo/registry.json
Replace <org> with the organization or owner name.
Modifying an Existing Template
Edit any of the four required files in the template's directory:
arcane.json— update metadata (version, description, tags)docker-compose.yml— update service configuration.env.example— add or update documented variablesREADME.md— update documentation
The content_hash is computed at build time from all four source files (sorted alphabetically: arcane.json, docker-compose.yml, .env.example, README.md), so any modification is automatically detected by CI. You do not need to update a hash manually.
Run local validation before pushing:
node scripts/build-registry.js --validate-only
Removing a Template
Delete the template directory:
rm -rf templates/<template-name>/
git add -A
git commit -m "feat: remove <template-name> template"
Commit and push. The next CI run skips the removed directory — no other files need updating. The registry.json is rebuilt from whatever directories remain.
CI Workflows
Validate Templates (validate.yml)
- Triggers on: Pull requests to any branch, when files under
templates/**change - Steps:
- Checkout code
- Set up Node.js 22
- Run
node scripts/build-registry.js --validate-only
- Failing a PR: If validation errors are found, the workflow exits with a non-zero code, marking the PR check as failed. Fix the reported issue and push again.
Build and Deploy Registry (deploy.yml)
- Triggers on: Push to
mainthat changes files undertemplates/**,schema.json, orscripts/build-registry.js - Steps:
- Checkout code
- Set up Node.js 22
- Run
node scripts/build-registry.js(writesregistry.json) - Configure GitHub Pages
- Upload the repository as a Pages artifact
- Deploy to Pages
Schema
The registry schema lives at schema.json in the repository root. It defines two levels:
Registry (top-level)
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Registry name |
description |
string | yes | Registry description |
version |
semver | yes | Registry version |
author |
string | yes | Registry author |
url |
URI | yes | Repository URL |
templates |
array | yes | Array of template objects (min 1 item) |
Template
| Field | Type | Required | Description |
|---|---|---|---|
id |
slug | yes | Unique identifier, matches folder name |
name |
string | yes | Human-readable name |
description |
string | yes | Detailed description |
version |
semver | yes | Template version |
author |
string | yes | Template author |
compose_url |
URI | yes | Auto-generated raw GitHub URL to compose file |
env_url |
URI | yes | Auto-generated raw GitHub URL to env example |
documentation_url |
URI | yes | Auto-generated raw GitHub URL to README |
content_hash |
SHA-256 hex | yes | Auto-generated hash of all source files |
tags |
array | yes | Non-empty array of unique tags (letters, digits, hyphens) |
Auto-Generated Fields
Template authors do not write these fields in arcane.json. The CI build script computes them:
compose_url—https://raw.githubusercontent.com/<owner>/<repo>/<branch>/templates/<id>/docker-compose.ymlenv_url—https://raw.githubusercontent.com/<owner>/<repo>/<branch>/templates/<id>/.env.exampledocumentation_url—https://raw.githubusercontent.com/<owner>/<repo>/<branch>/templates/<id>/README.mdcontent_hash— SHA-256 of the concatenation of all four source files sorted alphabetically
The build script resolves the repository owner and name from GITHUB_REPOSITORY in CI, or from REPO_OWNER/REPO_NAME environment variables locally.
Validation Rules (from build-registry.js)
These are checked by the validation script and CI:
| Rule | Error level |
|---|---|
templates/ directory must exist |
error |
Each subdirectory must have arcane.json |
error |
arcane.json must be valid JSON |
error |
id must match folder name |
error |
id must match slug pattern /^[a-z0-9-]+$/ |
error |
version must be valid semver |
error |
tags must be a non-empty array |
error |
docker-compose.yml must exist |
error |
.env.example must exist |
error |
README.md must exist |
error |
No duplicate template id values |
error |
| Duplicate tags (in same template) | warning |
License
By contributing, you agree that your contributions will be licensed under the MIT License (see LICENSE — if no LICENSE file exists, the repository defaults to MIT).