Repository navigation
feat(cli): Add token commands for org auth tokens #1647
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
sentry-junior
wants to merge
4
commits into
main
Choose a base branch
from
feat/cli-org-auth-tokens
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
a206a7f
feat(cli): Add token commands for org auth tokens
sentry-junior[bot] 0d5c11c
fix(cli): Name --dry-run when token delete can't re-authorize
sentry-junior[bot] ac0edfd
fix(cli): preserve token output and select target accounts
betegon cbb47a2
merge: sync main and adapt token command positionals
betegon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
|
|
||
|
|
||
| ## Permissions | ||
|
|
||
| Sentry only lets a CLI login from `sentry auth login` manage org auth tokens. | ||
| Personal tokens, org auth tokens, and `SENTRY_AUTH_TOKEN` can't create, list, | ||
| or revoke them. | ||
|
|
||
| The login also needs the `org:tokens` scope, which isn't part of the CLI's | ||
| default login. The first `sentry token` command asks you to re-authorize and | ||
| adds it. Creating a token also needs `org:ci`, because a login can only give a | ||
| new token scopes it holds itself, and revoking one needs `org:write` (org | ||
| owners and managers). | ||
|
|
||
| Re-authorization only happens in interactive runs: with `--yes`, `--json`, or | ||
| `--dry-run` the CLI never starts the authorization flow, so run a | ||
| `sentry token` command once without those flags first. | ||
|
|
||
| New tokens always get the `org:ci` scope. Sentry returns a token's value only | ||
| when it's created, so save it right away. | ||
|
|
||
| Self-hosted Sentry needs a version that supports the `org:tokens` scope. | ||
| Older servers reject the authorization request with an unknown-scope error. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
packages/cli/plugins/sentry-cli/skills/sentry-cli/references/token.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| --- | ||
| name: sentry-cli-token | ||
| version: 0.48.0-dev.0 | ||
| description: Manage org auth tokens | ||
| requires: | ||
| bins: ["sentry"] | ||
| auth: true | ||
| --- | ||
|
|
||
| # Token Commands | ||
|
|
||
| Manage org auth tokens | ||
|
|
||
| ### `sentry token list [<org>]` | ||
|
|
||
| List org auth tokens | ||
|
|
||
| **Arguments:** | ||
|
|
||
| | Argument | Description | | ||
| |----------|-------------| | ||
| | `[<org>]` | Organization slug (auto-detected if omitted) | | ||
|
|
||
| **JSON Fields** (use `--json --fields` to select specific fields): | ||
|
|
||
| | Field | Type | Description | | ||
| |-------|------|-------------| | ||
| | `id` | string | Token ID | | ||
| | `name` | string | Token name | | ||
| | `scopes` | array | Scopes granted to the token | | ||
| | `tokenLastCharacters` | string \| null | Last 4 characters of the token | | ||
| | `dateCreated` | string | Creation timestamp | | ||
| | `dateLastUsed` | string \| null | Last time the token was used, if ever | | ||
| | `projectLastUsedId` | string \| null | ID of the project the token was last used for | | ||
| | `token` | string | Full token value (create response only) | | ||
|
|
||
| **Examples:** | ||
|
|
||
| ```bash | ||
| # List tokens (auto-detect org) | ||
| sentry token list | ||
|
|
||
| # List tokens in a specific org | ||
| sentry token list my-org | ||
|
|
||
| # Output as JSON | ||
| sentry token list --json | ||
| ``` | ||
|
|
||
| ### `sentry token create <org/name>` | ||
|
|
||
| Create an org auth token | ||
|
|
||
| **Arguments:** | ||
|
|
||
| | Argument | Description | | ||
| |----------|-------------| | ||
| | `<org/name>` | [<org>/]<name> - Name of the new token | | ||
|
|
||
| **Flags:** | ||
| - `-n, --dry-run - Show what would happen without making changes` | ||
|
|
||
| **Examples:** | ||
|
|
||
| ```bash | ||
| # Create a token (auto-detect org) | ||
| sentry token create github-actions | ||
|
|
||
| # Create a token in a specific org | ||
| sentry token create my-org/github-actions | ||
|
|
||
| # Output as JSON, including the token value | ||
| sentry token create my-org/github-actions --json | ||
| ``` | ||
|
|
||
| ### `sentry token delete [<org>/]<token-id>` | ||
|
|
||
| Revoke an org auth token | ||
|
|
||
| **Destructive:** This command deletes data or makes changes that can't easily be undone. Use `--dry-run` to preview the changes first. Confirm with the user before running it. | ||
|
|
||
| **Arguments:** | ||
|
|
||
| | Argument | Description | | ||
| |----------|-------------| | ||
| | `[<org>/]<token-id>` | [<org>/]<token-id> - Token to revoke | | ||
|
|
||
| **Flags:** | ||
| - `-y, --yes - Skip confirmation prompt` | ||
| - `-f, --force - Force the operation without confirmation` | ||
| - `-n, --dry-run - Show what would happen without making changes` | ||
|
|
||
| **Examples:** | ||
|
|
||
| ```bash | ||
| # Revoke a token (auto-detect org) | ||
| sentry token delete 12345 | ||
|
|
||
| # Preview revoking a token | ||
| sentry token delete my-org/12345 --dry-run | ||
|
|
||
| # Revoke without the confirmation prompt | ||
| sentry token delete my-org/12345 --yes | ||
| ``` | ||
|
|
||
| All commands also support `--json`, `--fields`, `--help`, `--log-level`, and `--verbose` flags. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| /** | ||
| * sentry token create | ||
| * | ||
| * Create an org auth token (`org:ci`) and print its value. Sentry only | ||
| * returns the value in the create response. | ||
| */ | ||
|
|
||
| import type { SentryContext } from "../../context.js"; | ||
| import { createOrgAuthToken } from "../../lib/api-client.js"; | ||
| import { buildCommand } from "../../lib/command.js"; | ||
| import { ORG_TARGET } from "../../lib/completion-target.js"; | ||
| import { selectAccountForOrg } from "../../lib/db/auth.js"; | ||
| import { | ||
| escapeMarkdownInline, | ||
| mdKvTable, | ||
| renderMarkdown, | ||
| safeCodeSpan, | ||
| } from "../../lib/formatters/markdown.js"; | ||
| import { CommandOutput } from "../../lib/formatters/output.js"; | ||
| import { DRY_RUN_ALIASES, DRY_RUN_FLAG } from "../../lib/mutate-command.js"; | ||
| import { | ||
| type BoundPositional, | ||
| boundPositional, | ||
| } from "../../lib/positional-parse.js"; | ||
| import { resolveOrgInput } from "../../lib/target-positional.js"; | ||
| import type { OrgAuthToken } from "../../types/index.js"; | ||
| import { | ||
| CREATE_SCOPES, | ||
| ensureTokenScopes, | ||
| explainTokenForbidden, | ||
| parseOrgScopedArg, | ||
| } from "./shared.js"; | ||
|
|
||
| const USAGE_HINT = "sentry token create [<org>/]<name>"; | ||
|
|
||
| type CreateFlags = { | ||
| readonly "dry-run": boolean; | ||
| readonly json: boolean; | ||
| readonly fields?: string[]; | ||
| }; | ||
|
|
||
| type CreateResult = | ||
| | { dryRun: true; org: string; name: string } | ||
| | (OrgAuthToken & { dryRun?: false; org: string }); | ||
|
|
||
| /** A token name bound to the organization where it will be created. */ | ||
| type TokenCreateTarget = BoundPositional< | ||
| ReturnType<typeof parseOrgScopedArg>, | ||
| { readonly name: string; readonly org: string } | ||
| >; | ||
|
|
||
| function formatTokenCreated(result: CreateResult): string { | ||
| if (result.dryRun) { | ||
| return renderMarkdown( | ||
| `Would create org auth token ${safeCodeSpan(result.name)} in **${escapeMarkdownInline(result.org)}**. (dry run)`, | ||
| ); | ||
| } | ||
| const rows: [string, string][] = [ | ||
| ["Name", escapeMarkdownInline(result.name)], | ||
| ["ID", result.id], | ||
| ["Scopes", result.scopes.join(", ")], | ||
| ]; | ||
| // Keep the one-time secret outside the table, which hard-wraps long cells. | ||
| const token = result.token | ||
| ? `\n\nToken:\n\n${safeCodeSpan(result.token)}` | ||
| : ""; | ||
| return renderMarkdown( | ||
| `## Org auth token created in ${escapeMarkdownInline(result.org)}\n\n${mdKvTable(rows)}${token}`, | ||
| ); | ||
| } | ||
|
|
||
| export const createCommand = buildCommand({ | ||
| docs: { | ||
| brief: "Create an org auth token", | ||
| fullDescription: | ||
| "Create an org auth token with the org:ci scope, for uploading source maps, " + | ||
| "debug files, and releases from CI.\n\n" + | ||
| "The token value is printed once. Sentry doesn't store it, so save it now.\n\n" + | ||
| "Use `org/name` to pick the org: everything before the first `/` is the org " + | ||
| "slug. Add the org when the name itself contains a `/`.\n\n" + | ||
| "Needs a CLI login (`sentry auth login`). The first run asks you to " + | ||
| "re-authorize so the login can manage org auth tokens (interactive runs " + | ||
| "only; skipped with --json).", | ||
| examples: [ | ||
| { | ||
| description: "Create a token (auto-detect org)", | ||
| command: "sentry token create github-actions", | ||
| }, | ||
| { | ||
| description: "Create a token in a specific org", | ||
| command: "sentry token create my-org/github-actions", | ||
| }, | ||
| { | ||
| description: "Output as JSON, including the token value", | ||
| command: "sentry token create my-org/github-actions --json", | ||
| }, | ||
| ], | ||
| }, | ||
| output: { | ||
| human: formatTokenCreated, | ||
| }, | ||
| parameters: { | ||
| positional: { | ||
| kind: "tuple", | ||
| parameters: [ | ||
| { | ||
| placeholder: "org/name", | ||
| brief: "[<org>/]<name> - Name of the new token", | ||
| parse: boundPositional( | ||
| ORG_TARGET, | ||
| (raw) => parseOrgScopedArg(raw, "Token name", USAGE_HINT), | ||
| async ({ value: name, orgSlug }, context: SentryContext) => { | ||
| const { org } = await resolveOrgInput( | ||
| { org: orgSlug }, | ||
| context.cwd, | ||
| USAGE_HINT, | ||
| ); | ||
| return { name, org }; | ||
| }, | ||
| ), | ||
| }, | ||
| ], | ||
| }, | ||
| flags: { | ||
| "dry-run": DRY_RUN_FLAG, | ||
| }, | ||
| aliases: { ...DRY_RUN_ALIASES }, | ||
| }, | ||
| async *func( | ||
| this: SentryContext, | ||
| flags: CreateFlags, | ||
| target: TokenCreateTarget, | ||
| ) { | ||
| const { name, org } = await target.resolved; | ||
|
|
||
| if (flags["dry-run"]) { | ||
| yield new CommandOutput<CreateResult>({ dryRun: true, org, name }); | ||
| return { hint: "Dry run — no token was created." }; | ||
| } | ||
|
|
||
| selectAccountForOrg(org); | ||
| const scopeMissing = await ensureTokenScopes( | ||
| CREATE_SCOPES, | ||
| "Creating an org auth token", | ||
| ); | ||
|
|
||
| let token: OrgAuthToken; | ||
| try { | ||
| token = await createOrgAuthToken(org, name); | ||
| } catch (error) { | ||
| throw explainTokenForbidden(error, CREATE_SCOPES, scopeMissing); | ||
| } | ||
|
|
||
| yield new CommandOutput<CreateResult>({ ...token, org }); | ||
| return { | ||
| hint: "Save the token now. Sentry can't show it again.", | ||
| }; | ||
| }, | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.