fix(devops): upload Rust debug symbols to Sentry during Tauri build (closes #627) (#890)

- Add Sentry debug symbol upload step to the CI pipeline for production builds.
- Implement a helper script for manual symbol uploads with OS and architecture detection.
- Configure automatic Sentry release creation and commit association on main branch pushes.
- Refine Sentry CLI parameters to correctly handle shallow clones and debug ID indexing.
- Initialize CHANGELOG.md to track project changes and infrastructure updates.
- Update workflow permissions to allow Sentry to read action metadata for commit mapping.

Closes #627

Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
This commit is contained in:
unn-Known1
2026-04-24 10:20:58 -07:00
committed by GitHub
co-authored by Steven Enamakel
parent 11c67a70b9
commit 9b1f4cdf71
3 changed files with 326 additions and 0 deletions
+36
View File
@@ -8,6 +8,8 @@ on:
permissions:
contents: read
pull-requests: read
# Required for Sentry to associate commits with releases
actions: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.head_ref || github.ref }}
@@ -87,3 +89,37 @@ jobs:
CARGO_PROFILE_RELEASE_LTO: "false"
CARGO_PROFILE_RELEASE_STRIP: "true"
CARGO_PROFILE_RELEASE_DEBUG: "false"
- name: Upload Rust debug symbols to Sentry
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ vars.SENTRY_ORG }}
SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }}
run: |
# Install sentry-cli if not available (container runs as root, no sudo needed)
if ! command -v sentry-cli &> /dev/null; then
curl -sSL https://github.com/getsentry/sentry-cli/releases/download/2.34.2/sentry-cli-Linux-x86_64 -o /tmp/sentry-cli
chmod +x /tmp/sentry-cli
mv /tmp/sentry-cli /usr/local/bin/sentry-cli
fi
# Create Sentry release and upload debug symbols
VERSION=$(grep -m1 '^version\s*=' app/src-tauri/Cargo.toml | sed 's/version\s*=\s*"\([^"]*\)"/\1/')
RELEASE="openhuman@${VERSION}"
echo "Creating Sentry release: ${RELEASE}"
sentry-cli releases new "${RELEASE}" || true
# Use --ignore-missing because fetch-depth: 1 means shallow clone
sentry-cli releases set-commits --auto --ignore-missing "${RELEASE}" || true
echo "Uploading debug symbols..."
# Debug symbols are indexed by debug-ID, not release-scoped, so no --release flag
sentry-cli upload-dif \
--org "$SENTRY_ORG" \
--project "$SENTRY_PROJECT" \
--log-level=warning \
app/src-tauri/target/release/deps/
sentry-cli releases finalize "${RELEASE}"
echo "Sentry symbol upload complete for ${RELEASE}"
+36
View File
@@ -0,0 +1,36 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- **DevOps**: Added Sentry debug symbol upload to CI/CD pipeline
- Rust debug symbols from Tauri build are now automatically uploaded to Sentry on every main branch push
- Creates and finalizes Sentry releases with proper version tagging (`openhuman@{version}`)
- Enables accurate stack trace symbolication for production releases
- Added `scripts/upload_sentry_symbols.sh` helper script for local symbol uploads
### Changed
- **CI**: Updated `build.yml` workflow to upload debug symbols after successful builds
- Symbol upload only triggers on main branch pushes (not PRs)
- Added `actions: read` permission for Sentry commit association
### Dependencies
- None
### Fixed
- None
---
## [0.52.28] - 2026-04-18
See [release notes](https://github.com/tinyhumansai/openhuman/releases/tag/v0.52.28) for details.
+254
View File
@@ -0,0 +1,254 @@
#!/usr/bin/env bash
# =============================================================================
# upload_sentry_symbols.sh
#
# Uploads Rust debug symbols and source maps to Sentry for the Tauri app.
# This enables proper stack trace symbolication in Sentry for production builds.
#
# Usage:
# ./scripts/upload_sentry_symbols.sh [version]
#
# Environment variables required:
# SENTRY_AUTH_TOKEN - Sentry authentication token (required)
# SENTRY_ORG - Sentry organization slug (required)
# SENTRY_PROJECT - Sentry project name (required)
#
# Optional environment variables:
# SENTRY_VERSION - Release version (defaults to: openhuman@{version})
# DEBUG_SYMBOLS_PATH - Path to debug symbols (defaults to: target/release/deps)
# =============================================================================
set -euo pipefail
# Color output helpers
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Validate required environment variables
check_env_vars() {
local missing_vars=()
if [[ -z "${SENTRY_AUTH_TOKEN:-}" ]]; then
missing_vars+=("SENTRY_AUTH_TOKEN")
fi
if [[ -z "${SENTRY_ORG:-}" ]]; then
missing_vars+=("SENTRY_ORG")
fi
if [[ -z "${SENTRY_PROJECT:-}" ]]; then
missing_vars+=("SENTRY_PROJECT")
fi
if [[ ${#missing_vars[@]} -gt 0 ]]; then
log_error "Missing required environment variables: ${missing_vars[*]}"
log_error "Please set these variables before running this script."
exit 1
fi
}
# Detect or install sentry-cli
ensure_sentry_cli() {
if command -v sentry-cli &> /dev/null; then
log_info "sentry-cli already installed: $(sentry-cli --version)"
return 0
fi
log_info "Installing sentry-cli..."
# Detect OS and architecture
local os_arch
case "$(uname -s)" in
Linux*)
case "$(uname -m)" in
x86_64|amd64)
os_arch="linux-x86_64"
;;
aarch64|arm64)
os_arch="linux-aarch64"
;;
*)
log_error "Unsupported architecture: $(uname -m)"
exit 1
;;
esac
;;
Darwin*)
case "$(uname -m)" in
x86_64|amd64)
os_arch="macos-x86_64"
;;
arm64)
os_arch="macos-arm64"
;;
*)
log_error "Unsupported architecture on macOS: $(uname -m)"
exit 1
;;
esac
;;
MINGW*|CYGWIN*|MSYS*)
os_arch="windows-x86_64"
;;
*)
log_error "Unsupported operating system: $(uname -s)"
exit 1
;;
esac
local version="2.34.2"
local download_url="https://github.com/getsentry/sentry-cli/releases/download/${version}/sentry-cli-${os_arch}"
# Create temporary directory for installation
local tmp_dir
tmp_dir=$(mktemp -d)
# Use single quotes to prevent early expansion (ShellCheck SC2064)
trap 'rm -rf $tmp_dir' EXIT
# Download and install
log_info "Downloading sentry-cli ${version} for ${os_arch}..."
if command -v curl &> /dev/null; then
curl -sSL "${download_url}" -o "${tmp_dir}/sentry-cli" || {
log_error "Failed to download sentry-cli"
exit 1
}
elif command -v wget &> /dev/null; then
wget -q "${download_url}" -O "${tmp_dir}/sentry-cli" || {
log_error "Failed to download sentry-cli"
exit 1
}
else
log_error "Neither curl nor wget found. Cannot download sentry-cli."
exit 1
fi
# Make executable and install to ~/.cargo/bin or /usr/local/bin
chmod +x "${tmp_dir}/sentry-cli"
local install_dir="${HOME}/.cargo/bin"
mkdir -p "${install_dir}"
if [[ -w "${install_dir}" ]]; then
mv "${tmp_dir}/sentry-cli" "${install_dir}/sentry-cli"
log_info "sentry-cli installed to ${install_dir}/sentry-cli"
else
# Fallback to /usr/local/bin (may require sudo)
if sudo mv "${tmp_dir}/sentry-cli" "/usr/local/bin/sentry-cli" 2>/dev/null; then
log_info "sentry-cli installed to /usr/local/bin/sentry-cli"
else
log_error "Cannot write to ${install_dir} or /usr/local/bin. Please install sentry-cli manually."
exit 1
fi
fi
# Update PATH hash for current session (won't persist without shell restart)
hash -r
}
# Upload debug symbols to Sentry
upload_symbols() {
local version="${1:-}"
local symbols_path="${2:-target/release/deps}"
if [[ -z "${version}" ]]; then
log_error "Version is required"
exit 1
fi
local release_name="openhuman@${version}"
log_info "Uploading Rust debug symbols for release: ${release_name}"
log_info "Symbols path: ${symbols_path}"
# Create Sentry release
log_info "Creating/updating Sentry release..."
sentry-cli releases new "${release_name}" || true
# Use --ignore-missing for shallow clones or CI environments
sentry-cli releases set-commits --auto --ignore-missing "${release_name}" || true
# Upload debug symbols
log_info "Uploading debug symbols..."
local upload_args=(
"upload-dif"
"--org" "${SENTRY_ORG}"
"--project" "${SENTRY_PROJECT}"
"--log-level=warning"
)
# Find and upload all debug symbol files
if [[ -d "${symbols_path}" ]]; then
# Upload .dwp (dwarf packages), .debug files, and .pdb files
# Debug symbols are indexed by debug-ID, not release-scoped
log_info "Scanning for debug symbols in ${symbols_path}..."
sentry-cli "${upload_args[@]}" "${symbols_path}" || {
log_warn "Some debug symbols may have failed to upload"
}
else
log_warn "Symbols path does not exist: ${symbols_path}"
log_info "Looking for any release artifacts..."
fi
# Finalize the release
log_info "Finalizing release..."
sentry-cli releases finalize "${release_name}"
log_info "Successfully uploaded symbols for ${release_name}"
}
# Main execution
main() {
log_info "=== Sentry Symbol Upload Script ==="
# Parse arguments
local version="${1:-}"
local symbols_path="${2:-}"
# Check environment variables
check_env_vars
# Ensure sentry-cli is available
ensure_sentry_cli
# Validate version argument
if [[ -z "${version}" ]]; then
# Try to extract version from Cargo.toml or package.json
if [[ -f "app/src-tauri/Cargo.toml" ]]; then
version=$(grep -m1 '^version\s*=' app/src-tauri/Cargo.toml | sed 's/version\s*=\s*"\([^"]*\)"/\1/')
log_info "Detected version from Cargo.toml: ${version}"
elif [[ -f "app/package.json" ]]; then
version=$(grep -m1 '"version"' app/package.json | sed 's/.*"version": *"\([^"]*\)".*/\1/')
log_info "Detected version from package.json: ${version}"
else
log_error "Could not determine version. Please provide it as an argument."
log_info "Usage: $0 <version> [symbols_path]"
exit 1
fi
fi
# Default symbols path if not provided
if [[ -z "${symbols_path}" ]]; then
symbols_path="target/release/deps"
fi
# Upload symbols
upload_symbols "${version}" "${symbols_path}"
log_info "=== Upload complete ==="
}
# Run main function
main "$@"