Skip to content

Commit 3670887

Browse files
feat(upgrade): add nightly release channel (#292)
## Summary - Add a **nightly release channel** that tracks rolling builds from \`main\`, versioned as \`0.x.y-dev.<unix_seconds>\` - Users opt in via \`sentry cli upgrade nightly\` or \`curl ... | bash -s -- --version nightly\`; the channel is persisted so future \`sentry cli upgrade\` calls track the same channel automatically - Add \`--force\` flag to re-download even when already up to date ## Changes **CI** — three new/modified jobs in \`ci.yml\`: - \`nightly-version\`: computes the nightly version string on \`main\` pushes (skipped on PRs — skipped ≠ failed) - \`build-binary\`: injects the nightly version into \`package.json\` before building when on \`main\` - \`publish-nightly\`: after build+E2E pass on \`main\`, uploads \`.gz\` binaries + \`version.json\` to a rolling GitHub prerelease tagged \`nightly\` via \`gh release upload --clobber\` **Install script** — \`--version nightly\` downloads from the \`nightly\` tag, fetches \`version.json\` for the display version, passes \`--channel nightly\` to \`cli setup\` to persist the preference **DB** — new \`src/lib/db/release-channel.ts\`: \`getReleaseChannel()\` / \`setReleaseChannel()\` / \`parseReleaseChannel()\` using the existing \`metadata\` table (no migration needed) **\`cli setup\`** — new \`--channel\` flag persists the channel on install (used by the install script and upgrade auto-migration) **\`cli upgrade\`** — \`nightly\`/\`stable\` as positional version args switch channels (no separate \`--channel\` flag needed); new \`--force\` flag; auto-migrates brew/npm/pnpm/bun/yarn installs to a standalone binary when switching to nightly (with a warning about the old install) **Version check** — reads persisted channel; fetches \`version.json\` from the nightly release for nightly users; shows "New nightly available:" in the update notification ## Testing - 11 new unit tests in \`test/lib/db/release-channel.test.ts\` - \`bun run typecheck\` passes clean - \`bun run lint\` passes clean - \`bun test test/lib/db/ test/lib/version-check.test.ts\` — 156 tests passing --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent ddd62af commit 3670887

17 files changed

Lines changed: 1813 additions & 106 deletions

File tree

.github/workflows/ci.yml

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ concurrency:
1010
group: ci-${{ github.ref }}
1111
cancel-in-progress: true
1212

13+
env:
14+
# Commit timestamp used for deterministic nightly version strings.
15+
# Defined at workflow level so build-binary and publish-nightly always agree.
16+
COMMIT_TIMESTAMP: ${{ github.event.head_commit.timestamp }}
17+
1318
jobs:
1419
changes:
1520
name: Detect Changes
@@ -178,6 +183,20 @@ jobs:
178183
done
179184
echo "All install attempts failed"
180185
exit 1
186+
- name: Set nightly version
187+
# Inject a nightly version into package.json before the build so it gets
188+
# baked into the binary. Only runs on direct pushes to main.
189+
# Uses the commit timestamp (seconds since epoch) as a deterministic
190+
# value so every matrix leg and publish-nightly produce the same version
191+
# string for a given commit.
192+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
193+
shell: bash
194+
run: |
195+
TS=$(date -d "$COMMIT_TIMESTAMP" +%s 2>/dev/null || date -jf "%Y-%m-%dT%H:%M:%SZ" "$COMMIT_TIMESTAMP" +%s)
196+
CURRENT=$(jq -r .version package.json)
197+
NIGHTLY=$(echo "$CURRENT" | sed "s/-dev\.[0-9]*$/-dev.${TS}/")
198+
jq --arg v "$NIGHTLY" '.version = $v' package.json > package.json.tmp
199+
mv package.json.tmp package.json
181200
- name: Build
182201
env:
183202
SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }}
@@ -282,17 +301,80 @@ jobs:
282301
name: gh-pages
283302
path: gh-pages.zip
284303

