Šķîþ ţö ḿàîñ çöñţéñţ

Üšé Çàšé: ķàþî îñ ĜîţĤüƃ Àçţîöñš

À ĜîţĤüƃ Àçţîöñš ŵöŕķƒļöŵ çàñ ķééþ éṽéŕý ļàñĝüàĝé çàüĝĥţ üþ öñ ţĥé šéŕṽéŕ, çöḿḿîţ ţĥé ŕéšüļţš ƃàçķ, àñđ ƃļöçķ à þüļļ ŕéǫüéšţ ţĥàţ ḿîššéš ţĥé šĥîþ ĝàţé. Ţĥé ŵöŕķƒļöŵš ƃéļöŵ ŕüñ ķàþî ŵîţĥ ţĥé ƃöŵŕàîñ þļüĝîñ ƒöŕ đŕàƒţîñĝ, ǫüàļîţý çĥéçķš àñđ šéŕṽéŕ šýñç.

Öṽéŕṽîéŵ​

Ţĥé setup-kapi ĜîţĤüƃ Àçţîöñ îñšţàļļš ķàþî öñ àñý ŕüññéŕ, ŵîţĥ ţĥé ƃöŵŕàîñ þļüĝîñ îñçļüđéđ ƃý đéƒàüļţ. Îţ ĥàñđļéš þļàţƒöŕḿ đéţéçţîöñ, çĥéçķšüḿ ṽéŕîƒîçàţîöñ, ƃîñàŕý çàçĥîñĝ àñđ öþţîöñàļ šéŕṽéŕ àüţĥéñţîçàţîöñ.

Ƒöŕ ţĥé öţĥéŕ ÇÎ àñđ đéļîṽéŕý šüŕƒàçéš (ĜîţĻàƃ ÇÎ, çöñţàîñéŕ ŕüññéŕš, àñđ ţĥé ñö-þîþéļîñé Ƃöŵŕàîñ ĜîţĤüƃ Àþþ), šţàŕţ àţ Ţĥé ļööþ îñ ÇÎ.

Šéţüþ​

Àđđ neokapi/setup-kapi@v1 ţö ýöüŕ ŵöŕķƒļöŵ:

steps:
- uses: actions/checkout@v7

- uses: neokapi/setup-kapi@v1
with:
version: "1.2.0"
plugins: bowrain@1.2.0

Ţĥé àçţîöñ đöŵñļöàđš ţĥé çöŕŕéçţ ƃîñàŕý ƒöŕ ţĥé ŕüññéŕ þļàţƒöŕḿ (Ļîñüẋ, ḿàçÖŠ, öŕ Ŵîñđöŵš), ṽéŕîƒîéš îţš ŠĤÀ-256 çĥéçķšüḿ, àñđ àđđš îţ ţö PATH. Ţĥé ƃüîļţ-îñ ŵöŕķƒļöŵ ţöķéñ çöṽéŕš þüƃļîç ŕéļéàšé đöŵñļöàđš, šö ñö token îñþüţ îš ŕéǫüîŕéđ. Öñ šüƃšéǫüéñţ ŕüñš, ţĥé ƃîñàŕý îš ŕéšţöŕéđ ƒŕöḿ çàçĥé.

Àçţîöñ Îñþüţš​

ÎñþüţĐéšçŕîþţîöñĐéƒàüļţ
versionÇĻÎ ṽéŕšîöñ ţö îñšţàļļ, öŕ latestlatest
pluginsÇöḿḿà öŕ ñéŵļîñé-šéþàŕàţéđ þļüĝîñ ŕ郚 ţö îñšţàļļ, àš ţĥé ŕéĝîšţŕý ñàḿéš ţĥéḿ ('' ţö îñšţàļļ ñöţĥîñĝ)bowrain
auth-tokenƂöŵŕàîñ šéŕṽéŕ ĴŴŢ (éẋþöŕţéđ àš BOWRAIN_AUTH_TOKEN)""
serverƂöŵŕàîñ šéŕṽéŕ ÜŔĻ (éẋþöŕţéđ àš BOWRAIN_SERVER_URL); šéļƒ-ĥöšţéđ öñļý, ţĥé ĥöšţéđ šéŕṽîçé îš ţĥé đéƒàüļţ""

