Skip to content

Commit 35a46e3

Browse files
committed
feat(release): add release command group and CI finalization
Add `sentry release` command group with 8 subcommands for full release lifecycle management, plus a CI post-release script for automated finalization. Commands: list, view, create, finalize, delete, deploy, set-commits, propose-version. Supports --auto (repo integration) and --local (git history) modes for commit association via simple-git. CI integration: script/finalize-release.ts runs in .craft.yml postReleaseCommand before version bump to create, set commits, finalize, and deploy releases automatically. Ref: #600
1 parent 99be95c commit 35a46e3

File tree

35 files changed

+3778
-103
lines changed

35 files changed

+3778
-103
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Sentry Release
2+
on:
3+
release:
4+
types: [published]
5+
6+
permissions:
7+
contents: read
8+
9+
jobs:
10+
finalize:
11+
name: Finalize Sentry Release
12+
runs-on: ubuntu-latest
13+
# Skip pre-releases (nightlies, dev versions)
14+
if: "!github.event.release.prerelease"
15+
env:
16+
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
17+
# Tag names are bare semver (e.g., "0.24.0", no "v" prefix),
18+
# matching both the npm package version and Sentry release version.
19+
VERSION: ${{ github.event.release.tag_name }}
20+
steps:
21+
- name: Install CLI
22+
run: npm install -g "sentry@${VERSION}"
23+
24+
- name: Create release
25+
run: sentry release create "sentry/${VERSION}" --project cli
26+
27+
- name: Set commits
28+
continue-on-error: true
29+
run: sentry release set-commits "sentry/${VERSION}" --auto
30+
31+
- name: Finalize release
32+
run: sentry release finalize "sentry/${VERSION}"
33+
34+
- name: Create deploy
35+
run: sentry release deploy "sentry/${VERSION}" production