304+
publish-nightly:
305+
name: Publish Nightly
306+
# Only publish after a successful main-branch build+test. Skipped on PRs
307+
# and release branches.
308+
needs: [build-binary, test-e2e]
309+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
310+
runs-on: ubuntu-latest
311+
permissions:
312+
contents: write
313+
steps:
314+
- uses: actions/checkout@v4
315+
with:
316+
sparse-checkout: package.json
317+
- name: Compute nightly version
318+
# Uses the commit timestamp — the same value as build-binary — so
319+
# version.json exactly matches the version baked into the binaries.
320+
id: version
321+
run: |
322+
TS=$(date -d "$COMMIT_TIMESTAMP" +%s)
323+
CURRENT=$(jq -r .version package.json)
324+
VERSION=$(echo "$CURRENT" | sed "s/-dev\.[0-9]*$/-dev.${TS}/")
325+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
326+
- name: Download all binary artifacts
327+
uses: actions/download-artifact@v4
328+
with:
329+
pattern: sentry-*
330+
path: artifacts
331+
merge-multiple: true
332+
- name: Create version.json
333+
run: |
334+
cat > version.json <<EOF
335+
{"version":"${{ steps.version.outputs.version }}","sha":"${{ github.sha }}","date":"$(date -u +%Y-%m-%dT%H:%M:%SZ)"}
336+
EOF
337+
- name: Create or update nightly release
338+
env:
339+
GH_TOKEN: ${{ github.token }}
340+
GH_REPO: ${{ github.repository }}
341+
run: |
342+
# Create the release the first time; subsequent runs are a no-op
343+
gh release create nightly \
344+
--prerelease \
345+
--title "Nightly" \
346+
--notes "" \
347+
2>/dev/null || true
348+
349+
# Update release notes with the latest version + commit
350+
gh release edit nightly \
351+
--prerelease \
352+
--notes "Latest nightly build from the \`main\` branch.
353+
354+
**Version:** \`${{ steps.version.outputs.version }}\`
355+
**Commit:** ${{ github.sha }}"
356+
357+
# Delete all existing assets first so removed/renamed files don't linger
358+
gh release view nightly --json assets --jq '.assets[].name' | while read -r name; do
359+
gh release delete-asset nightly "$name" --yes
360+
done
361+
362+
# Upload the new .gz binaries and the version manifest
363+
gh release upload nightly \
364+
artifacts/dist-bin/*.gz \
365+
version.json
366+
285367
ci-status:
286368
name: CI Status
287369
if: always()
288-
needs: [changes, check-skill, build-binary, build-npm, build-docs, test-e2e]
370+
needs: [changes, check-skill, build-binary, build-npm, build-docs, test-e2e, publish-nightly]
289371
runs-on: ubuntu-latest
290372
permissions: {}
291373
steps:
292374
- name: Check CI status
293375
run: |
294376
# Check for explicit failures or cancellations in all jobs
295-
results="${{ needs.check-skill.result }} ${{ needs.build-binary.result }} ${{ needs.build-npm.result }} ${{ needs.build-docs.result }} ${{ needs.test-e2e.result }}"
377+
results="${{ needs.check-skill.result }} ${{ needs.build-binary.result }} ${{ needs.build-npm.result }} ${{ needs.build-docs.result }} ${{ needs.test-e2e.result }} ${{ needs.publish-nightly.result }}"
296378
for result in $results; do
297379
if [[ "$result" == "failure" || "$result" == "cancelled" ]]; then
298380
echo "::error::CI failed"

docs/src/content/docs/commands/cli/upgrade.md

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,37 @@ Self-update the Sentry CLI to the latest or a specific version.
88
## Usage
99

1010
```bash
11-
sentry cli upgrade # Update to latest version
12-
sentry cli upgrade 0.5.0 # Update to specific version
11+
sentry cli upgrade # Update using the persisted channel (default: stable)
12+
sentry cli upgrade nightly # Switch to nightly channel and update
13+
sentry cli upgrade stable # Switch back to stable channel and update
14+
sentry cli upgrade 0.5.0 # Update to a specific stable version
1315
sentry cli upgrade --check # Check for updates without installing
16+
sentry cli upgrade --force # Force re-download even if already up to date
1417
sentry cli upgrade --method npm # Force using npm to upgrade
1518
```
1619

1720
## Options
1821

1922
| Option | Description |
2023
|--------|-------------|
21-
| `<version>` | Target version to install (defaults to latest) |
24+
| `<version>` | Target version, or `nightly`/`stable` to switch channel (defaults to latest) |
2225
| `--check` | Check for updates without installing |
26+
| `--force` | Re-download even if already on the latest version |
27+
| `--channel <channel>` | Set release channel: `stable` or `nightly` |
2328
| `--method <method>` | Force installation method: curl, brew, npm, pnpm, bun, yarn |
2429

30+
## Release Channels
31+
32+
The CLI supports two release channels:
33+
34+
| Channel | Description |
35+
|---------|-------------|
36+
| `stable` | Latest stable release (default) |
37+
| `nightly` | Built from `main`, updated on every commit |
38+
39+
The chosen channel is persisted locally so that subsequent bare `sentry cli upgrade`
40+
calls use the same channel without requiring a flag.
41+
2542
## Installation Detection
2643

2744
The CLI auto-detects how it was installed and uses the same method to upgrade:
@@ -35,6 +52,11 @@ The CLI auto-detects how it was installed and uses the same method to upgrade:
3552
| bun | Globally installed via `bun install -g sentry` |
3653
| yarn | Globally installed via `yarn global add sentry` |
3754

55+
> **Note:** Nightly builds are only available as standalone binaries (via the curl
56+
> install method). If you switch to the nightly channel from a package manager or
57+
> Homebrew install, the CLI will automatically migrate to a standalone binary and
58+
> warn you about the existing package-manager installation.
59+
3860
## Examples
3961

4062
### Check for updates
@@ -46,12 +68,13 @@ sentry cli upgrade --check
4668
```
4769
Installation method: curl
4870
Current version: 0.4.0
71+
Channel: stable
4972
Latest version: 0.5.0
5073
5174
Run 'sentry cli upgrade' to update.
5275
```
5376

54-
### Upgrade to latest
77+
### Upgrade to latest stable
5578

5679
```bash
5780
sentry cli upgrade
@@ -60,19 +83,44 @@ sentry cli upgrade
6083
```
6184
Installation method: curl
6285
Current version: 0.4.0
86+
Channel: stable
6387
Latest version: 0.5.0
6488
6589
Upgrading to 0.5.0...
6690
6791
Successfully upgraded to 0.5.0.
6892
```
6993

