# frozen_string_literal: true
# This task will notify Sentry via their API[2] that you have deployed # a new release. It uses the commit hash as the `version` and the git ref as # the optional `ref` value. # # [1]: docs.sentry.io/api/releases/post-project-releases/ # [2]: docs.sentry.io/api/releases/post-release-deploys/
# For Rails app, this goes in config/deploy.rb
module Capistrano
class SentryConfigurationError < StandardError end
end
namespace :sentry do
desc 'Confirm configuration for notification to Sentry' task :validate_config do run_locally do info '[sentry:validate_config] Validating Sentry notification config' api_token = ENV['SENTRY_API_TOKEN'] || fetch(:sentry_api_token) if api_token.nil? || api_token.empty? msg = 'Missing SENTRY_API_TOKEN. Please set SENTRY_API_TOKEN environment' \ ' variable or `set :sentry_api_token` in your `config/deploy.rb` file for your Rails application.' warn msg raise Capistrano::SentryConfigurationError, msg end end end desc 'Notice new deployment in Sentry' task :notice_deployment do run_locally do require 'uri' require 'net/https' require 'json' head_revision = fetch(:current_revision) || `git rev-parse HEAD`.strip prev_revision = fetch(:previous_revision) || `git rev-parse #{fetch(:current_revision)}^`.strip sentry_host = ENV['SENTRY_HOST'] || fetch(:sentry_host, 'https://sentry.io') organization_slug = fetch(:sentry_organization) || fetch(:application) project = fetch(:sentry_project) || fetch(:application) environment = fetch(:stage) || 'default' api_token = ENV['SENTRY_API_TOKEN'] || fetch(:sentry_api_token) repo_integration_enabled = fetch(:sentry_repo_integration, true) release_refs = fetch(:sentry_release_refs, [{ repository: fetch(:sentry_repo) || fetch(:repo_url).split(':').last.delete_suffix('.git'), commit: head_revision, previousCommit: prev_revision }]) release_version = fetch(:sentry_release_version) || head_revision deploy_name = fetch(:sentry_deploy_name) || "#{release_version}-#{fetch(:release_timestamp)}" uri = URI.parse(sentry_host) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true headers = { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' + api_token.to_s } req = Net::HTTP::Post.new("/api/0/organizations/#{organization_slug}/releases/", headers) body = { version: release_version, projects: [project] } body[:refs] = release_refs if repo_integration_enabled req.body = JSON.generate(body) response = http.request(req) if response.is_a? Net::HTTPSuccess info "Notified Sentry of new release: #{release_version}" req = Net::HTTP::Post.new( "/api/0/organizations/#{organization_slug}/releases/#{release_version}/deploys/", headers ) req.body = JSON.generate( environment: environment, name: deploy_name ) response = http.request(req) if response.is_a? Net::HTTPSuccess info "Notified Sentry of new deployment: #{deploy_name}" else warn "Cannot notify sentry for new deployment. Response: #{response.code.inspect}: #{response.body}" end else warn "Cannot notify sentry for new release. Response: #{response.code.inspect}: #{response.body}" end end end
end