Skip to main content

Use case: gate brand terminology in CI

A team's governed terminology lives in the Brand hub on the Bowrain server — preferred terms, forbidden terms, the wording approved per market. This guide wires that governed terminology into a CI gate, so a pull request that uses a banned term or the wrong translation fails the build before it merges.

The loop is two commands:

  1. kapi pull fetches translations and, when the project is claimed into a workspace, also snapshots the workspace's governed concepts and their relations into the project's local terms store (.kapi/terms.db).
  2. kapi check --ship runs the project's bound gates — the terminology gate checks the project's target files against that terms store and exits non-zero when a file violates it.

Pull the truth once, then verify offline — no per-file server round-trip, and the gate enforces exactly what the hub shows.

Prerequisites

  • The project is claimed into a workspace (its kapi.yaml recipe carries a server: block).
  • The project binds a terms store — defaults.terms in the recipe, or the conventional .kapi/terms.db, which is where kapi pull writes the governed concepts.
  • The runner is authenticated. In CI, set BOWRAIN_AUTH_TOKEN; locally, run kapi auth login.

Locally

# 1. Pull translations and governed terminology from the workspace.
kapi pull

# 2. Gate the project against its bound gates, terminology included.
kapi check --ship

kapi check --ship runs every gate the project binds — brand, terminology, QA — plus its ship/source coverage gates. The terminology gate runs because the project binds a terms store (the conventional .kapi/terms.db, which is exactly where kapi pull snapshots the governed concepts), so the gate enforces what the hub shows with no extra configuration.

Scope the check to one locale with --locale, or point the terminology gate at a specific terms store with --terms:

kapi check --ship --locale fr

In GitHub Actions

Install kapi with setup-kapi (the bowrain plugin is included by default), pull terminology, then gate:

name: Brand terminology gate

on:
pull_request:
paths:
- "src/locales/**"
- "kapi.yaml"
- ".kapi/**"

jobs:
terminology:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: neokapi/setup-kapi@v1
with:
auth-token: ${{ secrets.BOWRAIN_AUTH_TOKEN }}
server: https://dev.bowrain.cloud

- name: Pull translations and governed terminology
run: kapi pull

- name: Gate against the project's bound gates
run: kapi check --ship

The auth-token input exports BOWRAIN_AUTH_TOKEN, which kapi pull uses to reach the workspace; the server input (exported as BOWRAIN_SERVER_URL) is only needed for a self-hosted server — the hosted service is the default. A failing gate exits non-zero and fails the job.

Exit codes

kapi check --ship returns a single exit code the CI runner gates on:

ExitMeaning
0Pass — every bound gate passed
3A gate failed
1Operational error (project not found, unreadable file, …)

Exit 3 means "not on-spec yet", not a crash: read the findings and fix them. Pass --no-fail to always exit 0 (report mode) — useful inside an assistant fix-loop that reads the findings from the output and re-runs; omit it for CI gating, where the non-zero exit is the point.

Add --json to feed the structured findings to another tool:

kapi check --ship --json

Keeping the snapshot fresh

kapi pull refreshes the local terms store on every run, so pulling at the start of each CI job keeps the gate aligned with the current governed terminology. When the workspace changes a preferred or forbidden term — a governed edit that travels through a change-set — the next CI run pulls it and gates against it automatically.