94+
### Switch to nightly channel
95+
96+
```bash
97+
sentry cli upgrade nightly
98+
# or equivalently:
99+
sentry cli upgrade --channel nightly
100+
```
101+
102+
After switching, bare `sentry cli upgrade` will continue tracking nightly.
103+
104+
### Switch back to stable
105+
106+
```bash
107+
sentry cli upgrade stable
108+
# or equivalently:
109+
sentry cli upgrade --channel stable
110+
```
111+
70112
### Upgrade to specific version
71113

72114
```bash
73115
sentry cli upgrade 0.5.0
74116
```
75117

118+
### Force re-download
119+
120+
```bash
121+
sentry cli upgrade --force
122+
```
123+
76124
### Force installation method
77125

78126
If auto-detection fails or you want to switch installation methods:

docs/src/content/docs/getting-started.mdx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,21 @@ import PackageManagerCode from "../../components/PackageManagerCode.astro";
99

1010
### Install Script
1111

12-
Install the Sentry CLI using the install script:
12+
Install the latest stable release:
1313

1414
```bash
1515
curl https://cli.sentry.dev/install -fsS | bash
1616
```
1717

18+
Install the nightly build (built from `main`, updated on every commit):
19+
20+
```bash
21+
curl https://cli.sentry.dev/install -fsS | bash -s -- --version nightly
22+
```
23+
24+
The chosen channel is persisted so that `sentry cli upgrade` automatically
25+
tracks the same channel on future updates.
26+
1827
### Homebrew
1928

