@sentry/junior-github 0.68.0 → 0.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SETUP.md +64 -17
- package/index.d.ts +41 -1
- package/index.js +975 -31
- package/package.json +3 -2
- package/permissions.js +77 -0
- package/skills/github-code/SKILL.md +6 -8
- package/skills/github-code/references/api-surface.md +43 -37
- package/skills/github-code/references/troubleshooting-workarounds.md +19 -14
- package/skills/github-issues/SKILL.md +5 -7
- package/skills/github-issues/references/api-surface.md +3 -3
- package/skills/github-issues/references/issue-examples.md +0 -28
- package/skills/github-issues/references/troubleshooting-workarounds.md +13 -12
package/SETUP.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# GitHub plugin setup
|
|
2
2
|
|
|
3
|
-
This plugin exposes two skills — `github-code` (clone, source-code investigation, pull requests) and `github-issues` (issue workflows)
|
|
3
|
+
This plugin exposes two skills — `github-code` (clone, source-code investigation, pull requests) and `github-issues` (issue workflows). Read operations use host-issued GitHub App installation tokens. Write operations use GitHub App user-to-server OAuth tokens so GitHub attributes the action to the requesting user with the app badge.
|
|
4
4
|
|
|
5
5
|
## 1) Create/install GitHub App
|
|
6
6
|
|
|
7
7
|
In GitHub:
|
|
8
8
|
|
|
9
9
|
1. Go to `Settings -> Developer settings -> GitHub Apps -> New GitHub App`.
|
|
10
|
-
2. Set app name and callback URL
|
|
10
|
+
2. Set app name and callback URL to `https://<junior-host>/api/oauth/callback/github`.
|
|
11
11
|
3. Under repository permissions, grant:
|
|
12
12
|
|
|
13
13
|
- Issues: Read and write
|
|
@@ -23,6 +23,8 @@ In GitHub:
|
|
|
23
23
|
Install the app on target repos/orgs and collect:
|
|
24
24
|
|
|
25
25
|
- `GITHUB_APP_ID`
|
|
26
|
+
- `GITHUB_APP_CLIENT_ID`
|
|
27
|
+
- `GITHUB_APP_CLIENT_SECRET`
|
|
26
28
|
- `GITHUB_APP_PRIVATE_KEY` (PEM)
|
|
27
29
|
|
|
28
30
|
## 2) Configure host runtime
|
|
@@ -30,6 +32,8 @@ Install the app on target repos/orgs and collect:
|
|
|
30
32
|
Set on the harness host (never in skill files):
|
|
31
33
|
|
|
32
34
|
- `GITHUB_APP_ID`
|
|
35
|
+
- `GITHUB_APP_CLIENT_ID`
|
|
36
|
+
- `GITHUB_APP_CLIENT_SECRET`
|
|
33
37
|
- `GITHUB_APP_PRIVATE_KEY`
|
|
34
38
|
- `GITHUB_INSTALLATION_ID`
|
|
35
39
|
|
|
@@ -39,16 +43,15 @@ under different app installations across orgs/accounts.
|
|
|
39
43
|
|
|
40
44
|
### Vercel env setup (multiline-safe)
|
|
41
45
|
|
|
42
|
-
`GITHUB_APP_PRIVATE_KEY`
|
|
43
|
-
|
|
44
|
-
- Raw PEM (multiline)
|
|
45
|
-
- Escaped-newline PEM (single-line with `\n`)
|
|
46
|
-
- Base64-encoded PEM
|
|
46
|
+
`GITHUB_APP_PRIVATE_KEY` must be the PEM private key generated by GitHub for
|
|
47
|
+
this app.
|
|
47
48
|
|
|
48
49
|
For Vercel, prefer CLI file input so newlines are preserved exactly:
|
|
49
50
|
|
|
50
51
|
```bash
|
|
51
52
|
vercel env add GITHUB_APP_ID production
|
|
53
|
+
vercel env add GITHUB_APP_CLIENT_ID production
|
|
54
|
+
vercel env add GITHUB_APP_CLIENT_SECRET production
|
|
52
55
|
vercel env add GITHUB_INSTALLATION_ID production
|
|
53
56
|
vercel env add GITHUB_APP_PRIVATE_KEY production --sensitive < ./github-app-private-key.pem
|
|
54
57
|
```
|
|
@@ -61,10 +64,44 @@ vercel env update GITHUB_APP_PRIVATE_KEY production --sensitive < ./github-app-p
|
|
|
61
64
|
|
|
62
65
|
Repeat for `preview` and `development` as needed. After env changes, redeploy so the new deployment picks up updated values.
|
|
63
66
|
|
|
67
|
+
### Optional permission overrides
|
|
68
|
+
|
|
69
|
+
By default, `installation-read` grants read the app installation's current permission envelope once per process and scopes read-capable permissions down to `read` when requesting a token. To declare the GitHub App permission envelope in the plugin and avoid that installation lookup, pass `appPermissions` when registering the plugin:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
githubPlugin({
|
|
73
|
+
appPermissions: {
|
|
74
|
+
actions: "write",
|
|
75
|
+
contents: "write",
|
|
76
|
+
issues: "write",
|
|
77
|
+
metadata: "read",
|
|
78
|
+
pull_requests: "write",
|
|
79
|
+
workflows: "write",
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Junior records these permissions as plugin capabilities. The configured values are the maximum GitHub App envelope Junior may need for writes. Installation-read token requests remain read-only by requesting read-capable configured permissions at `read` level and omitting GitHub permission fields that have no `read` value. GitHub remains the source of truth for whether a permission name or level exists.
|
|
85
|
+
|
|
86
|
+
GitHub App user-to-server tokens do not use OAuth scopes as their permission model. Their effective access is limited by the GitHub App's installed permissions, the app installation's repository access, and the requesting user's own GitHub access. GitHub returns an empty `scope` value for these tokens, so Junior cannot verify granted scopes from the token response.
|
|
87
|
+
|
|
88
|
+
If you pass `additionalUserScopes`, Junior includes those values in the authorization URL and records the requested scope string as a local reauthorization contract. This does not expand or prove GitHub API permissions — configure GitHub App permissions with `appPermissions` and in the GitHub App settings for provider-enforced access:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
githubPlugin({
|
|
92
|
+
additionalUserScopes: ["read:org", "workflow"],
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Use `additionalUserScopes` only when an integration flow requires specific GitHub OAuth scope parameters in the authorization URL. Do not rely on it to authorize repository, Actions, or workflow writes — those are enforced by GitHub App permissions and the requesting user's own access.
|
|
97
|
+
|
|
64
98
|
## 3) Runtime behavior
|
|
65
99
|
|
|
66
100
|
- When either GitHub skill is active, authenticated `gh` and `git` commands cause the runtime to inject GitHub credentials automatically for the current turn.
|
|
67
|
-
-
|
|
101
|
+
- The plugin classifies GitHub traffic from the forwarded HTTP request. Safe app-readable API methods, GraphQL `GET`/`HEAD`/`OPTIONS` requests, GraphQL `POST` bodies that prove the operation is a query, and `git-upload-pack` use the `installation-read` grant. `GET /user` uses the `user-read` grant so account identity checks use the requester token. Write-specific REST URLs, GraphQL mutations/subscriptions, unknown GraphQL `POST` bodies, other non-read API methods, and `git-receive-pack` use the `user-write` grant.
|
|
102
|
+
- `user-read` and `user-write` require the requester, or an explicitly delegated user subject from an allowed system run, to authorize the GitHub App through the private OAuth flow. Missing or expired user authorization pauses interactive turns, sends a private authorization link, and resumes after approval.
|
|
103
|
+
- Git commits use the requester as the commit author, Junior as committer, and a Junior `Co-Authored-By` trailer.
|
|
104
|
+
- Issued credentials are reused only within the current turn, credential leases are cached separately by plugin grant name, and upstream 403 permission denials clear the cached lease before the next retry.
|
|
68
105
|
- Sandbox does not receive raw tokens via env; host applies Authorization header transforms for GitHub API calls.
|
|
69
106
|
|
|
70
107
|
## 4) CLI usage
|
|
@@ -84,16 +121,25 @@ git -C repo fetch --depth=50 origin
|
|
|
84
121
|
git -C repo fetch --unshallow
|
|
85
122
|
```
|
|
86
123
|
|
|
87
|
-
|
|
124
|
+
Load the relevant GitHub skill for command guidance and repo context:
|
|
88
125
|
|
|
89
126
|
```bash
|
|
90
127
|
gh issue create --repo owner/repo --title "Example issue" --body-file /vercel/sandbox/tmp/issue.md
|
|
91
128
|
```
|
|
92
129
|
|
|
93
130
|
`gh` supports either direct `GITHUB_TOKEN` (for local debugging) or sandbox-level header injection.
|
|
94
|
-
The
|
|
131
|
+
The plugin uses `installation-read` for read-only GitHub traffic and `user-write` for mutations. GitHub App permissions still need to cover the operation: issues for issue edits/comments/labels, contents for pushes and merges, pull requests for PR mutations, actions/workflows for workflow operations.
|
|
132
|
+
|
|
133
|
+
Committing and pushing code uses more than one GitHub surface:
|
|
134
|
+
|
|
135
|
+
- Creating the local Git commit does not call GitHub. Junior sets the requester as author and the GitHub App bot as committer in the sandbox.
|
|
136
|
+
- Pushing a branch with Git smart HTTP (`git push`) uses the `user-write` grant and requires the GitHub App to have `Contents: write` on the target repository. The requesting user must also have write access to that repository.
|
|
137
|
+
- REST Git database writes used by some `gh` flows also require `Contents: write`: create blob (`POST /git/blobs`), create tree (`POST /git/trees`), create commit (`POST /git/commits`), and create/update refs (`POST /git/refs`, `PATCH /git/refs/{ref}`). Changes to workflow files may also require `Workflows: write`.
|
|
138
|
+
- Opening the PR after the branch exists is separate: `gh pr create --head` needs pull-request write permission, but it should not create or push commits itself.
|
|
139
|
+
|
|
140
|
+
Fork creation is not part of the default PR path. `POST /repos/{owner}/{repo}/forks` uses the `user-write` grant, but GitHub requires `Administration: write` and `Contents: read`, and the app must be installed on both the source and destination accounts. Do not grant `Administration: write` for routine PR creation; push a branch explicitly and create the PR with `--head` instead.
|
|
95
141
|
|
|
96
|
-
GitHub
|
|
142
|
+
GitHub App permission scoping is a safety rail, not a hard sandbox boundary. It helps prevent accidental write scope and wrong-repo mutations, and the host runtime still decides when to mint credentials. Credential injection is provider-domain scoped for sandbox traffic to `api.github.com` and `github.com` during turns with a signed credential context. Keep repo context explicit, and let the plugin choose the required grant for the outbound request.
|
|
97
143
|
|
|
98
144
|
Be careful with mixed-surface PR commands:
|
|
99
145
|
|
|
@@ -128,23 +174,24 @@ jr-rpc config set github.repo getsentry/junior
|
|
|
128
174
|
|
|
129
175
|
1. Confirm host env vars are present in prod:
|
|
130
176
|
- `GITHUB_APP_ID`
|
|
177
|
+
- `GITHUB_APP_CLIENT_ID`
|
|
178
|
+
- `GITHUB_APP_CLIENT_SECRET`
|
|
131
179
|
- `GITHUB_APP_PRIVATE_KEY`
|
|
132
180
|
- `GITHUB_INSTALLATION_ID`
|
|
133
181
|
2. Confirm the GitHub App is installed on your test repo with the permissions above.
|
|
134
182
|
3. Deploy `main` to prod.
|
|
135
183
|
4. Exercise `github-issues` to create an issue in a safe test repo.
|
|
136
|
-
5. Verify the issue is authored by the GitHub App
|
|
184
|
+
5. Verify the issue is authored by the requesting GitHub user with the GitHub App badge.
|
|
137
185
|
6. Exercise `github-issues` to update title/body, add/remove labels, and add a comment.
|
|
138
186
|
7. Push a test branch and exercise `github-code` to create a draft PR using explicit repo targeting and `--head`.
|
|
139
|
-
8. Verify all mutations succeed and are attributed to the app.
|
|
187
|
+
8. Verify all mutations succeed and are attributed to the requesting GitHub user with the app badge.
|
|
140
188
|
9. Verify GitHub API calls succeed while this skill is active without writing tokens into sandbox env/files.
|
|
141
189
|
10. Verify raw token values are never printed in output or logs.
|
|
142
190
|
11. Check logs for:
|
|
143
191
|
|
|
144
|
-
- `
|
|
145
|
-
- `
|
|
146
|
-
- `
|
|
147
|
-
- `credential_inject_cleanup`
|
|
192
|
+
- `sandbox_egress_upstream_request`
|
|
193
|
+
- `sandbox_egress_credential_needed`
|
|
194
|
+
- `sandbox_egress_upstream_auth_rejected`
|
|
148
195
|
|
|
149
196
|
12. Verify logs contain no token/private-key values.
|
|
150
197
|
13. Negative test: target a repo without app installation and confirm explicit failure.
|
package/index.d.ts
CHANGED
|
@@ -1,11 +1,51 @@
|
|
|
1
1
|
import type { JuniorPluginRegistration } from "@sentry/junior-plugin-api";
|
|
2
2
|
|
|
3
|
+
export type GitHubAppPermissionLevel = "read" | "write" | "admin";
|
|
4
|
+
|
|
5
|
+
/** Configure the built-in GitHub plugin manifest and hooks. */
|
|
3
6
|
export interface GitHubPluginOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Extra OAuth `scope` values to request during GitHub App user authorization.
|
|
9
|
+
*
|
|
10
|
+
* GitHub App user tokens report empty scopes, so Junior treats this as a
|
|
11
|
+
* local reauthorization contract only. Effective access still comes from the
|
|
12
|
+
* app permissions, installation repositories, and requesting user's access.
|
|
13
|
+
*/
|
|
14
|
+
additionalUserScopes?: string[];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* GitHub App installation permissions Junior should request for app tokens.
|
|
18
|
+
*
|
|
19
|
+
* Keys may use GitHub permission names with underscores or hyphens. Junior
|
|
20
|
+
* records these as plugin capabilities and requests read-only installation
|
|
21
|
+
* tokens by scoping read-capable permissions down to `read`.
|
|
22
|
+
* GitHub remains the source of truth for whether a permission exists.
|
|
23
|
+
*/
|
|
24
|
+
appPermissions?: Record<string, GitHubAppPermissionLevel>;
|
|
25
|
+
|
|
26
|
+
/** Environment variable containing the GitHub App id. */
|
|
27
|
+
appIdEnv?: string;
|
|
28
|
+
|
|
29
|
+
/** Environment variable containing Junior's Git committer email. */
|
|
4
30
|
botEmailEnv?: string;
|
|
31
|
+
|
|
32
|
+
/** Environment variable containing Junior's Git committer name. */
|
|
5
33
|
botNameEnv?: string;
|
|
34
|
+
|
|
35
|
+
/** Environment variable containing the GitHub App OAuth client id. */
|
|
36
|
+
clientIdEnv?: string;
|
|
37
|
+
|
|
38
|
+
/** Environment variable containing the GitHub App OAuth client secret. */
|
|
39
|
+
clientSecretEnv?: string;
|
|
40
|
+
|
|
41
|
+
/** Environment variable containing the GitHub App installation id. */
|
|
42
|
+
installationIdEnv?: string;
|
|
43
|
+
|
|
44
|
+
/** Environment variable containing the GitHub App private key. */
|
|
45
|
+
privateKeyEnv?: string;
|
|
6
46
|
}
|
|
7
47
|
|
|
8
|
-
/** Register GitHub manifest content and
|
|
48
|
+
/** Register GitHub manifest content and runtime hooks. */
|
|
9
49
|
export function githubPlugin(
|
|
10
50
|
options?: GitHubPluginOptions,
|
|
11
51
|
): JuniorPluginRegistration;
|