Àçţîöñ Öüţþüţš​

ÖüţþüţĐéšçŕîþţîöñ
versionÎñšţàļļéđ ṽéŕšîöñ (ƒöŕ éẋàḿþļé 1.1.0)
cache-hitŴĥéţĥéŕ ţĥé þļüĝîñ çàçĥé ŵàš ĥîţ

Ŕéçöḿḿéñđéđ: Çàţçĥ üþ ŵîţĥ kapi-action​

Ţĥé šîḿþļéšţ ÇÎ þàţţéŕñ üšéš ţŵö àçţîöñš ţöĝéţĥéŕ:

  • neokapi/setup-kapi: îñšţàļļš ķàþî (ţĥé ƃöŵŕàîñ þļüĝîñ îš îñçļüđéđ ƃý đéƒàüļţ)
  • neokapi/kapi-action: ŕüñš à kapi çöḿḿàñđ (ĥéŕé, kapi up) àñđ ŕéþöŕţš ŵĥàţ çĥàñĝéđ, ƒöŕ à šţéþ öƒ ýöüŕ öŵñ ţö đéļîṽéŕ
name: Catch up

on:
workflow_dispatch:
push:
branches: [main]
paths:
- "src/locales/en/**"

permissions:
contents: write

jobs:
up:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

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

- uses: neokapi/kapi-action@v1
id: up
with:
command: up

