Claude
Skills
Sign in
Back

eve-manifest-authoring

Included with Lifetime
$97 forever

Author and maintain Eve manifest files (.eve/manifest.yaml) for services, environments, pipelines, workflows, and secret interpolation. Use when changing deployment shape or runtime configuration in an Eve-compatible repo.

Security

What this skill does


# Eve Manifest Authoring

Keep the manifest as the single source of truth for build and deploy behavior.

## Minimal skeleton (v2)

```yaml
schema: eve/compose/v2
project: my-project

registry: "eve"  # Use managed registry by default for Eve apps
services:
  api:
    build:
      context: ./apps/api           # Build context directory
      dockerfile: Dockerfile        # Optional, defaults to context/Dockerfile
    # image omitted by default; when build is present, Eve derives image name from service key
    ports: [3000]
    environment:
      NODE_ENV: production
    x-eve:
      ingress:
        public: true
        port: 3000

environments:
  staging:
    pipeline: deploy
    pipeline_inputs:
      some_key: default_value

pipelines:
  deploy:
    steps:
      - name: build
        action:
          type: build               # Builds all services with build: config
      - name: release
        depends_on: [build]
        action:
          type: release
      - name: deploy
        depends_on: [release]
        action:
          type: deploy
```

## Registry Image Labels

Some registries require package metadata for permission and ownership inheritance.
Add these labels to your Dockerfiles when supported by your registry:

```dockerfile
LABEL org.opencontainers.image.source="https://github.com/YOUR_ORG/YOUR_REPO"
LABEL org.opencontainers.image.description="Service description"
```

**Why this matters**: Metadata helps preserve repository ownership and improves traceability. The Eve builder injects these labels automatically, but including them in your Dockerfile is still recommended.

For multi-stage Dockerfiles, add the labels to the **final** stage (the production image).

## Registry Modes

```yaml
registry: "eve"     # Eve-native registry (internal JWT auth)
registry: "none"    # Disable registry handling (public images)
registry:           # BYO registry (full object — see section below)
  host: public.ecr.aws/w7c4v0w3
  namespace: myorg
  auth: { username_secret: REGISTRY_USERNAME, token_secret: REGISTRY_PASSWORD }
```

For BYO/private registries, provide:

```yaml
registry:
  host: public.ecr.aws/w7c4v0w3
  namespace: myorg
  auth:
    username_secret: REGISTRY_USERNAME
    token_secret: REGISTRY_PASSWORD
```

## Managed Databases

Declare platform-provisioned databases with `x-eve.role: managed_db`:

```yaml
services:
  db:
    x-eve:
      role: managed_db
      managed:
        class: db.p1
        engine: postgres
        engine_version: "16"
```

Not deployed to K8s — provisioned by the orchestrator on first deploy.
Reference managed values elsewhere: `${managed.db.url}`.

## Eve-Migrate for Database Migrations

Use the platform's migration runner instead of Flyway, TypeORM, or Knex. It uses plain SQL files with timestamp prefixes, tracked in `schema_migrations`:

```yaml
services:
  migrate:
    image: public.ecr.aws/w7c4v0w3/eve-horizon/migrate:latest
    environment:
      DATABASE_URL: ${managed.db.url}
      MIGRATIONS_DIR: /migrations
    x-eve:
      role: job
      files:
        - source: db/migrations
          target: /migrations
```

Migration files: `db/migrations/20260312000000_initial_schema.sql`. The `x-eve.files` directive mounts them into the container at `/migrations`.

In the pipeline, the migrate step must run **after deploy** (managed DB needs provisioning):

```yaml
pipelines:
  deploy:
    steps:
      - name: build
        action: { type: build }
      - name: release
        depends_on: [build]
        action: { type: release }
      - name: deploy
        depends_on: [release]
        action: { type: deploy }
      - name: migrate
        depends_on: [deploy]
        action: { type: job, service: migrate }
```

For local dev, use the same image via Docker Compose for parity:

```yaml
# docker-compose.yml
services:
  migrate:
    image: ghcr.io/incept5/eve-migrate:latest
    environment:
      DATABASE_URL: postgres://app:app@db:5432/myapp
    volumes:
      - ./db/migrations:/migrations:ro
    depends_on:
      db: { condition: service_healthy }
```

## Legacy manifests

If the repo still uses `components:` from older manifests, migrate to `services:`
and add `schema: eve/compose/v2`. Keep ports and env keys the same.

## Services

- Provide `image` and optionally `build` (context and dockerfile).
- Use `ports`, `environment`, `healthcheck`, `depends_on` as needed.
- Use `x-eve.external: true` and `x-eve.connection_url` for externally hosted services.
- Use `x-eve.role: job` for one-off services (migrations, seeds). For database migrations, prefer Eve's `eve-migrate` image (see below).

### Build configuration

Services with Docker images should define their build configuration:

```yaml
services:
  api:
    build:
      context: ./apps/api           # Build context directory
      dockerfile: Dockerfile        # Optional, defaults to context/Dockerfile
    # image: api      # optional if using build; managed registry derives this
    ports: [3000]
```

Note: Every deploy pipeline should include a `build` step before `release`. The build step creates tracked BuildSpec/BuildRun records and produces image digests that releases use for deterministic deployments.

## Local dev alignment

- Keep service names and ports aligned with Docker Compose.
- Prefer `${secret.KEY}` and use `.eve/dev-secrets.yaml` for local values.

## Environments, pipelines, workflows

- Link each environment to a pipeline via `environments.<env>.pipeline`.
- When `pipeline` is set, `eve env deploy <env>` triggers that pipeline instead of direct deploy.
- Use `environments.<env>.pipeline_inputs` to provide default inputs for pipeline runs.
- Override inputs at runtime with `eve env deploy <env> --ref <sha> --inputs '{"key":"value"}' --repo-dir ./my-app`.
- Use `--direct` flag to bypass pipeline and do direct deploy: `eve env deploy <env> --ref <sha> --direct --repo-dir ./my-app`.
- Pipeline steps can be `action`, `script`, or `agent`.
- Use `action.type: create-pr` for PR automation when configured.
- Workflows live under `workflows` and are invoked via CLI; `db_access` is honored.
- Workflow steps support `harness`, `harness_profile`, and `harness_options` per step (overrides agent-resolved values), `condition` for skip-if-false gating against upstream step status, and `git` controls (now correctly materialized at dispatch). See `references/manifest.md` for the full step shape.
- Workflow- and step-level `scope` blocks narrow the step job token and org filesystem mount. Supported axes: `orgfs`, `orgdocs`, `envdb`, `cloud_fs`. Step scope intersects workflow scope — invocation scope may narrow but not widen. Use it to grant a step exactly the paths/tables/mounts it needs, default-deny everything else.

```yaml
workflows:
  create-design:
    scope:
      orgfs: { allow_prefixes: [/groups/projects/proj-a/**] }
    steps:
      - name: publish
        scope:
          cloud_fs: { allow_mount_ids: [mount_a] }
        agent: { name: publisher }
```

Request-supplied `scope` (workflow invoke API body) requires `jobs:harness_override`. No `--scope-*` CLI flag yet.

## Custom Domains and Stable Egress

Bring-your-own hostnames and opt-in network shape are declared per service:

```yaml
services:
  api:
    x-eve:
      ingress:
        public: true
        port: 3000
        domains: ["app.example.com", "www.example.com"]    # max 10
      networking:
        egress: stable    # default 'nat'; opt in only when a vendor needs allowlisted source IPs
```

- `ingress.domains` are bound on first deploy: the **first env** to deploy with a hostname owns it; other envs that reference the same hostname log `owned by environment "<A>"` and skip rendering. Operate ownership with `eve domain list|verify|status|transfer|unbind|remove` (see `eve-deploy-debugging`).
- `networking.egress: stable` schedules the pod on the stable-egress node group with `hostNetwork: true`. It bypasses NAT and constrains scheduling — only opt in when needed.

See `references/m

Related in Security