Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 84 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

env:
# Commit timestamp used for deterministic nightly version strings.
# Defined at workflow level so build-binary and publish-nightly always agree.
COMMIT_TIMESTAMP: ${{ github.event.head_commit.timestamp }}

jobs:
changes:
name: Detect Changes
Expand Down Expand Up @@ -178,6 +183,20 @@ jobs:
done
echo "All install attempts failed"
exit 1
- name: Set nightly version
# Inject a nightly version into package.json before the build so it gets
# baked into the binary. Only runs on direct pushes to main.
# Uses the commit timestamp (seconds since epoch) as a deterministic
# value so every matrix leg and publish-nightly produce the same version
# string for a given commit.
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
shell: bash
run: |
TS=$(date -d "$COMMIT_TIMESTAMP" +%s 2>/dev/null || date -jf "%Y-%m-%dT%H:%M:%SZ" "$COMMIT_TIMESTAMP" +%s)
CURRENT=$(jq -r .version package.json)
NIGHTLY=$(echo "$CURRENT" | sed "s/-dev\.[0-9]*$/-dev.${TS}/")
jq --arg v "$NIGHTLY" '.version = $v' package.json > package.json.tmp
mv package.json.tmp package.json
- name: Build
env:
SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }}
Expand Down Expand Up @@ -282,17 +301,80 @@ jobs:
name: gh-pages
path: gh-pages.zip

publish-nightly:
name: Publish Nightly
# Only publish after a successful main-branch build+test. Skipped on PRs
# and release branches.
needs: [build-binary, test-e2e]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: package.json
- name: Compute nightly version
# Uses the commit timestamp — the same value as build-binary — so
# version.json exactly matches the version baked into the binaries.
id: version
run: |
TS=$(date -d "$COMMIT_TIMESTAMP" +%s)
CURRENT=$(jq -r .version package.json)
VERSION=$(echo "$CURRENT" | sed "s/-dev\.[0-9]*$/-dev.${TS}/")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Download all binary artifacts
uses: actions/download-artifact@v4
with:
pattern: sentry-*
path: artifacts
merge-multiple: true
- name: Create version.json
run: |
cat > version.json <<EOF
{"version":"${{ steps.version.outputs.version }}","sha":"${{ github.sha }}","date":"$(date -u +%Y-%m-%dT%H:%M:%SZ)"}
EOF
- name: Create or update nightly release
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
# Create the release the first time; subsequent runs are a no-op
gh release create nightly \
--prerelease \
--title "Nightly" \
--notes "" \
2>/dev/null || true

# Update release notes with the latest version + commit
gh release edit nightly \
--prerelease \
--notes "Latest nightly build from the \`main\` branch.

**Version:** \`${{ steps.version.outputs.version }}\`
**Commit:** ${{ github.sha }}"

# Delete all existing assets first so removed/renamed files don't linger
gh release view nightly --json assets --jq '.assets[].name' | while read -r name; do
gh release delete-asset nightly "$name" --yes
done

# Upload the new .gz binaries and the version manifest
gh release upload nightly \
artifacts/dist-bin/*.gz \
version.json

ci-status:
name: CI Status
if: always()
needs: [changes, check-skill, build-binary, build-npm, build-docs, test-e2e]
needs: [changes, check-skill, build-binary, build-npm, build-docs, test-e2e, publish-nightly]
runs-on: ubuntu-latest
permissions: {}
steps:
- name: Check CI status
run: |
# Check for explicit failures or cancellations in all jobs
results="${{ needs.check-skill.result }} ${{ needs.build-binary.result }} ${{ needs.build-npm.result }} ${{ needs.build-docs.result }} ${{ needs.test-e2e.result }}"
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 }}"
for result in $results; do
if [[ "$result" == "failure" || "$result" == "cancelled" ]]; then
echo "::error::CI failed"
Expand Down
56 changes: 52 additions & 4 deletions docs/src/content/docs/commands/cli/upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,37 @@ Self-update the Sentry CLI to the latest or a specific version.
## Usage

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

## Options

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

## Release Channels

The CLI supports two release channels:

| Channel | Description |
|---------|-------------|
| `stable` | Latest stable release (default) |
| `nightly` | Built from `main`, updated on every commit |

The chosen channel is persisted locally so that subsequent bare `sentry cli upgrade`
calls use the same channel without requiring a flag.

## Installation Detection

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

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

## Examples

### Check for updates
Expand All @@ -46,12 +68,13 @@ sentry cli upgrade --check
```
Installation method: curl
Current version: 0.4.0
Channel: stable
Latest version: 0.5.0