AGENTS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ bun run test:unit # Run unit tests only
6161
bun run test:e2e # Run e2e tests only
6262
```
6363

64+
## Rules: No Runtime Dependencies
65+
66+
**CRITICAL**: All packages must be in `devDependencies`, never `dependencies`. Everything is bundled at build time via esbuild. CI enforces this with `bun run check:deps`.
67+
68+
When adding a package, always use `bun add -d <package>` (the `-d` flag).
69+
70+
When the `@sentry/api` SDK provides types for an API response, import them directly from `@sentry/api` instead of creating redundant Zod schemas in `src/types/sentry.ts`.
71+
6472
## Rules: Use Bun APIs
6573

6674
**CRITICAL**: This project uses Bun as runtime. Always prefer Bun-native APIs over Node.js equivalents.

docs/public/.well-known/skills/index.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"references/logs.md",
1414
"references/organizations.md",
1515
"references/projects.md",
16+
"references/release.md",
1617
"references/setup.md",
1718
"references/sourcemap.md",
1819
"references/teams.md",
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
title: release
3+
description: Release commands for the Sentry CLI
4+
---
5+
6+
Work with Sentry releases
7+
8+
## Commands
9+
10+
### `sentry release list <org/project>`
11+
12+
List releases
13+
14+
### `sentry release view <org/version>`
15+
16+
View release details
17+
18+
### `sentry release create <org/version>`
19+
20+
Create a release
21+
22+
### `sentry release finalize <org/version>`
23+
24+
Finalize a release
25+
26+
### `sentry release delete <org/version>`
27+
28+
Delete a release
29+
30+
### `sentry release deploy <org/version> <environment> [name]`
31+
32+
Create a deploy for a release
33+
34+
### `sentry release set-commits <org/version>`
35+
36+
Set commits for a release
37+
38+
### `sentry release propose-version`
39+
40+
Propose a release version (outputs the current git HEAD SHA)
41+
42+
All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields.
43+
44+
<!-- GENERATED:END -->
45+
46+
## Examples
47+
48+
```bash
49+
# List releases (auto-detect org)
50+
sentry release list
51+
52+
# List releases in a specific org
53+
sentry release list my-org/
54+
55+
# View release details
56+
sentry release view 1.0.0
57+
sentry release view my-org/1.0.0
58+
59+
# Create and finalize a release
60+
sentry release create 1.0.0 --finalize
61+
62+
# Create a release, then finalize separately
63+
sentry release create 1.0.0
64+
sentry release set-commits 1.0.0 --auto
65+
sentry release finalize 1.0.0
66+
67+
# Set commits from local git history
68+
sentry release set-commits 1.0.0 --local
69+
70+
# Create a deploy
71+
sentry release deploy 1.0.0 production
72+
sentry release deploy 1.0.0 staging "Deploy #42"
73+
74+
# Propose a version from git HEAD
75+
sentry release create $(sentry release propose-version)
76+
77+
# Output as JSON
78+
sentry release list --json
79+
sentry release view 1.0.0 --json
80+
```

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"type": "git",
66
"url": "git+https://github.com/getsentry/cli.git"
77
},
8+
"main": "./dist/index.cjs",
89
"devDependencies": {
910
"@anthropic-ai/sdk": "^0.39.0",
1011
"@biomejs/biome": "2.3.8",
@@ -43,18 +44,16 @@
4344
"wrap-ansi": "^10.0.0",
4445
"zod": "^3.24.0"
4546
},
46-
"bin": {
47-
"sentry": "./dist/bin.cjs"
48-
},
49-
"main": "./dist/index.cjs",
50-
"types": "./dist/index.d.cts",
5147
"exports": {
5248
".": {
5349
"types": "./dist/index.d.cts",
5450
"require": "./dist/index.cjs",
5551
"default": "./dist/index.cjs"
5652
}
5753
},
54+
"bin": {
55+
"sentry": "./dist/bin.cjs"
56+
},
5857
"description": "Sentry CLI - A command-line interface for using Sentry built by robots and humans for robots and humans",
5958
"engines": {
6059
"node": ">=22"
@@ -94,5 +93,6 @@
9493
"check:deps": "bun run script/check-no-deps.ts",
9594
"check:errors": "bun run script/check-error-patterns.ts"
9695
},
97-
"type": "module"
96+
"type": "module",
97+
"types": "./dist/index.d.cts"
9898
}

plugins/sentry-cli/skills/sentry-cli/SKILL.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,22 @@ Manage Sentry dashboards
313313

314314
→ Full flags and examples: `references/dashboards.md`
315315

316+
### Release
317+
318+
Work with Sentry releases
319+
320+
- `sentry release list <org/project>` — List releases
321+
- `sentry release view <org/version...>` — View release details
322+
- `sentry release create <org/version...>` — Create a release
323+
- `sentry release finalize <org/version...>` — Finalize a release
324+
- `sentry release delete <org/version...>` — Delete a release
325+
- `sentry release deploy <org/version environment name...>` — Create a deploy for a release
326+
- `sentry release deploys <org/version...>` — List deploys for a release
327+
- `sentry release set-commits <org/version...>` — Set commits for a release
328+
- `sentry release propose-version` — Propose a release version
329+
330+
→ Full flags and examples: `references/release.md`
331+
316332
### Repo
317333

318334
Work with Sentry repositories
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
---
2+
name: sentry-cli-release
3+
version: 0.24.0-dev.0
4+
description: Sentry CLI release commands
5+
requires:
6+
bins: ["sentry"]
7+
auth: true
8+
---
9+
10+
# release Commands
11+
12+
Work with Sentry releases
13+
14+
### `sentry release list <org/project>`
15+
16+
List releases
17+
18+
**Flags:**
19+
- `-n, --limit <value> - Maximum number of releases to list - (default: "30")`
20+
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`
21+
- `-c, --cursor <value> - Navigate pages: "next", "prev", "first" (or raw cursor string)`
22+
23+
### `sentry release view <org/version...>`
24+
25+
View release details
26+
27+
**Flags:**
28+
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`
29+
30+
### `sentry release create <org/version...>`
31+
32+
Create a release
33+
34+
**Flags:**
35+
- `-p, --project <value> - Associate with project(s), comma-separated`
36+
- `--finalize - Immediately finalize the release (set dateReleased)`
37+
- `--ref <value> - Git ref (branch or tag name)`
38+
- `--url <value> - URL to the release source`
39+
- `-n, --dry-run - Show what would happen without making changes`
40+
41+
### `sentry release finalize <org/version...>`
42+
43+
Finalize a release
44+
45+
**Flags:**
46+
- `--released <value> - Custom release timestamp (ISO 8601). Defaults to now.`
47+
- `--url <value> - URL for the release`
48+
49+
### `sentry release delete <org/version...>`
50+
51+
Delete a release
52+
53+
**Flags:**
54+
- `-y, --yes - Skip confirmation prompt`
55+
- `-f, --force - Force the operation without confirmation`
56+
- `-n, --dry-run - Show what would happen without making changes`
57+
58+
### `sentry release deploy <org/version environment name...>`
59+
60+
Create a deploy for a release
61+
62+
**Flags:**
63+
- `--url <value> - URL for the deploy`
64+
- `--started <value> - Deploy start time (ISO 8601)`
65+
- `--finished <value> - Deploy finish time (ISO 8601)`
66+
- `-t, --time <value> - Deploy duration in seconds (sets started = now - time, finished = now)`
67+
68+
### `sentry release deploys <org/version...>`
69+
70+
List deploys for a release
71+
72+
### `sentry release set-commits <org/version...>`
73+
74+
Set commits for a release
75+
76+
**Flags:**
77+
- `--auto - Use repository integration to auto-discover commits`
78+
- `--local - Read commits from local git history`
79+
- `--clear - Clear all commits from the release`
80+
- `--commit <value> - Explicit commit as REPO@SHA or REPO@PREV..SHA (comma-separated)`
81+
- `--initial-depth <value> - Number of commits to read with --local - (default: "20")`
82+
83+
### `sentry release propose-version`
84+
85+
Propose a release version
86+
87+
**Examples:**
88+
89+
```bash
90+
# List releases (auto-detect org)
91+
sentry release list
92+
93+
# List releases in a specific org
94+
sentry release list my-org/
95+
96+
# View release details
97+
sentry release view 1.0.0
98+
sentry release view my-org/1.0.0
99+
100+
# Create and finalize a release
101+
sentry release create 1.0.0 --finalize
102+
103+
# Create a release, then finalize separately
104+
sentry release create 1.0.0
105+
sentry release set-commits 1.0.0 --auto
106+
sentry release finalize 1.0.0
107+
108+
# Set commits from local git history
109+
sentry release set-commits 1.0.0 --local
110+
111+
# Create a deploy
112+
sentry release deploy 1.0.0 production
113+
sentry release deploy 1.0.0 staging "Deploy #42"
114+
115+
# Propose a version from git HEAD
116+
sentry release create $(sentry release propose-version)
117+
118+
# Output as JSON
119+
sentry release list --json
120+
sentry release view 1.0.0 --json
121+
```
122+
123+
All commands also support `--json`, `--fields`, `--help`, `--log-level`, and `--verbose` flags.

script/generate-sdk.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,8 @@ for (const { path, command } of allCommands) {
556556
let body: string;
557557

558558
const brief = command.brief || path.join(" ");
559-
const methodName = path.at(-1) ?? path[0];
559+
const rawName = path.at(-1) ?? path[0];
560+
const methodName = needsQuoting(rawName) ? `"${rawName}"` : rawName;
560561
const indent = " ".repeat(path.length - 1);
561562

562563
if (hasVariadicPositional) {

src/app.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import { orgRoute } from "./commands/org/index.js";
2525
import { listCommand as orgListCommand } from "./commands/org/list.js";
2626
import { projectRoute } from "./commands/project/index.js";
2727
import { listCommand as projectListCommand } from "./commands/project/list.js";
28+
import { releaseRoute } from "./commands/release/index.js";
29+
import { listCommand as releaseListCommand } from "./commands/release/list.js";
2830
import { repoRoute } from "./commands/repo/index.js";
2931
import { listCommand as repoListCommand } from "./commands/repo/list.js";
3032
import { schemaCommand } from "./commands/schema.js";
@@ -61,6 +63,7 @@ const PLURAL_TO_SINGULAR: Record<string, string> = {
6163
issues: "issue",
6264
orgs: "org",
6365
projects: "project",
66+
releases: "release",
6467
repos: "repo",
6568
teams: "team",
6669
logs: "log",
@@ -79,6 +82,7 @@ export const routes = buildRouteMap({
7982
dashboard: dashboardRoute,
8083
org: orgRoute,
8184
project: projectRoute,
85+
release: releaseRoute,
8286
repo: repoRoute,
8387
team: teamRoute,
8488
issue: issueRoute,
@@ -96,6 +100,7 @@ export const routes = buildRouteMap({
96100
issues: issueListCommand,
97101
orgs: orgListCommand,
98102
projects: projectListCommand,
103+
releases: releaseListCommand,
99104
repos: repoListCommand,
100105
teams: teamListCommand,
101106
logs: logListCommand,
@@ -115,6 +120,7 @@ export const routes = buildRouteMap({
115120
issues: true,
116121
orgs: true,
117122
projects: true,
123+
releases: true,
118124
repos: true,
119125
teams: true,
120126
logs: true,

0 commit comments

Comments
 (0)