#!/usr/bin/env bash # Sentry release helper used by GitHub + Gitea CI to tag releases, # upload source-maps, correlate commits and mark deploys against our # self-hosted Sentry (https://sentry.boiler.saas-ctrl.com). # # Usage: # scripts/ci/sentry-release.sh \ # --project \ # --environment \ # --release \ # --sourcemaps # # Required environment variables: # SENTRY_AUTH_TOKEN Auth token scoped to project:releases # SENTRY_ORG Sentry organisation slug (e.g. "sentry") # SENTRY_URL Base URL of the self-hosted instance # # This script intentionally never prints the auth token. Callers in CI # should mask SENTRY_AUTH_TOKEN via the runner's secret masking. set -euo pipefail PROJECT="" ENVIRONMENT="" RELEASE="" SOURCEMAPS="none" usage() { cat <&2 sentry-release.sh: arguments --project Sentry project slug (required) --environment Deploy environment name (required) --release Release identifier (usually \$GIT_SHA, required) --sourcemaps Directory to upload source-maps from, or "none" Required env vars: SENTRY_AUTH_TOKEN, SENTRY_ORG, SENTRY_URL USAGE } while [ $# -gt 0 ]; do case "$1" in --project) PROJECT="${2:-}" shift 2 ;; --environment) ENVIRONMENT="${2:-}" shift 2 ;; --release) RELEASE="${2:-}" shift 2 ;; --sourcemaps) SOURCEMAPS="${2:-none}" shift 2 ;; -h|--help) usage exit 0 ;; *) echo "sentry-release.sh: unknown argument: $1" >&2 usage exit 2 ;; esac done missing=() [ -z "$PROJECT" ] && missing+=("--project") [ -z "$ENVIRONMENT" ] && missing+=("--environment") [ -z "$RELEASE" ] && missing+=("--release") if [ "${#missing[@]}" -gt 0 ]; then echo "sentry-release.sh: missing required argument(s): ${missing[*]}" >&2 usage exit 2 fi missing_env=() [ -z "${SENTRY_AUTH_TOKEN:-}" ] && missing_env+=("SENTRY_AUTH_TOKEN") [ -z "${SENTRY_ORG:-}" ] && missing_env+=("SENTRY_ORG") [ -z "${SENTRY_URL:-}" ] && missing_env+=("SENTRY_URL") if [ "${#missing_env[@]}" -gt 0 ]; then echo "sentry-release.sh: missing required environment variable(s): ${missing_env[*]}" >&2 exit 3 fi # Pinning the CLI version keeps CI deterministic; bump intentionally. SENTRY_CLI_PACKAGE="${SENTRY_CLI_PACKAGE:-@sentry/cli@2.41.1}" # Allow tests to inject a fake binary by overriding SENTRY_CLI. if [ -n "${SENTRY_CLI:-}" ]; then sentry_cli() { "$SENTRY_CLI" "$@" } else sentry_cli() { npx --yes "$SENTRY_CLI_PACKAGE" "$@" } fi export SENTRY_AUTH_TOKEN SENTRY_ORG SENTRY_URL export SENTRY_PROJECT="$PROJECT" # Disable shell-trace if a caller enabled it — protects the auth token # from leaking into log surfaces. set +x echo "sentry-release: project=$PROJECT environment=$ENVIRONMENT release=$RELEASE sourcemaps=$SOURCEMAPS" sentry_cli releases new "$RELEASE" if [ "$SOURCEMAPS" != "none" ]; then if [ ! -d "$SOURCEMAPS" ]; then echo "sentry-release.sh: sourcemaps path does not exist: $SOURCEMAPS" >&2 exit 4 fi sentry_cli sourcemaps upload --release "$RELEASE" "$SOURCEMAPS" fi sentry_cli releases set-commits "$RELEASE" --auto sentry_cli releases finalize "$RELEASE" sentry_cli releases deploys "$RELEASE" new -e "$ENVIRONMENT" echo "sentry-release: done"