Permalink
Browse files

Merge branch 'feature/redmine'

  • Loading branch information...
oruen committed Apr 8, 2011
2 parents d95174a + dd383c8 commit bd17fa780fb7f38eb201c96fc4a87f9f8e597a55
View
@@ -7,6 +7,7 @@ gem 'haml'
gem 'will_paginate'
gem 'devise', '~> 1.1.8'
gem 'lighthouse-api'
+gem 'redmine_client', :git => "git://github.com/oruen/redmine_client.git"
platform :ruby do
gem 'bson_ext', '~> 1.2'
View
@@ -1,3 +1,10 @@
+GIT
+ remote: git://github.com/oruen/redmine_client.git
+ revision: 0df20a8b695869b03cfa129560b938a0af346add
+ specs:
+ redmine_client (0.0.1)
+ activeresource (>= 2.3.0)
+
GEM
remote: http://rubygems.org/
specs:
@@ -122,6 +129,7 @@ DEPENDENCIES
mongoid (~> 2.0.0.rc.7)
nokogiri
rails (= 3.0.5)
+ redmine_client!
rspec (~> 2.5)
rspec-rails (~> 2.5)
webmock
View
@@ -94,7 +94,14 @@ Lighthouseapp integration
* Account is the name of your subdomain, i.e. **litcafe** for project at http://litcafe.lighthouseapp.com/projects/73466-face/overview
* Errbit uses token-based authentication. Get your API Token or visit [http://help.lighthouseapp.com/kb/api/how-do-i-get-an-api-token](http://help.lighthouseapp.com/kb/api/how-do-i-get-an-api-token) to learn how to get it.
-* Project id is number identifier of your project, i.e. **73466** for project at http://litcafe.lighthouseapp.com/projects/73466-face/overview
+* Project id is number identifier of your project, i.e. **73466** for project at http://litcafe.lighthouseapp.com/projects/73466-face/overview
+
+Redmine integration
+-------------------------
+
+* Account is the host of your redmine installation, i.e. **http://redmine.org**
+* Errbit uses token-based authentication. Get your API Key or visit [http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication](http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication) to learn how to get it.
+* Project id is an identifier of your project, i.e. **chilliproject** for project at http://www.redmine.org/projects/chilliproject
TODO
----
@@ -36,7 +36,8 @@ def create_issue
flash[:error] = "This up has no issue tracker setup."
end
redirect_to app_err_path(@app, @err)
- rescue ActiveResource::ConnectionError
+ rescue ActiveResource::ConnectionError => e
+ Rails.logger.error e.to_s
flash[:error] = "There was an error during issue creation. Check your tracker settings or try again later."
redirect_to app_err_path(@app, @err)
end
@@ -1,2 +1,5 @@
module ApplicationHelper
+ def lighthouse_tracker? object
+ object.issue_tracker_type == "lighthouseapp"
+ end
end
View
@@ -33,7 +33,7 @@ class App
accepts_nested_attributes_for :watchers, :allow_destroy => true,
:reject_if => proc { |attrs| attrs[:user_id].blank? && attrs[:email].blank? }
accepts_nested_attributes_for :issue_tracker, :allow_destroy => true,
- :reject_if => proc { |attrs| !%w( lighthouseapp ).include?(attrs[:issue_tracker_type]) }
+ :reject_if => proc { |attrs| !%w( lighthouseapp redmine ).include?(attrs[:issue_tracker_type]) }
# Mongoid Bug: find(id) on association proxies returns an Enumerator
def self.find_by_id!(app_id)
View
@@ -5,7 +5,7 @@ class IssueTracker
include Rails.application.routes.url_helpers
default_url_options[:host] = Errbit::Application.config.action_mailer.default_url_options[:host]
- validate :check_lighthouseapp_params
+ validate :check_params
embedded_in :app, :inverse_of => :issue_tracker
@@ -15,82 +15,65 @@ class IssueTracker
field :issue_tracker_type, :type => String, :default => 'lighthouseapp'
def create_issue err
+ return create_lighthouseapp_issue err if issue_tracker_type == 'lighthouseapp'
+ create_redmine_issue err if issue_tracker_type == 'redmine'
+ end
+
+ protected
+ def create_redmine_issue err
+ token = api_token
+ acc = account
+ RedmineClient::Base.configure do
+ self.token = token
+ self.site = acc
+ end
+ issue = RedmineClient::Issue.new(:project_id => project_id)
+ issue.subject = issue_title err
+ issue.description = self.class.redmine_body_template.result(binding)
+ issue.save!
+ err.update_attribute :issue_link, "#{RedmineClient::Issue.site.to_s.sub(/#{RedmineClient::Issue.site.path}$/, '')}#{RedmineClient::Issue.element_path(issue.id, :project_id => project_id)}".sub(/\.xml\?project_id=#{project_id}$/, "\?project_id=#{project_id}")
+ end
+
+ def create_lighthouseapp_issue err
Lighthouse.account = account
Lighthouse.token = api_token
# updating lighthouse account
Lighthouse::Ticket.site
ticket = Lighthouse::Ticket.new(:project_id => project_id)
- ticket.title = "[#{ err.environment }][#{ err.where }] #{err.message.to_s.truncate(100)}"
+ ticket.title = issue_title err
- ticket.body = ""
- ticket.body += "[See this exception on Errbit](#{ app_err_url err.app, err } \"See this exception on Errbit\")"
- ticket.body += "\n"
- if notice = err.notices.first
- ticket.body += "# #{notice.message} #"
- ticket.body += "\n"
- ticket.body += "## Summary ##"
- ticket.body += "\n"
- if notice.request['url'].present?
- ticket.body += "### URL ###"
- ticket.body += "\n"
- ticket.body += "[#{notice.request['url']}](#{notice.request['url']})"
- ticket.body += "\n"
- end
- ticket.body += "### Where ###"
- ticket.body += "\n"
- ticket.body += notice.err.where
- ticket.body += "\n"
-
- ticket.body += "### Occured ###"
- ticket.body += "\n"
- ticket.body += notice.created_at.to_s(:micro)
- ticket.body += "\n"
-
- ticket.body += "### Similar ###"
- ticket.body += "\n"
- ticket.body += (notice.err.notices.count - 1).to_s
- ticket.body += "\n"
-
- ticket.body += "## Params ##"
- ticket.body += "\n"
- ticket.body += "<code>#{pretty_hash(notice.params)}</code>"
- ticket.body += "\n"
-
- ticket.body += "## Session ##"
- ticket.body += "\n"
- ticket.body += "<code>#{pretty_hash(notice.session)}</code>"
- ticket.body += "\n"
-
- ticket.body += "## Backtrace ##"
- ticket.body += "\n"
- ticket.body += "<code>"
- for line in notice.backtrace
- ticket.body += "#{line['number']}: #{line['file'].sub(/^\[PROJECT_ROOT\]/, '')} -> **#{line['method']}**"
- ticket.body += "\n"
- end
- ticket.body += "</code>"
- ticket.body += "\n"
-
- ticket.body += "## Environment ##"
- ticket.body += "\n"
- for key, val in notice.env_vars
- ticket.body += "#{key}: #{val}"
- end
- ticket.body += "\n"
- end
+ ticket.body = self.class.lighthouseapp_body_template.result(binding)
ticket.tags << "errbit"
ticket.save!
err.update_attribute :issue_link, "#{Lighthouse::Ticket.site.to_s.sub(/#{Lighthouse::Ticket.site.path}$/, '')}#{Lighthouse::Ticket.element_path(ticket.id, :project_id => project_id)}".sub(/\.xml$/, '')
end
- protected
- def check_lighthouseapp_params
+ def issue_title err
+ "[#{ err.environment }][#{ err.where }] #{err.message.to_s.truncate(100)}"
+ end
+
+ def check_params
blank_flags = %w( api_token project_id account ).map {|m| self[m].blank? }
if blank_flags.any? && !blank_flags.all?
- errors.add(:base, "You must specify your Lighthouseapp account, token and project id")
+ message = if issue_tracker_type == 'lighthouseapp'
+ "You must specify your Lighthouseapp account, api token and project id"
+ else
+ "You must specify your Redmine url, api token and project id"
+ end
+ errors.add(:base, message)
+ end
+ end
+
+ class << self
+ def lighthouseapp_body_template
+ @@lighthouseapp_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/lighthouseapp_body.txt.erb").gsub(/^\s*/, ''))
+ end
+
+ def redmine_body_template
+ @@redmine_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/redmine_body.txt.erb"))
end
end
end
@@ -33,15 +33,24 @@
%fieldset
%legend Issue tracker
= f.fields_for :issue_tracker do |w|
- %div.watcher.nested
+ %div.issue_tracker.nested
%div.choose
= w.radio_button :issue_tracker_type, :lighthouseapp
= label_tag :issue_tracker_type_lighthouseapp, 'Lighthouse', :for => label_for_attr(w, 'issue_tracker_type_lighthouseapp')
- %div.lighthouseapp{:class => 'choosen'}
+ = w.radio_button :issue_tracker_type, :redmine
+ = label_tag :issue_tracker_type_redmine, 'Redmine', :for => label_for_attr(w, 'issue_tracker_type_redmine')
+ %div.tracker_params{:class => lighthouse_tracker?(w.object) ? 'choosen' : nil}
= w.label :account, "Account"
- = w.text_field :account
+ = w.text_field :account, :placeholder => "abc from abc.lighthouseapp.com"
+ = w.label :api_token, "API token"
+ = w.text_field :api_token, :placeholder => "API Token for your account"
+ = w.label :project_id, "Project ID"
+ = w.text_field :project_id, :placeholder => "123 from abc from abc.lighthouseapp.com/projects/123"
+ %div.tracker_params{:class => lighthouse_tracker?(w.object) ? nil : 'choosen'}
+ = w.label :account, "Redmine URL"
+ = w.text_field :account, :placeholder => "like http://www.redmine.org/"
= w.label :api_token, "API token"
- = w.text_field :api_token
+ = w.text_field :api_token, :placeholder => "API Token for your account"
= w.label :project_id, "Project ID"
= w.text_field :project_id
@@ -0,0 +1,34 @@
+[See this exception on Errbit](<%= app_err_url err.app, err %> "See this exception on Errbit")
+<% if notice = err.notices.first %>
+ # <%= notice.message %> #
+ ## Summary ##
+ <% if notice.request['url'].present? %>
+ ### URL ###
+ [<%= notice.request['url'] %>](<%= notice.request['url'] %>)"
+ <% end %>
+ ### Where ###
+ <%= notice.err.where %>
+
+ ### Occured ###
+ <%= notice.created_at.to_s(:micro) %>
+
+ ### Similar ###
+ <%= (notice.err.notices.count - 1).to_s %>
+
+ ## Params ##
+ <code><%= pretty_hash(notice.params) %></code>
+
+ ## Session ##
+ <code><%= pretty_hash(notice.session) %></code>
+
+ ## Backtrace ##
+ <code>
+ <% for line in notice.backtrace %><%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> -> **<%= line['method'] %>**
+ <% end %>
+ </code>
+
+ ## Environment ##
+ <% for key, val in notice.env_vars %>
+ <%= key %>: <%= val %>
+ <% end %>
+<% end %>
@@ -0,0 +1,45 @@
+"See this exception on Errbit":<%= app_err_url err.app, err %>
+<% if notice = err.notices.first %>
+h1. <%= notice.message %>
+
+h2. Summary
+<% if notice.request['url'].present? %>
+h3. URL
+
+"<%= notice.request['url'] %>":<%= notice.request['url'] %>
+<% end %>
+h3. Where
+
+<%= notice.err.where %>
+
+h3. Occured
+
+<%= notice.created_at.to_s(:micro) %>
+
+h3. Similar
+
+<%= (notice.err.notices.count - 1).to_s %>
+
+h2. Params
+
+<pre><%= pretty_hash(notice.params) %></pre>
+
+h2. Session
+
+<pre><%= pretty_hash(notice.session) %></pre>
+
+h2. Backtrace
+
+<pre>
+<% for line in notice.backtrace %><%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> -> *<%= line['method'] %>*
+<% end %>
+</pre>
+
+h2. Environment
+
+<pre>
+<% for key, val in notice.env_vars %>
+<%= key %>: <%= val %>
+<% end %>
+</pre>
+<% end %>
@@ -12,10 +12,10 @@
- content_for :action_bar do
- if @err.app.issue_tracker
- if @err.issue_link.blank?
- %span= link_to 'create issue', create_issue_app_err_path(@app, @err), :method => :post, :class => 'create-issue'
+ %span= link_to 'create issue', create_issue_app_err_path(@app, @err), :method => :post, :class => "#{@app.issue_tracker.issue_tracker_type}_create create-issue"
- else
- %span= link_to 'go to issue', @err.issue_link, :class => 'goto-issue'
- = link_to 'clear issue', clear_issue_app_err_path(@app, @err), :method => :delete, :confirm => "Clear err issues?", :class => 'clear-issue'
+ %span= link_to 'go to issue', @err.issue_link, :class => "#{@app.issue_tracker.issue_tracker_type}_create goto-issue"
+ = link_to 'clear issue', clear_issue_app_err_path(@app, @err), :method => :delete, :confirm => "Clear err issues?", :class => "clear-issue"
- if @err.unresolved?
%span= link_to 'resolve', resolve_app_err_path(@app, @err), :method => :put, :confirm => err_confirm, :class => 'resolve'
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
View
@@ -3,6 +3,9 @@ $(function(){
if($('div.watcher.nested').length)
activateWatcherTypeSelector();
+
+ if($('div.issue_tracker.nested').length)
+ activateIssueTrackerTypeSelector();
});
function activateNestedForms() {
@@ -67,4 +70,20 @@ function activateWatcherTypeSelector() {
wrapper.find('div.choosen').removeClass('choosen');
wrapper.find('div.'+choosen).addClass('choosen');
});
+}
+
+function activateIssueTrackerTypeSelector() {
+ var not_choosen = $("div.tracker_params").filter(function () {
+ return !$(this).hasClass("choosen");
+ });
+ window.hiddenTracker = not_choosen.html();
+ not_choosen.remove();
+ $('div.issue_tracker input[name*=issue_tracker_type]').live('click', function(){
+ var choosen = $(this).val();
+ var wrapper = $(this).closest('.nested');
+ var tmp;
+ tmp = wrapper.find('div.choosen').html();
+ wrapper.find('div.choosen').html(window.hiddenTracker);
+ window.hiddenTracker = tmp;
+ });
}
Oops, something went wrong.

0 comments on commit bd17fa7

Please sign in to comment.