Skip to content

Migrating to 0.17: config.yaml

0.17 consolidates all non-secret configuration into a single config.yaml file. Previously, configuration was split across ~17 environment variables and a separate mappings.yaml. This is a manual, breaking migration — there is no automated converter. The server fails fast at startup if a retired environment variable is still set, printing the variable name and a pointer to this guide.

What changes

  • A new config.yaml file holds all non-secret app settings plus the mappings: and digest: sections that previously lived in mappings.yaml.
  • .env shrinks to secrets and infra-interpolation values only (see Stays in .env).
  • mappings.yaml and mappings.lock are retired. The equivalent sections move verbatim into config.yaml.
  • The validation cache file is now config.lock (same mechanism as mappings.lock, retargeted).
  • The CLI binary is renamed: notifycat-mappingnotifycat-config.

Retired environment variables

Every variable in this table is now a key in config.yaml. Remove it from .env / your deployment secrets and add the corresponding YAML key instead.

Retired env var config.yaml path Notes
ADDR server.addr Default :8080
LOG_LEVEL server.log_level Default info
LOG_FORMAT server.log_format Default text
DATABASE_URL database.url Default file:./data/notifycat.db; see Docker note
NOTIFYCAT_MAPPINGS_FILE (removed) Mappings content now lives directly under config.yaml's mappings: key; no separate file path needed
SLACK_BASE_URL slack.base_url Default https://slack.com
SLACK_REACTIONS_ENABLED slack.reactions.enabled Default true
SLACK_REACTION_NEW_PR slack.reactions.new_pr Default eyes
SLACK_REACTION_MERGED_PR slack.reactions.merged_pr Default twisted_rightwards_arrows
SLACK_REACTION_CLOSED_PR slack.reactions.closed_pr Default x
SLACK_REACTION_PR_APPROVED slack.reactions.approved Default white_check_mark
SLACK_REACTION_PR_COMMENTED slack.reactions.commented Default speech_balloon
SLACK_REACTION_PR_REQUEST_CHANGE slack.reactions.request_change Default exclamation
SLACK_REACTION_BOT_REVIEW slack.reactions.bot_review Default robot_face
GITHUB_BASE_URL github.base_url Default https://api.github.com
NOTIFYCAT_MESSAGE_TTL_DAYS cleanup.message_ttl_days Default 30
NOTIFYCAT_IGNORE_AI_REVIEWS reviews.ignore_ai_reviews Default false
NOTIFYCAT_DEPENDABOT_FORMAT reviews.dependabot_format Default true

Stays in .env

Only these values remain in .env:

Variable Required Notes
GITHUB_WEBHOOK_SECRET Required The secret configured on the GitHub webhook
SLACK_BOT_TOKEN Required Bot token starting with xoxb-
GITHUB_TOKEN Optional PAT for notifycat-config validate and notifycat-doctor; if unset, webhook-coverage check is skipped
DOMAIN Required for Docker Compose Public DNS name; Caddy uses it for TLS and can't read config.yaml. Also set server.domain in config.yaml for notifycat-doctor.
ACME_EMAIL Required for Docker Compose Contact email for Let's Encrypt registration

Moving mappings.yaml into config.yaml

The content of mappings.yaml moves verbatim into config.yaml. The per-org schema is unchanged in 0.17.

Before (mappings.yaml):

digest:
  enabled: true
  schedule: "0 9 * * *"

mappings:
  acme:
    channel: C0123ABCDE
    mentions: ["<@U0123ALICE>"]
    repositories:
      - api
      - web

After (inside config.yaml):

digest:
  enabled: true
  schedule: "0 9 * * *"

mappings:
  acme:
    channel: C0123ABCDE
    mentions: ["<@U0123ALICE>"]
    repositories:
      - api
      - web

The mappings: and digest: keys become top-level sections in config.yaml alongside the app-settings sections. No schema changes to the per-org entries.

Fail-fast on retired variables

The server detects every retired variable listed above at startup. If any is set, startup is aborted before the config is loaded, with a message listing the offending variables:

config: these env vars are no longer read and now live in config.yaml: [SLACK_REACTION_NEW_PR LOG_LEVEL] — see docs/0.17-config-migration.md

Remove the listed variables from your environment (.env, Docker env block, or deployment secret manager) and add the corresponding config.yaml keys before restarting.

Docker note

Prior to 0.17 the Docker image set DATABASE_URL=file:/app/notifycat.db as a built-in default. The image no longer sets this variable. Operators must add database.url to their config.yaml:

database:
  url: "file:/app/notifycat.db"   # historical image path — use this if you were relying on the old default

If you mount a /data volume for persistence, use "file:/data/notifycat.db" instead.

CLI rename

The notifycat-mapping binary is renamed to notifycat-config. Subcommands and flags are unchanged.

Old New
notifycat-mapping list notifycat-config list
notifycat-mapping validate notifycat-config validate
notifycat-mapping validate <owner/repo> notifycat-config validate <owner/repo>
notifycat-mapping validate --force notifycat-config validate --force

Update any scripts, CI jobs, or operator runbooks that call notifycat-mapping.

Migration checklist

  1. Create config.yaml from config.example.yaml — fill in any non-default values you had in .env.
  2. Copy the mappings: and digest: blocks from mappings.yaml into config.yaml as top-level keys.
  3. Trim .env to secrets + DOMAIN + ACME_EMAIL only (see Stays in .env).
  4. Delete mappings.yaml and mappings.lock from your deployment directory (they are superseded by config.yaml and config.lock).
  5. Run notifycat-config validate to populate config.lock.
  6. Run notifycat-doctor to confirm the full preflight.
  7. Deploy and verify startup logs show no FATAL: environment variable lines.