Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 58 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ on:
workflow_dispatch:

env:
KAPI_VERSION: "1.2.0-rc29"
KAPI_VERSION: "1.2.0-rc32"

jobs:
test-plan:
Expand All @@ -39,7 +39,7 @@ jobs:
uses: ./
with:
plan: "true"
project: "test/fixture/fixture.kapi"
project: "test/fixture/kapi.yaml"

- name: Verify plan outputs
env:
Expand Down Expand Up @@ -71,7 +71,7 @@ jobs:
with:
command: check
args: "--ship"
project: "test/fixture/fixture.kapi"
project: "test/fixture/kapi.yaml"

- name: Verify gate contract
env:
Expand Down Expand Up @@ -382,3 +382,58 @@ jobs:
run: |
test -f test/fixture/content/en_qps.json
test "${STATUS}" = "no-changes"

# The README sends callers to setup-kapi's cache-tm for caching rather than a
# cache step of their own. The save job runs the action and finds kapi's parse
# cache where setup-kapi saves it, and nothing at the retired .kapi/cache path;
# the restore job must find that cache in place before the action runs again.
test-parse-cache-save:
name: "parse cache: written where setup-kapi saves it"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: neokapi/setup-kapi@v1
with:
version: ${{ env.KAPI_VERSION }}
plugins: ""
project-dir: test/fixture

- name: Report status
uses: ./
with:
command: status
project: "test/fixture/kapi.yaml"

- name: Verify the cache paths
run: |
test -f test/fixture/.kapi/work/cache/docs/index.db
test ! -e test/fixture/.kapi/cache

test-parse-cache-restore:
name: "parse cache: restored before the action runs"
needs: test-parse-cache-save
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: neokapi/setup-kapi@v1
with:
version: ${{ env.KAPI_VERSION }}
plugins: ""
project-dir: test/fixture

- name: Verify the restored cache
run: test -f test/fixture/.kapi/work/cache/docs/index.db

- name: Report status on the restored cache
id: status
uses: ./
with:
command: status
project: "test/fixture/kapi.yaml"

- name: Verify the action reports no changes
env:
STATUS: ${{ steps.status.outputs.status }}
run: test "${STATUS}" = "no-changes"
28 changes: 13 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This action requires the `kapi` CLI to be installed. Use [`neokapi/setup-kapi@v1

### Bring translations up to date

`kapi up` runs the kapi loop, and is the Action's default. In a server-connected project — a recipe with a `server:` block — it pushes, catches up on the Bowrain server (org keys, shared TM, team review), and pulls the produced targets back. With no server it runs the same loop locally.
`kapi up` runs the kapi loop, and is the Action's default. It needs kapi 1.2.0 or later, which `neokapi/setup-kapi@v1` installs by default. In a server-connected project, a recipe with a `bowrain:` block, it pushes, catches up on the Bowrain server, and pulls the produced targets back; give setup-kapi the server token. With no server it runs the same loop locally and needs an AI provider key, such as `ANTHROPIC_API_KEY`.

```yaml
name: Translations
Expand All @@ -29,10 +29,16 @@ jobs:
- uses: actions/checkout@v6

- uses: neokapi/setup-kapi@v1
with:
# A recipe with a bowrain: block runs the loop on the server.
auth-token: ${{ secrets.BOWRAIN_AUTH_TOKEN }}

- uses: neokapi/kapi-action@v1
env:
# A project with no server translates locally with your provider key.
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

# The action reports; delivery is your step. Any commit action works —
# The action reports; delivery is your step. Any commit action works,
# or plain git. See "Delivering the changes" for the PR-based recipe.
- uses: stefanzweifel/git-auto-commit-action@v5
with:
Expand Down Expand Up @@ -76,11 +82,11 @@ flowchart LR
U --> PASS
CK -->|every gate met| CV["up to date<br/>changes ready to deliver"]
CK -->|needs a person| PK["parked<br/>the review queue"]
PK --> RV["review & approve<br/>recorded in .kapi-state.json"]
PK --> RV["review & approve<br/>committed under .kapi/state"]
RV -.->|next run sees it| U
```

**Parked work is the review queue, not an error.** What the machine couldn't decide waits for a person: review the wording, approve or fix it, and the decision is recorded — in the committed `.kapi-state.json` state store, or on the connected server. Approvals raise the `reviewed` coverage the ship gate measures, so the next run and the next gate see them. `kapi check --ship` (see [Gate pull requests](#gate-pull-requests-on-content-quality)) is what enforces the bar at release time.
**Parked work is the review queue, not an error.** What the machine couldn't decide waits for a person: review the wording, approve or fix it, and `kapi commit` records the decision under `.kapi/state/`, or the connected server records it. Approvals raise the `reviewed` coverage the ship gate measures, so the next run and the next gate see them. `kapi check --ship` (see [Gate pull requests](#gate-pull-requests-on-content-quality)) is what enforces the bar at release time.

The kapi up report (outcome, passes, parked locales) is always written to the job summary. Under the hood the Action runs `kapi up --json`, an NDJSON stream — one convergence event per line, closed by a single `{"type":"result", ...}` record. That record is the contract; the events are the log. It becomes the `outcome`, `passes`, and `parked-locales` outputs.

Expand Down Expand Up @@ -155,7 +161,7 @@ jobs:

### Gate pull requests on content quality

`command: check` with `--ship` is the release bar: the project's bound quality gates (brand, terminology, QA) plus its ship/source coverage gates. An unmet gate exits `3`, which the Action surfaces as a distinct **"gate unmet"** annotation (not a generic failure), as `gate: fail` and as `result: failed`:
`command: check` with `--ship` is the release bar: the project's bound gates (voice, terminology, rule-based checks) plus its ship and source coverage gates. An unmet gate exits `3`, which the Action surfaces as a distinct **"gate unmet"** annotation (not a generic failure), as `gate: fail` and as `result: failed`:

```yaml
name: Ship gate
Expand Down Expand Up @@ -213,17 +219,9 @@ This runs `kapi run -p kapi.yaml translate`.

### Caching

The loop runs incrementally via the project's `.kapi/cache` (block store, extractions), which is gitignored and therefore rebuilt on every fresh runner. Restore it across runs to skip re-extraction:

```yaml
- uses: actions/cache@v5
with:
path: .kapi/cache
key: kapi-cache-${{ hashFiles('kapi.yaml', 'src/locales/en/**') }}
restore-keys: kapi-cache-
```
`neokapi/setup-kapi@v1` carries kapi's parse cache (`.kapi/work/cache/docs`) between runs. Its `cache-tm` input is on by default for a project with a `kapi.yaml`, so this Action needs no cache step of its own. Set setup-kapi's `project-dir` when the recipe is not at the repository root.

Server-connected projects don't need this — the project state lives on the server.
Leave the rest of `.kapi/work/` out of any cache. Its store holds the targets and review state a run produced, and a restored copy changes what `kapi status`, `kapi check --ship` and `kapi up` report.

## Inputs

Expand Down
File renamed without changes.
Loading