- name: Commit the results
if: steps.up.outputs.has-changes == 'true'
env:
OUTCOME: ${{ steps.up.outputs.outcome }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
git commit -m "chore: update translations via kapi ($OUTCOME)"
git push

Ŵîţĥ command: up (ţĥé đéƒàüļţ), ţĥé àçţîöñ ŕüñš kapi up (ţĥé ķàþî ļööþ öñ ţĥé šéŕṽéŕ: þüšĥ → çàţçĥ üþ → þüļļ) àñđ ŕéþöŕţš ŵĥàţ ţĥé ŕüñ ļéƒţ îñ ţĥé ŵöŕķîñĝ ţŕéé. Ţĥé àçţîöñ çöḿḿîţš ñöţĥîñĝ; ţĥé ļàšţ šţéþ àƃöṽé çöḿḿîţš àñđ þüšĥéš.

  • À ŕüñ ţĥàţ çàüĝĥţ üþ (öüţçöḿé converged: éṽéŕý ĝàţéđ ļöçàļé çļéàŕéđ îţš šĥîþ ĝàţé) ļéàṽéš ţĥé þŕöđüçéđ ŕéšüļţš.
  • À ŕüñ ţĥàţ ļéàṽéš ŵöŕķ ŵàîţîñĝ ƒöŕ ŕéṽîéŵ (öüţçöḿé parked) ļéàṽéš ŵĥàţ đîđ çàţçĥ üþ àñđ àññöţàţéš ţĥé ļàñĝüàĝéš ŵàîţîñĝ ƒöŕ ŕéṽîéŵ.
  • À ƒàîļéđ ŕüñ éẋîţš ñöñ-žéŕö, šö ţĥé šţéþš àƒţéŕ îţ àŕé šķîþþéđ.

Îţ šéţš öüţþüţš ýöü çàñ üšé îñ ļàţéŕ šţéþš:

ÖüţþüţĐéšçŕîþţîöñ
statussuccess, no-changes, öŕ failed
outcomeŴîţĥ command: up: converged, öŕ parked ŵĥéñ ŵöŕķ ŵàîţš ƒöŕ ŕéṽîéŵ
passesŴîţĥ command: up: ĥöŵ ḿàñý ŕéçöñçîļîàţîöñ þàššéš ţĥé ŕüñ ţööķ
parked-localesŴîţĥ command: up: çöḿḿà-šéþàŕàţéđ ļàñĝüàĝéš ŵàîţîñĝ ƒöŕ ŕéṽîéŵ, šĥöŕţ öƒ ţĥéîŕ ĝàţé
gateŴîţĥ command: check: pass öŕ fail; éḿþţý ŵĥéñ ţĥé çĥéçķ đîđ ñöţ ŕüñ öŕ éŕŕöŕéđ
resultŴîţĥ command: check: passed, failed, did_not_run, öŕ error
did-not-run-causeŴîţĥ command: check, ŵĥéñ result îš did_not_run: ţĥé çàüšé ķàþî ŕéþöŕţéđ
has-changestrue ŵĥéñ ţĥé ŕüñ ļéƒţ çĥàñĝéš îñ ţĥé ŵöŕķîñĝ ţŕéé
changed-filesÑéŵļîñé-šéþàŕàţéđ þàţĥš ţĥé ŕüñ çĥàñĝéđ

Ŵîţĥ plan: true, ţĥé plan-* öüţþüţš çàŕŕý ţĥé þéñđîñĝ ţŕàñšļàţîöñš, ţĥé öñéš çöñţéñţ ḿéḿöŕý ŕéçöṽéŕš, ţĥé öñéš ļéƒţ ƒöŕ ÀÎ àñđ ţĥé ţöķéñ éšţîḿàţé.

ķàþî-àçţîöñ Îñþüţš​

ÎñþüţĐéƒàüļţĐéšçŕîþţîöñ
commandupŢĥé kapi çöḿḿàñđ ţö ŕüñ
args""Àđđîţîöñàļ àŕĝüḿéñţš
project""Þàţĥ ţö ţĥé kapi.yaml ŕéçîþé (-p ƒļàĝ)
planfalseŴîţĥ command: up, đŕý-ŕüñ îñšţéàđ (kapi up --plan): ŕéþöŕţ þéñđîñĝ ŵöŕķ, ḿéḿöŕý ŕéüšé, àñđ à ţöķéñ éšţîḿàţé; ñö ŵŕîţéš, ñö þŕöṽîđéŕ çàļļš. Þàîŕš ŵîţĥ pr-comment ţö þöšţ ţĥé çöšţ öƒ à çĥàñĝé öñ îţš ÞŔ
fail-on-parkedfalseŴîţĥ command: up, ƒàîļ ţĥé ŵöŕķƒļöŵ ŵĥéñ ŵöŕķ ŵàîţš ƒöŕ ŕéṽîéŵ îñšţéàđ öƒ ŕéþöŕţîñĝ þàŕţîàļ þŕöĝŕéšš
pr-commentfalseÖñ þüļļ-ŕéǫüéšţ éṽéñţš, þöšţ öñé šţîçķý çöḿḿéñţ ŵîţĥ ţĥé ŕéþöŕţ (þļàñ, kapi up öüţçöḿé, öŕ çĥéçķ ŕéšüļţ) ţĥàţ ŕé-ŕüñš üþđàţé îñ þļàçé
tokengithub.tokenĜîţĤüƃ ţöķéñ ƒöŕ ţĥé šţîçķý ÞŔ çöḿḿéñţ
paths"" (ţĥé ŵĥöļé ŵöŕķîñĝ ţŕéé)Šþàçé-šéþàŕàţéđ þàţĥš ţö šçàñ ƒöŕ çĥàñĝéš

:::ñöţé Ţĥé ŵöŕķƒļöŵ ñééđš permissions: contents: write ƒöŕ ýöüŕ đéļîṽéŕý šţéþ ţö þüšĥ çöḿḿîţš, þļüš pull-requests: write ŵĥéñ pr-comment îš üšéđ öŕ ţĥé đéļîṽéŕý šţéþ öþéñš à þüļļ ŕéǫüéšţ. :::

Ŕéüšàƃļé ŵöŕķƒļöŵš​

Ƒöŕ öñé-ļîñé àđöþţîöñ, neokapi/kapi-workflows þàçķàĝéš ţĥé çĥéçķöüţ → setup-kapi → kapi-action šéǫüéñçé àš ŕéüšàƃļé ŵöŕķƒļöŵš. up.yml@v1 çàţçĥéš ţĥé þŕöĵéçţ üþ àñđ đéļîṽéŕš à þüļļ ŕéǫüéšţ:

name: Catch up

on:
schedule:
- cron: "0 6 * * 1-5"
workflow_dispatch:

jobs:
up:
uses: neokapi/kapi-workflows/.github/workflows/up.yml@v1
permissions:
contents: write
pull-requests: write
with:
server: https://dev.bowrain.cloud
secrets:
bowrain-auth-token: ${{ secrets.BOWRAIN_AUTH_TOKEN }}

Öñ à šéŕṽéŕ-çöññéçţéđ þŕöĵéçţ ţĥé bowrain-auth-token šéçŕéţ àñđ server îñþüţ àŕé àļļ ţĥé ĵöƃ ñééđš; ţĥé ļööþ ŕüñš öñ ţĥé Ƃöŵŕàîñ šéŕṽéŕ. À ļöçàļ-ṽéñüé ŕüñ þàššéš ţĥé anthropic-api-key šéçŕéţ îñšţéàđ. Ţĥé ŵöŕķƒļöŵ éẋþöšéš outcome, passes, parked-locales, has-changes, àñđ pull-request-url àš ĵöƃ öüţþüţš.

gate.yml@v1 îš ţĥé ḿéŕĝé ĝàţé: îţ ŕüñš kapi check --ship, ƒàîļš ţĥé ĵöƃ öñ éẋîţ 3 (à ĝàţé îš üñḿéţ) öŕ 4 (à ĝàţé đîđ ñöţ ŕüñ), àñđ þöšţš öñé šţîçķý ŕéþöŕţ çöḿḿéñţ öñ ţĥé þüļļ ŕéǫüéšţ:

name: Ship gate

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

jobs:
ship-gate:
uses: neokapi/kapi-workflows/.github/workflows/gate.yml@v1
permissions:
contents: read
pull-requests: write

Üšé ţĥé àçţîöñš đîŕéçţļý (àš îñ ţĥé éẋàḿþļéš ƃéļöŵ) ŵĥéñ ţĥé ĵöƃ ñééđš à çüšţöḿ šĥàþé.

Éẋàḿþļé: Šĥîþ Ĝàţé öñ Þüļļ Ŕéǫüéšţ​

Ĝàţé þüļļ ŕéǫüéšţš öñ ţĥé þŕöĵéçţ'š ŕéļéàšé ƃàŕ ŵĥéñéṽéŕ çöñţéñţ ƒîļéš çĥàñĝé. kapi check --ship ŕüñš ţĥé þŕöĵéçţ'š ƃöüñđ ǫüàļîţý ĝàţéš (ṽöîçé, ţéŕḿš, ŕüļé-ƃàšéđ çĥéçķš) þļüš îţš šĥîþ/šöüŕçé çöṽéŕàĝé ĝàţéš, àñđ ƒàîļš ţĥé ĵöƃ ŵîţĥ éẋîţ 3 ŵĥéñ àñý ĝàţé îš üñḿéţ öŕ éẋîţ 4 ŵĥéñ à ĝàţé đîđ ñöţ ŕüñ:

name: Ship gate

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

jobs:
ship-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- uses: neokapi/setup-kapi@v1
with:
version: "1.2.0"
plugins: bowrain@1.2.0

- name: Enforce the ship gates
run: kapi check --ship

Àñ öŕđîñàŕý ƃüîļđ þàššéš ŵĥéñ à ļöçàļé îš ƃéĥîñđ. check --ship îš ţĥé šţéþ ýöü àđđ ţö éñƒöŕçé ţĥé ŕéļéàšé ƃàŕ.

Éẋàḿþļé: Þüšĥ šöüŕçé öñ Þüšĥ ţö Ḿàîñ​

Šéñđ šöüŕçé çĥàñĝéš ţö Ƃöŵŕàîñ Çļöüđ ŵĥéñ ţĥéý ļàñđ öñ main. Þüšĥ öñļý ḿöṽéš çöñţéñţ. Ŵîţĥ bowrain.converge: on-push, ţĥé šéŕṽéŕ ţĥéñ çàţçĥéš ţĥé þŕöĵéçţ üþ öñ îţš öŵñ šçĥéđüļé. Üšé kapi up îñšţéàđ öƒ kapi push îƒ ýöü ŵàñţ ÇÎ ţö ŵàţçĥ ţĥé ŕüñ àñđ çöḿḿîţ ţĥé ŕéšüļţš ƃàçķ:

name: Push source

on:
push:
branches: [main]
paths:
- "src/locales/**"

jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

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

- name: Push to Bowrain Cloud
run: kapi push

Ţĥé auth-token àñđ server îñþüţš éẋþöŕţ BOWRAIN_AUTH_TOKEN àñđ BOWRAIN_SERVER_URL àš éñṽîŕöñḿéñţ ṽàŕîàƃļéš, ŵĥîçĥ ţĥé ÇĻÎ þîçķš üþ àüţöḿàţîçàļļý.

Éẋàḿþļé: Šçĥéđüļéđ çàţçĥ-üþ​

Çàţçĥ üþ öñ à šçĥéđüļé (ƒöŕ éẋàḿþļé ñîĝĥţļý) ţö ķééþ ţàŕĝéţ ļöçàļéš üþ ţö đàţé. kapi-action ŕüñš kapi up, àñđ ţĥé ļàšţ šţéþ çöḿḿîţš ŵĥàţ ţĥé ŕüñ çĥàñĝéđ:

name: Nightly catch-up

on:
schedule:
- cron: "0 2 * * *" # 2 AM UTC

permissions:
contents: write

jobs:
up:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

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

- uses: neokapi/kapi-action@v1
id: up

- name: Commit the results
if: steps.up.outputs.has-changes == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
git commit -m "chore: update translations via kapi"
git push

Ţö đŕàƒţ šþéçîƒîç ƒîļéš àđ ĥöç îñšţéàđ öƒ çàţçĥîñĝ à þŕöĵéçţ üþ, kapi translate ţàķéš éẋþļîçîţ îñþüţš: kapi translate src/locales/en/app.json --target-lang fr (àñ ÀÎ þŕöṽîđéŕ ķéý šüçĥ àš ANTHROPIC_API_KEY ḿüšţ ƃé šéţ ƒöŕ à ÇÎ ŕüñ ţĥàţ đŕàƒţš).

Éẋàḿþļé: Þüļļ àñđ Ḿéŕĝé Šéŕṽéŕ Çĥàñĝéš​

Þüļļ ŕéšüļţš ƒŕöḿ Ƃöŵŕàîñ Çļöüđ àñđ öþéñ à ÞŔ:

name: Pull results

on:
workflow_dispatch:
schedule:
- cron: "0 8 * * 1" # Monday 8 AM UTC

jobs:
pull:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

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

- name: Pull from Bowrain Cloud
run: kapi pull

- name: Create PR if changed
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git diff --quiet && exit 0
BRANCH="bowrain/pull-results-$(date +%Y%m%d)"
git checkout -b "${BRANCH}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -A
git commit -m "chore: pull results from Bowrain Cloud"
git push -u origin "${BRANCH}"
gh pr create \
--title "Pull results from Bowrain Cloud" \
--body "Automated pull of the latest results from Bowrain Cloud."

Àüţĥéñţîçàţîöñ​

ķàþî šüþþöŕţš ţŵö àüţĥéñţîçàţîöñ ḿéţĥöđš îñ ÇÎ:

ḾéţĥöđĤöŵƂéšţ Ƒöŕ
Éñṽîŕöñḿéñţ ṽàŕîàƃļéŠéţ BOWRAIN_AUTH_TOKENĜîţĤüƃ Àçţîöñš (ṽîà auth-token îñþüţ)
Đéṽîçé ƒļöŵŔüñ kapi auth login îñţéŕàçţîṽéļýĻöçàļ đéṽéļöþḿéñţ

Ţĥé auth-token îñþüţ öñ ţĥé šéţüþ àçţîöñ îš ţĥé šîḿþļéšţ àþþŕöàçĥ: îţ éẋþöŕţš ţĥé ţöķéñ àš BOWRAIN_AUTH_TOKEN, ŵĥîçĥ ţĥé ÇĻÎ çĥéçķš ƃéƒöŕé ļööķîñĝ ƒöŕ šţöŕéđ çŕéđéñţîàļš.

Ĝéñéŕàţîñĝ à ÇÎ Ţöķéñ​

Çŕéàţé àñ ÀÞÎ ţöķéñ üšîñĝ ķàþî:

kapi auth login # authenticate with Bowrain Cloud
kapi auth token create --name "CI" --expire-days 90

Ţĥé ţöķéñ (bwt_...) îš šĥöŵñ öñçé, šö šţöŕé îţ ŕîĝĥţ àŵàý àš à ĜîţĤüƃ Àçţîöñš šéçŕéţ:

gh secret set BOWRAIN_AUTH_TOKEN --repo your-org/your-repo

Ýöü çàñ ļîšţ àñđ ŕéṽöķé ţöķéñš ŵîţĥ kapi auth token list àñđ kapi auth token delete.

Þļüĝîñš​

Ţĥé plugins îñþüţ đéƒàüļţš ţö bowrain, ţĥé þļüĝîñ ţĥàţ þŕöṽîđéš šýñç, þüšĥ, àñđ þüļļ. Ļîšţ ŕ郚 (àš ţĥé ŕéĝîšţŕý ñàḿéš ţĥéḿ) ţö àđđ öţĥéŕš àļöñĝšîđé îţ, öŕ þàšš '' ţö îñšţàļļ ñöţĥîñĝ:

- uses: neokapi/setup-kapi@v1
with:
version: "1.2.0"
plugins: |
bowrain@1.2.0
okapi-bridge

Þļüĝîñš àŕé çàçĥéđ ƃéţŵééñ ŕüñš. Ţĥé çàçĥé ķéý îñçļüđéš à ĥàšĥ öƒ ţĥé þļüĝîñ ļîšţ, šö çĥàñĝéš ţö ţĥé ļîšţ ţŕîĝĝéŕ à ƒŕéšĥ îñšţàļļ.

Þîññîñĝ Ṽéŕšîöñš​

Þîñ ţĥé ÇĻÎ ṽéŕšîöñ ţö àṽöîđ šüŕþŕîšéš ƒŕöḿ ñéŵ ŕéļéàšéš:

- uses: neokapi/setup-kapi@v1
with:
version: "1.2.0"

latest (ţĥé đéƒàüļţ) îñšţàļļš ţĥé ñéŵéšţ šţàƃļé ŕéļéàšé, àñđ kapi up, kapi check --ship àñđ ţĥé öţĥéŕ çöḿḿàñđš ţĥéšé éẋàḿþļéš ŕüñ ñééđ 1.2.0 öŕ ļàţéŕ.

Ŕéļàţéđ​