services.json — field-by-field¶
TL;DR
Statički registar servisa, vlasnik je developer (commit-only).
Schema v31, hard-cut (bilo koja v≠31 → ManifestError). Najvažniji
top-level blokovi: environments, services, module_ci.
Top-level¶
{
"$schema": "https://schemas.infopuls.app/services/v31.json",
"version": 31,
"environments": { ... },
"services": { ... },
"module_ci": { ... }
}
| Field | Tip | Svrha |
|---|---|---|
$schema |
URL | JSON Schema referenca (IDE autocomplete) |
version |
int | Hard-cut gate; loader odbija sve ≠31 |
environments |
dict | Logical env mapping (production/staging/...) |
services |
dict | Servis registar (ime → config) |
module_ci |
dict | Laravel-module CI (opciono, build.kind=none) |
services.<name> — identitet¶
{
"path": "apps/api",
"build": { ... },
"release": { ... },
"deploy": { ... },
"observability": { ... }
}
path: repo-root-relative path do servisa. Koristi se zadocker build, file scanning, change detection.
services.<name>.build¶
{
"enabled": true,
"kind": "docker", // docker | expo | npm | none
"docker": {
"dockerfile": "Dockerfile",
"context": ".",
"build_args": ["SOURCE_COMMIT"],
"cache": { "mode": "registry", "ref": "..." },
"publish": { "image": "infopuls/api", "tags": ["resolved"] },
"secrets": ["GIT_AUTH_TOKEN"]
}
}
kind: docker— standard Docker build + push.kind: expo— EAS build (mobile), deploy.mode=expo.kind: npm— host-build paketa na runneru (build.npm: package_manager/build_script/install); publish prekoci/npm/publish.py.kind: none— nema builda (artifact-only ili external).secrets— POSIX shell imena BuildKit secrets, forwarded viadocker build --secret.
services.<name>.release¶
{
"enabled": true,
"scheme": "semver",
"git_tag": {
"prefix": "v",
"pattern": "{version}",
"staging_suffix": "rc.N"
},
"version_files": ["apps/api/package.json"]
}
scheme: semver—MAJOR.MINOR.PATCHiz git tagova.git_tag.prefix— prefiks za tag (običnov).git_tag.staging_suffix— sufiks za non-production tagove.version_files— fajlovi koje bump REWRITE-uje (.jsonversionkey,.py__version__).
services.<name>.deploy¶
{
"enabled": true,
"mode": "coolify", // coolify | ecs | expo
"image_tag": {
"var_name": "IMAGE_TAG",
"sync": { "coolify_env": false, "infisical": { "folder": "/prod" } }
},
"secrets": { "infisical": { "folder": "/prod/api" } },
"coolify": {
"by_environment": {
"production": { "uuid": "...", "project": "api-prod" },
"staging": { "uuid": "...", "project": "api-staging" }
}
},
"failure_policy": "soft" // soft | strict
}
mode: coolify— primary, two-phase deploy.mode: ecs— boto3 native, single-phase.mode: expo— EAS orchestrator.image_tag.sync— gdje se piše novi tag (Coolify env direkt ILI Infisical folder). Bezsync= silent no-op.failure_policy: strict— opt-in fail-closed.
services.<name>.observability¶
{
"sentry": {
"enabled": true,
"dsn": "https://...@sentry.io/...",
"stamp": {
"auto": true,
"finalize_on_deploy": true
},
"by_environment": {
"production": { "environment": "production" }
}
},
"slack": {
"channel": "#deploys"
}
}
sentry.stamp.auto: true— auto-stamp release nakon deploy-a.sentry.by_environment— per-env override (v18+).
jira.on.<action> (v28+)¶
{
"jira": {
"on": {
"release": {
"enabled": true,
"version": { "name": "{version}", "release_date": "..." },
"transition": {
"production": { "from": "In Progress", "to": "Done" }
}
}
}
}
}
on.<action>— top-level, keyed by CI action.transition— per-env{from, to}map.
module_ci (v29+)¶
{
"module_ci": {
"module_name": "socauth",
"parent": { "repo": "infopuls/api", "default_version": "1.5.0" },
"test_command": "php artisan test --filter={module}",
"junit_path": "test-results/{module}.xml",
"version_matrix": [{ "parent": "1.5.0", "module": ">=2.0.0" }]
}
}
- Samo na
build.kind: noneservisima (Laravel modules). - Vidi
ci/laravel_module/CLAUDE.md.
Vidi i¶
01-two-schemas.mdci/json/services.schema.json— canonical schemaci/json/CLAUDE.md— versioning + migration policyci/service_manifest.py— typed loader