Preskoči na sadržaj

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 za docker 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 preko ci/npm/publish.py.
  • kind: none — nema builda (artifact-only ili external).
  • secrets — POSIX shell imena BuildKit secrets, forwarded via docker 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: semverMAJOR.MINOR.PATCH iz git tagova.
  • git_tag.prefix — prefiks za tag (obično v).
  • git_tag.staging_suffix — sufiks za non-production tagove.
  • version_files — fajlovi koje bump REWRITE-uje (.json version key, .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). Bez sync = 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" }]
  }
}

Vidi i