Skip to content

Commit 0a5c167

Browse files
JarbasAlclaude
andcommitted
feat: use GitHub App instead of PAT for PR submissions
Replace BOT_TOKEN (personal access token) with a proper GitHub App: - uses actions/create-github-app-token@v1 to generate short-lived tokens scoped to the target skill repo - PRs authored by ovos-localize[bot], not a personal account - App needs: Contents (read/write) + Pull requests (read/write) - Config: LOCALIZE_APP_ID (variable) + LOCALIZE_APP_PRIVATE_KEY (secret) Updated docs/deployment.md with step-by-step GitHub App setup guide. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 28e1337 commit 0a5c167

File tree

2 files changed

+65
-27
lines changed

2 files changed

+65
-27
lines changed

.github/workflows/submit_translation.yml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,21 @@ jobs:
1919
echo "branch=${{ github.event.client_payload.branch }}" >> "$GITHUB_OUTPUT"
2020
echo "author=${{ github.event.client_payload.author }}" >> "$GITHUB_OUTPUT"
2121
22+
- name: Generate GitHub App token
23+
id: app-token
24+
uses: actions/create-github-app-token@v1
25+
with:
26+
app-id: ${{ vars.LOCALIZE_APP_ID }}
27+
private-key: ${{ secrets.LOCALIZE_APP_PRIVATE_KEY }}
28+
owner: ${{ steps.payload.outputs.org }}
29+
repositories: ${{ steps.payload.outputs.repo }}
30+
2231
- name: Checkout target repo
2332
uses: actions/checkout@v4
2433
with:
2534
repository: ${{ steps.payload.outputs.org }}/${{ steps.payload.outputs.repo }}
2635
ref: ${{ steps.payload.outputs.branch }}
27-
token: ${{ secrets.BOT_TOKEN }}
36+
token: ${{ steps.app-token.outputs.token }}
2837

2938
- name: Create branch and commit
3039
env:
@@ -43,8 +52,8 @@ jobs:
4352
# Write content (base64 decoded)
4453
echo "$CONTENT" | base64 -d > "$FILE_PATH"
4554
46-
git config user.name "OVOS Localize Bot"
47-
git config user.email "noreply@openvoiceos.org"
55+
git config user.name "ovos-localize[bot]"
56+
git config user.email "ovos-localize[bot]@users.noreply.github.com"
4857
git add "$FILE_PATH"
4958
git commit -m "translate(${LANG}): update ${FILE_KEY}
5059
@@ -57,7 +66,7 @@ Submitted by @${AUTHOR} via OVOS Localize"
5766

5867
- name: Create Pull Request
5968
env:
60-
GH_TOKEN: ${{ secrets.BOT_TOKEN }}
69+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
6170
ORG: ${{ steps.payload.outputs.org }}
6271
REPO: ${{ steps.payload.outputs.repo }}
6372
BASE: ${{ steps.payload.outputs.branch }}

docs/deployment.md

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,66 @@ In the repo settings → Pages → Source: deploy from `dev` branch, root `/`.
1010

1111
The SPA (`index.html`) and data files (`data/`) are served directly.
1212