Run 'sentry cli upgrade' to update.
```

### Upgrade to latest
### Upgrade to latest stable

```bash
sentry cli upgrade
Expand All @@ -60,19 +83,44 @@ sentry cli upgrade
```
Installation method: curl
Current version: 0.4.0
Channel: stable
Latest version: 0.5.0

Upgrading to 0.5.0...

Successfully upgraded to 0.5.0.
```

### Switch to nightly channel

```bash
sentry cli upgrade nightly
# or equivalently:
sentry cli upgrade --channel nightly
```

After switching, bare `sentry cli upgrade` will continue tracking nightly.

### Switch back to stable

```bash
sentry cli upgrade stable
# or equivalently:
sentry cli upgrade --channel stable
```

### Upgrade to specific version

```bash
sentry cli upgrade 0.5.0
```

### Force re-download

```bash
sentry cli upgrade --force
```

### Force installation method

If auto-detection fails or you want to switch installation methods:
Expand Down
11 changes: 10 additions & 1 deletion docs/src/content/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,21 @@ import PackageManagerCode from "../../components/PackageManagerCode.astro";

### Install Script

Install the Sentry CLI using the install script:
Install the latest stable release:

```bash
curl https://cli.sentry.dev/install -fsS | bash
```

Install the nightly build (built from `main`, updated on every commit):

```bash
curl https://cli.sentry.dev/install -fsS | bash -s -- --version nightly
```

The chosen channel is persisted so that `sentry cli upgrade` automatically
tracks the same channel on future updates.

### Homebrew

```bash
Expand Down
36 changes: 31 additions & 5 deletions install
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Usage: install [options]

Options:
-h, --help Display this help message
-v, --version <version> Install a specific version (e.g., 0.2.0)
-v, --version <version> Install a specific version (e.g., 0.2.0) or "nightly"
--no-modify-path Don't modify shell config files (.zshrc, .bashrc, etc.)
--no-completions Don't install shell completions

Expand All @@ -22,6 +22,7 @@ Environment Variables:

Examples:
curl -fsSL https://cli.sentry.dev/install | bash
curl -fsSL https://cli.sentry.dev/install | bash -s -- --version nightly
curl -fsSL https://cli.sentry.dev/install | bash -s -- --version 0.2.0
SENTRY_INSTALL_DIR=~/.local/bin curl -fsSL https://cli.sentry.dev/install | bash
EOF
Expand Down Expand Up @@ -80,21 +81,38 @@ if [[ "$os" == "windows" ]]; then
fi
fi

# Resolve version
# Resolve version and download tag.
#
# "nightly" is a special value that installs from the rolling nightly prerelease
# built from the main branch. In this case both `version` and `download_tag`
# are set to the literal string "nightly".
#
# For stable releases both are the same version string (e.g. "0.5.0").
channel="stable"
download_tag=""

if [[ -z "$requested_version" ]]; then
version=$(curl -fsSL https://api.github.com/repos/getsentry/cli/releases/latest | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')
if [[ -z "$version" ]]; then
echo -e "${RED}Failed to fetch latest version${NC}"
exit 1
fi
download_tag="$version"
elif [[ "$requested_version" == "nightly" ]]; then
channel="nightly"
download_tag="nightly"
version="nightly"
else
version="$requested_version"
download_tag="$requested_version"
fi

# Strip leading 'v' if present (releases use version without 'v' prefix)
version="${version#v}"
download_tag="${download_tag#v}"

filename="sentry-${os}-${arch}${suffix}"
url="https://github.com/getsentry/cli/releases/download/${version}/${filename}"
url="https://github.com/getsentry/cli/releases/download/${download_tag}/${filename}"

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

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

# Try gzip-compressed download first (~60% smaller, ~37 MB vs ~99 MB).
# gunzip is POSIX and available on all Unix systems.
Expand All @@ -119,7 +143,9 @@ chmod +x "$tmp_binary"
# Delegate installation and configuration to the binary itself.
# setup --install handles: directory selection, binary placement, PATH,
# completions, agent skills, and the welcome message.
setup_args="--install --method curl"
# --channel persists the release channel so future `sentry cli upgrade`
# calls track the same channel without requiring a flag.
setup_args="--install --method curl --channel $channel"
if [[ "$no_modify_path" == "true" ]]; then
setup_args="$setup_args --no-modify-path"
fi
Expand Down
3 changes: 3 additions & 0 deletions plugins/sentry-cli/skills/sentry-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The CLI must be installed and authenticated before use.

```bash
curl https://cli.sentry.dev/install -fsS | bash
curl https://cli.sentry.dev/install -fsS | bash -s -- --version nightly
brew install getsentry/tools/sentry

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

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

### Repo
Expand Down
Loading
Loading