2029
```bash

install

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Usage: install [options]
1313
1414
Options:
1515
-h, --help Display this help message
16-
-v, --version <version> Install a specific version (e.g., 0.2.0)
16+
-v, --version <version> Install a specific version (e.g., 0.2.0) or "nightly"
1717
--no-modify-path Don't modify shell config files (.zshrc, .bashrc, etc.)
1818
--no-completions Don't install shell completions
1919
@@ -22,6 +22,7 @@ Environment Variables:
2222
2323
Examples:
2424
curl -fsSL https://cli.sentry.dev/install | bash
25+
curl -fsSL https://cli.sentry.dev/install | bash -s -- --version nightly
2526
curl -fsSL https://cli.sentry.dev/install | bash -s -- --version 0.2.0
2627
SENTRY_INSTALL_DIR=~/.local/bin curl -fsSL https://cli.sentry.dev/install | bash
2728
EOF
@@ -80,21 +81,38 @@ if [[ "$os" == "windows" ]]; then
8081
fi
8182
fi
8283

83-
# Resolve version
84+
# Resolve version and download tag.
85+
#
86+
# "nightly" is a special value that installs from the rolling nightly prerelease
87+
# built from the main branch. In this case both `version` and `download_tag`
88+
# are set to the literal string "nightly".
89+
#
90+
# For stable releases both are the same version string (e.g. "0.5.0").
91+
channel="stable"
92+
download_tag=""
93+
8494
if [[ -z "$requested_version" ]]; then
8595
version=$(curl -fsSL https://api.github.com/repos/getsentry/cli/releases/latest | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')
8696
if [[ -z "$version" ]]; then
8797
echo -e "${RED}Failed to fetch latest version${NC}"
8898
exit 1
8999
fi
100+
download_tag="$version"
101+
elif [[ "$requested_version" == "nightly" ]]; then
102+
channel="nightly"
103+
download_tag="nightly"
104+
version="nightly"
90105
else
91106
version="$requested_version"
107+
download_tag="$requested_version"
92108
fi
93109

94110
# Strip leading 'v' if present (releases use version without 'v' prefix)
95111
version="${version#v}"
112+
download_tag="${download_tag#v}"
113+
96114
filename="sentry-${os}-${arch}${suffix}"
97-
url="https://github.com/getsentry/cli/releases/download/${version}/${filename}"
115+
url="https://github.com/getsentry/cli/releases/download/${download_tag}/${filename}"
98116

99117
# Download binary to a temp location
100118
tmpdir="${TMPDIR:-${TMP:-${TEMP:-/tmp}}}"
@@ -103,7 +121,13 @@ tmp_binary="${tmpdir}/sentry-install-$$${suffix}"
103121
# Clean up temp binary on failure (setup handles cleanup on success)
104122
trap 'rm -f "$tmp_binary"' EXIT
105123

106-
echo -e "${MUTED}Downloading sentry v${version}...${NC}"
124+
# For nightly the version string is literally "nightly", not a semver, so
125+
# skip the "v" prefix that's only meaningful for numbered releases.
126+
if [[ "$version" == "nightly" ]]; then
127+
echo -e "${MUTED}Downloading sentry nightly...${NC}"
128+
else
129+
echo -e "${MUTED}Downloading sentry v${version}...${NC}"
130+
fi
107131

108132
# Try gzip-compressed download first (~60% smaller, ~37 MB vs ~99 MB).
109133
# gunzip is POSIX and available on all Unix systems.
@@ -119,7 +143,9 @@ chmod +x "$tmp_binary"
119143
# Delegate installation and configuration to the binary itself.
120144
# setup --install handles: directory selection, binary placement, PATH,
121145
# completions, agent skills, and the welcome message.
122-
setup_args="--install --method curl"
146+
# --channel persists the release channel so future `sentry cli upgrade`
147+
# calls track the same channel without requiring a flag.
148+
setup_args="--install --method curl --channel $channel"
123149
if [[ "$no_modify_path" == "true" ]]; then
124150
setup_args="$setup_args --no-modify-path"
125151
fi

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The CLI must be installed and authenticated before use.
1515

1616
```bash
1717
curl https://cli.sentry.dev/install -fsS | bash
18+
curl https://cli.sentry.dev/install -fsS | bash -s -- --version nightly
1819
brew install getsentry/tools/sentry
1920

2021
# Or install via npm/pnpm/bun
@@ -426,6 +427,7 @@ Configure shell integration
426427
**Flags:**
427428
- `--install - Install the binary from a temp location to the system path`
428429
- `--method <value> - Installation method (curl, npm, pnpm, bun, yarn)`
430+
- `--channel <value> - Release channel to persist (stable or nightly)`
429431
- `--no-modify-path - Skip PATH modification`
430432
- `--no-completions - Skip shell completion installation`
431433
- `--no-agent-skills - Skip agent skill installation for AI coding assistants`
@@ -437,6 +439,7 @@ Update the Sentry CLI to the latest version
437439

438440
**Flags:**
439441
- `--check - Check for updates without installing`
442+
- `--force - Force upgrade even if already on the latest version`
440443
- `--method <value> - Installation method to use (curl, brew, npm, pnpm, bun, yarn)`
441444

442445
### Repo

0 commit comments

Comments
 (0)