13-
### 2. Configure the bot token
14-
15-
Translation submissions work via a GitHub Action that creates PRs on behalf of users. This requires a **bot token** stored as a repository secret.
16-
17-
**Create a fine-grained PAT for the bot:**
18-
1. Go to [github.com/settings/personal-access-tokens/new](https://github.com/settings/personal-access-tokens/new)
19-
2. Name: `ovos-localize-bot`
20-
3. Resource owner: `OpenVoiceOS`
21-
4. Repository access: **All repositories** (the bot needs to create branches + PRs on any skill repo)
22-
5. Permissions:
23-
- **Contents**: Read and write (to commit files)
13+
### 2. Create a GitHub App
14+
15+
Translation submissions work via a GitHub Action that creates PRs on skill repos. This uses a **GitHub App** (not a personal token) so PRs come from a bot identity.
16+
17+
**Create the App:**
18+
1. Go to **github.com/organizations/OpenVoiceOS/settings/apps/new**
19+
2. Fill in:
20+
- **Name**: `ovos-localize`
21+
- **Homepage URL**: `https://openvoiceos.github.io/ovos-localize/`
22+
- **Webhook**: uncheck "Active" (not needed)
23+
3. **Permissions → Repository permissions**:
24+
- **Contents**: Read and write (to create branches and commit files)
2425
- **Pull requests**: Read and write (to open PRs)
25-
6. Generate and copy the token
26-
27-
**Add as repo secret:**
28-
1. Go to the ovos-localize repo → Settings → Secrets → Actions
29-
2. New repository secret: `BOT_TOKEN` = the token you just created
26+
4. **Where can this app be installed?**: "Only on this account"
27+
5. Click **Create GitHub App**
28+
6. Note the **App ID** shown on the settings page
29+
30+
**Generate a private key:**
31+
1. On the App settings page, scroll to "Private keys"
32+
2. Click **Generate a private key** — downloads a `.pem` file
33+
34+
**Install the App:**
35+
1. Go to the App's page → **Install App**
36+
2. Select the **OpenVoiceOS** organization
37+
3. Choose **All repositories** (the bot needs access to any skill repo)
38+
4. Click **Install**
39+
40+
**Add to the ovos-localize repo:**
41+
1. Settings → **Variables → Actions** → New variable:
42+
- Name: `LOCALIZE_APP_ID`, Value: the App ID from step 6
43+
2. Settings → **Secrets → Actions** → New secret:
44+
- Name: `LOCALIZE_APP_PRIVATE_KEY`, Value: paste the entire contents of the `.pem` file
3045

3146
### 3. How it works
3247

3348
```
3449
User (browser) GitHub
35-
───────────── ──────
50+
───────────── ──────
3651
1. Edit translation
3752
2. Click "Submit"
3853
3. POST /repos/OpenVoiceOS/ ──→ repository_dispatch event
3954
ovos-localize/dispatches (event_type: submit-translation)
4055
4156
4257
submit_translation.yml runs:
43-
- Checks out target skill repo
44-
- Creates translate/{lang}/{file} branch
45-
- Commits the translated file
46-
- Opens PR to dev branch
47-
- PR body mentions @username
58+
├── actions/create-github-app-token
59+
│ generates a short-lived token
60+
│ scoped to the target skill repo
61+
├── Checks out target skill repo
62+
├── Creates translate/{lang}/{file} branch
63+
├── Commits as ovos-localize[bot]
64+
└── Opens PR to dev branch
65+
(mentions @username in body)
4866
```
4967

50-
The user's token only needs permission to trigger dispatches on ovos-localize. The `BOT_TOKEN` secret handles the actual repo writes and PR creation.
68+
**Key properties:**
69+
- The GitHub App token is **short-lived** (expires in 1 hour) and scoped to the single target repo
70+
- PRs appear as authored by `ovos-localize[bot]` — not tied to any personal account
71+
- No personal tokens or service accounts needed for the bot side
72+
- The user's token only needs permission to trigger `repository_dispatch` on the ovos-localize repo
5173

5274
### 4. Daily data refresh
5375

@@ -63,3 +85,10 @@ Users create a fine-grained PAT scoped to the `ovos-localize` repo only, with:
6385
- **Actions**: Read and write (to trigger `repository_dispatch`)
6486

6587
This is the minimum permission needed. Users never get write access to skill repos.
88+
89+
### 6. Summary of secrets/variables
90+
91+
| Name | Type | Where | Purpose |
92+
|------|------|-------|---------|
93+
| `LOCALIZE_APP_ID` | Variable | ovos-localize repo | GitHub App ID |
94+
| `LOCALIZE_APP_PRIVATE_KEY` | Secret | ovos-localize repo | GitHub App private key (.pem) |

0 commit comments

Comments
 (0)