Skip to content

Instantly share code, notes, and snippets.

@jnstq
Created August 26, 2017 07:45
Show Gist options
  • Save jnstq/52d10b9d262be92987228e7fb4b7a066 to your computer and use it in GitHub Desktop.
Save jnstq/52d10b9d262be92987228e7fb4b7a066 to your computer and use it in GitHub Desktop.
Enable honeybadger for javascript on Rails 5.1 when webpacker

Enable honeybadger for javascript using rails-webpacker and cloudfront

Source maps is enabled by default when using rails-webpacker. The rask tasks open the manifest file, post the source map to honeybadger and remove the source map file and remove it from the manifest.

yarn add honeybadger-js

in app/javascript/packs/application.js require honeybadger

var Honeybadger = require('honeybadger-js');

Honeybadger.configure({
  apiKey: process.env.HONEYBADGER_API_KEY,
  environment: process.env.RAILS_ENV,
  revision: process.env.SOURCE_VERSION || 'master',
  disabled: process.env.NODE_ENV !== 'production'
});

Honeybadger.beforeNotify((err) => {
  err.cookies = document.cookie;
  return true;
});

It's possible to use process.env thanks to webpacks EnvironmentPlugin

in config/environments/production.rb

config.public_file_server.headers = {
  'Access-Control-Allow-Origin' => '*',
  'Access-Control-Request-Method' => 'GET,HEAD'
}

Go to aws.amazon.com, Cloudfront, CloudFront Distributions, Your Distribution, Behaviors, Edit, Forward Headers, Whitelist, Add Origin.

In your layout make sure to add crossorigin

javascript_include_tag 'application', 'data-turbolinks-track': 'reload', crossorigin: 'anonymous'
javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', crossorigin: 'anonymous'

The rake tasks runs after webpacker:compile

namespace :honeybadger do
  task source_map: :environment do
    api_key = ENV['HONEYBADGER_API_KEY']
    revision = ENV['SOURCE_VERSION']

    manifest_path = Rails.root.join('public', 'packs', 'manifest.json')
    manifest = Oj.load(manifest_path.read)

    manifest.each do |basename, file_url|
      if basename.ends_with?('.map')
        puts "[Honeybadger] Sending javascript source map 🐛"
        conn = Faraday.new('https://api.honeybadger.io') do |f|
          f.request :multipart
          f.request :url_encoded
          f.adapter Faraday.default_adapter
        end

        minified_url = "http*:#{file_url.gsub(/\.map$/, '')}"
        source_map_file = Faraday::UploadIO.new(Rails.root.join('public', 'packs', File.basename(file_url)).to_s, 'application/octet-stream', File.basename(file_url))
        minified_file = Faraday::UploadIO.new(Rails.root.join('public', 'packs', File.basename(file_url.gsub(/\.map$/, ''))).to_s, 'application/javascript', File.basename(file_url.gsub(/\.map$/, '')))

        payload = {
          api_key: api_key,
          minified_url: "http*:#{file_url.gsub(/\.map$/, '')}",
          source_map: source_map_file,
          minified_file: minified_file,
          revision: revision
        }

        puts "[Honeybadger] Posting #{payload.stringify_keys.inspect}"

        response = conn.post('/v1/source_maps', payload)

        puts "[Honeybadger] Response #{basename} (#{revision}): #{Rack::Utils::HTTP_STATUS_CODES[response.status]}"

        File.delete Rails.root.join('public', 'packs', File.basename(file_url))
      end
    end

    manifest.delete_if { |basename, _| basename.ends_with?('.map') }

    File.open(manifest_path, "w") { |f| f.write Oj.dump(manifest, indent: 2) }
  end
end

# Compile packs after we've compiled all other assets during precompilation
if Rake::Task.task_defined?("webpacker:compile")
  Rake::Task["webpacker:compile"].enhance do
    Rake::Task["honeybadger:source_map"].invoke
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment