Commit f9109d366f8125612b0bba02b11880a1388f26db
1 parent
25d141bd
Exists in
master
and in
1 other branch
Finished #59 - Refactored Issue Trackers. Remember to run "rake db:migrate".
Showing
30 changed files
with
421 additions
and
378 deletions
Show diff stats
app/controllers/apps_controller.rb
| @@ -24,6 +24,18 @@ class AppsController < InheritedResources::Base | @@ -24,6 +24,18 @@ class AppsController < InheritedResources::Base | ||
| 24 | end | 24 | end |
| 25 | end | 25 | end |
| 26 | 26 | ||
| 27 | + def create | ||
| 28 | + @app = App.new(params[:app]) | ||
| 29 | + initialize_subclassed_issue_tracker | ||
| 30 | + create! | ||
| 31 | + end | ||
| 32 | + | ||
| 33 | + def update | ||
| 34 | + @app = resource | ||
| 35 | + initialize_subclassed_issue_tracker | ||
| 36 | + update! | ||
| 37 | + end | ||
| 38 | + | ||
| 27 | def new | 39 | def new |
| 28 | plug_params build_resource | 40 | plug_params build_resource |
| 29 | new! | 41 | new! |
| @@ -34,7 +46,16 @@ class AppsController < InheritedResources::Base | @@ -34,7 +46,16 @@ class AppsController < InheritedResources::Base | ||
| 34 | edit! | 46 | edit! |
| 35 | end | 47 | end |
| 36 | 48 | ||
| 49 | + | ||
| 37 | protected | 50 | protected |
| 51 | + def initialize_subclassed_issue_tracker | ||
| 52 | + if params[:app][:issue_tracker_attributes] && tracker_type = params[:app][:issue_tracker_attributes][:type] | ||
| 53 | + if IssueTracker.subclasses.map(&:to_s).include?(tracker_type.to_s) | ||
| 54 | + @app.issue_tracker = tracker_type.constantize.new(params[:app][:issue_tracker_attributes]) | ||
| 55 | + end | ||
| 56 | + end | ||
| 57 | + end | ||
| 58 | + | ||
| 38 | def begin_of_association_chain | 59 | def begin_of_association_chain |
| 39 | current_user unless current_user.admin? | 60 | current_user unless current_user.admin? |
| 40 | end | 61 | end |
| @@ -45,7 +66,7 @@ class AppsController < InheritedResources::Base | @@ -45,7 +66,7 @@ class AppsController < InheritedResources::Base | ||
| 45 | 66 | ||
| 46 | def plug_params app | 67 | def plug_params app |
| 47 | app.watchers.build if app.watchers.none? | 68 | app.watchers.build if app.watchers.none? |
| 48 | - app.issue_tracker = IssueTracker.new if app.issue_tracker.nil? | 69 | + app.issue_tracker = IssueTracker.new unless app.issue_tracker_configured? |
| 49 | end | 70 | end |
| 50 | 71 | ||
| 51 | # email_at_notices is edited as a string, and stored as an array. | 72 | # email_at_notices is edited as a string, and stored as an array. |
app/helpers/application_helper.rb
| @@ -29,16 +29,5 @@ module ApplicationHelper | @@ -29,16 +29,5 @@ module ApplicationHelper | ||
| 29 | tallies.values.inject(0) {|sum, n| sum + n} | 29 | tallies.values.inject(0) {|sum, n| sum + n} |
| 30 | end | 30 | end |
| 31 | private :total_from_tallies | 31 | private :total_from_tallies |
| 32 | - | ||
| 33 | - def no_tracker? object | ||
| 34 | - object.issue_tracker_type == "none" | ||
| 35 | - end | ||
| 36 | - | ||
| 37 | - %w(lighthouseapp redmine pivotal fogbugz mingle).each do |tracker| | ||
| 38 | - define_method("#{tracker}_tracker?".to_sym) do |object| | ||
| 39 | - object.issue_tracker_type == tracker | ||
| 40 | - end | ||
| 41 | - end | ||
| 42 | - | ||
| 43 | end | 32 | end |
| 44 | 33 |
app/models/app.rb
| @@ -11,7 +11,7 @@ class App | @@ -11,7 +11,7 @@ class App | ||
| 11 | field :notify_on_deploys, :type => Boolean, :default => true | 11 | field :notify_on_deploys, :type => Boolean, :default => true |
| 12 | field :email_at_notices, :type => Array, :default => Errbit::Config.email_at_notices | 12 | field :email_at_notices, :type => Array, :default => Errbit::Config.email_at_notices |
| 13 | 13 | ||
| 14 | - # Some legacy apps may have sting as key instead of BSON::ObjectID | 14 | + # Some legacy apps may have string as key instead of BSON::ObjectID |
| 15 | identity :type => String | 15 | identity :type => String |
| 16 | # There seems to be a Mongoid bug making it impossible to use String identity with references_many feature: | 16 | # There seems to be a Mongoid bug making it impossible to use String identity with references_many feature: |
| 17 | # https://github.com/mongoid/mongoid/issues/703 | 17 | # https://github.com/mongoid/mongoid/issues/703 |
| @@ -37,7 +37,7 @@ class App | @@ -37,7 +37,7 @@ class App | ||
| 37 | accepts_nested_attributes_for :watchers, :allow_destroy => true, | 37 | accepts_nested_attributes_for :watchers, :allow_destroy => true, |
| 38 | :reject_if => proc { |attrs| attrs[:user_id].blank? && attrs[:email].blank? } | 38 | :reject_if => proc { |attrs| attrs[:user_id].blank? && attrs[:email].blank? } |
| 39 | accepts_nested_attributes_for :issue_tracker, :allow_destroy => true, | 39 | accepts_nested_attributes_for :issue_tracker, :allow_destroy => true, |
| 40 | - :reject_if => proc { |attrs| !%w(none lighthouseapp redmine pivotal fogbugz mingle).include?(attrs[:issue_tracker_type]) } | 40 | + :reject_if => proc { |attrs| !IssueTracker.subclasses.map(&:to_s).include?(attrs[:type].to_s) } |
| 41 | 41 | ||
| 42 | def self.find_by_id!(app_id) | 42 | def self.find_by_id!(app_id) |
| 43 | find app_id | 43 | find app_id |
| @@ -71,7 +71,7 @@ class App | @@ -71,7 +71,7 @@ class App | ||
| 71 | end | 71 | end |
| 72 | 72 | ||
| 73 | def issue_tracker_configured? | 73 | def issue_tracker_configured? |
| 74 | - issue_tracker && issue_tracker.issue_tracker_type != "none" && !issue_tracker.project_id.blank? | 74 | + !!(issue_tracker && issue_tracker.class < IssueTracker && issue_tracker.project_id.present?) |
| 75 | end | 75 | end |
| 76 | 76 | ||
| 77 | def notification_recipients | 77 | def notification_recipients |
app/models/issue_tracker.rb
| @@ -5,171 +5,28 @@ class IssueTracker | @@ -5,171 +5,28 @@ class IssueTracker | ||
| 5 | include Rails.application.routes.url_helpers | 5 | include Rails.application.routes.url_helpers |
| 6 | default_url_options[:host] = Errbit::Application.config.action_mailer.default_url_options[:host] | 6 | default_url_options[:host] = Errbit::Application.config.action_mailer.default_url_options[:host] |
| 7 | 7 | ||
| 8 | - validate :check_params | ||
| 9 | - | ||
| 10 | embedded_in :app, :inverse_of => :issue_tracker | 8 | embedded_in :app, :inverse_of => :issue_tracker |
| 11 | 9 | ||
| 12 | - field :account, :type => String | ||
| 13 | - field :api_token, :type => String | ||
| 14 | field :project_id, :type => String | 10 | field :project_id, :type => String |
| 15 | - field :ticket_properties, :type => String | 11 | + field :api_token, :type => String |
| 12 | + field :account, :type => String | ||
| 16 | field :username, :type => String | 13 | field :username, :type => String |
| 17 | field :password, :type => String | 14 | field :password, :type => String |
| 18 | - field :issue_tracker_type, :type => String, :default => 'none' | ||
| 19 | - | ||
| 20 | - def create_issue err | ||
| 21 | - case issue_tracker_type | ||
| 22 | - when 'lighthouseapp' | ||
| 23 | - create_lighthouseapp_issue err | ||
| 24 | - when 'redmine' | ||
| 25 | - create_redmine_issue err | ||
| 26 | - when 'pivotal' | ||
| 27 | - create_pivotal_issue err | ||
| 28 | - when 'fogbugz' | ||
| 29 | - create_fogbugz_issue err | ||
| 30 | - when 'mingle' | ||
| 31 | - create_mingle_issue err | ||
| 32 | - end | ||
| 33 | - end | ||
| 34 | - | ||
| 35 | - def ticket_properties_hash | ||
| 36 | - # Parses 'key=value, key2=value2' from user input into a ruby hash. | ||
| 37 | - self.ticket_properties.split(",").inject({}) do |hash, pair| | ||
| 38 | - key, value = pair.split("=").map(&:strip) | ||
| 39 | - hash[key] = value | ||
| 40 | - hash | ||
| 41 | - end | ||
| 42 | - end | ||
| 43 | - | ||
| 44 | - protected | ||
| 45 | - def create_redmine_issue err | ||
| 46 | - token = api_token | ||
| 47 | - acc = account | ||
| 48 | - RedmineClient::Base.configure do | ||
| 49 | - self.token = token | ||
| 50 | - self.site = acc | ||
| 51 | - end | ||
| 52 | - issue = RedmineClient::Issue.new(:project_id => project_id) | ||
| 53 | - issue.subject = issue_title err | ||
| 54 | - issue.description = self.class.redmine_body_template.result(binding) | ||
| 55 | - issue.save! | ||
| 56 | - 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}") | ||
| 57 | - end | ||
| 58 | - | ||
| 59 | - def create_pivotal_issue err | ||
| 60 | - PivotalTracker::Client.token = api_token | ||
| 61 | - PivotalTracker::Client.use_ssl = true | ||
| 62 | - project = PivotalTracker::Project.find project_id.to_i | ||
| 63 | - story = project.stories.create :name => issue_title(err), :story_type => 'bug', :description => self.class.pivotal_body_template.result(binding) | ||
| 64 | - err.update_attribute :issue_link, "https://www.pivotaltracker.com/story/show/#{story.id}" | ||
| 65 | - end | ||
| 66 | - | ||
| 67 | - def create_lighthouseapp_issue err | ||
| 68 | - Lighthouse.account = account | ||
| 69 | - Lighthouse.token = api_token | ||
| 70 | - | ||
| 71 | - # updating lighthouse account | ||
| 72 | - Lighthouse::Ticket.site | ||
| 73 | - | ||
| 74 | - ticket = Lighthouse::Ticket.new(:project_id => project_id) | ||
| 75 | - ticket.title = issue_title err | ||
| 76 | - | ||
| 77 | - ticket.body = self.class.lighthouseapp_body_template.result(binding) | ||
| 78 | - | ||
| 79 | - ticket.tags << "errbit" | ||
| 80 | - ticket.save! | ||
| 81 | - 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$/, '') | ||
| 82 | - end | ||
| 83 | - | ||
| 84 | - def create_fogbugz_issue err | ||
| 85 | - fogbugz = Fogbugz::Interface.new(:email => username, :password => password, :uri => "https://#{account}.fogbugz.com") | ||
| 86 | - fogbugz.authenticate | ||
| 87 | - | ||
| 88 | - issue = {} | ||
| 89 | - issue['sTitle'] = issue_title err | ||
| 90 | - issue['sArea'] = project_id | ||
| 91 | - issue['sEvent'] = self.class.fogbugz_body_template.result(binding) | ||
| 92 | - issue['sTags'] = ['errbit'].join(',') | ||
| 93 | - issue['cols'] = ['ixBug'].join(',') | ||
| 94 | - | ||
| 95 | - fb_resp = fogbugz.command(:new, issue) | ||
| 96 | - err.update_attribute :issue_link, "https://#{account}.fogbugz.com/default.asp?#{fb_resp['case']['ixBug']}" | ||
| 97 | - end | ||
| 98 | - | ||
| 99 | - def create_mingle_issue err | ||
| 100 | - properties = ticket_properties_hash | ||
| 101 | - basic_auth = account.gsub(/https?:\/\//, "https://#{username}:#{password}@") | ||
| 102 | - Mingle.set_site "#{basic_auth}/api/v1/projects/#{project_id}/" | 15 | + field :ticket_properties, :type => String |
| 103 | 16 | ||
| 104 | - card = Mingle::Card.new | ||
| 105 | - card.card_type_name = properties.delete("card_type") | ||
| 106 | - card.name = issue_title(err) | ||
| 107 | - card.description = self.class.mingle_body_template.result(binding) | ||
| 108 | - properties.each do |property, value| | ||
| 109 | - card.send("cp_#{property}=", value) | ||
| 110 | - end | 17 | + validate :check_params |
| 111 | 18 | ||
| 112 | - card.save! | ||
| 113 | - err.update_attribute :issue_link, URI.parse("#{account}/projects/#{project_id}/cards/#{card.id}").to_s | ||
| 114 | - end | 19 | + # Subclasses are responsible for overwriting this method. |
| 20 | + def check_params; end | ||
| 115 | 21 | ||
| 116 | def issue_title err | 22 | def issue_title err |
| 117 | "[#{ err.environment }][#{ err.where }] #{err.message.to_s.truncate(100)}" | 23 | "[#{ err.environment }][#{ err.where }] #{err.message.to_s.truncate(100)}" |
| 118 | end | 24 | end |
| 119 | 25 | ||
| 120 | - def check_params | ||
| 121 | - blank_flag_fields = %w(project_id) | ||
| 122 | - if %w(fogbugz mingle).include?(issue_tracker_type) | ||
| 123 | - blank_flag_fields += %w(username password) | ||
| 124 | - else | ||
| 125 | - blank_flag_fields << 'api_token' | ||
| 126 | - end | ||
| 127 | - blank_flag_fields << 'account' if(%w(fogbugz lighthouseapp redmine mingle).include?(issue_tracker_type)) | ||
| 128 | - blank_flags = blank_flag_fields.map {|m| self[m].blank? } | ||
| 129 | - | ||
| 130 | - if issue_tracker_type == "mingle" | ||
| 131 | - # Check that mingle was given a 'card_type' in the ticket_properties | ||
| 132 | - blank_flags << "card_type" unless ticket_properties_hash["card_type"] | ||
| 133 | - end | ||
| 134 | - | ||
| 135 | - if blank_flags.any? && !blank_flags.all? | ||
| 136 | - message = case issue_tracker_type | ||
| 137 | - when 'lighthouseapp' | ||
| 138 | - 'You must specify your Lighthouseapp account, API token and Project ID' | ||
| 139 | - when 'redmine' | ||
| 140 | - 'You must specify your Redmine URL, API token and Project ID' | ||
| 141 | - when 'pivotal' | ||
| 142 | - 'You must specify your Pivotal Tracker API token and Project ID' | ||
| 143 | - when 'fogbugz' | ||
| 144 | - 'You must specify your FogBugz Area Name, Username, and Password' | ||
| 145 | - when 'mingle' | ||
| 146 | - 'You must specify your Mingle URL, Project ID, Card Type (in default card properties), Sign-in name, and Password' | ||
| 147 | - end | ||
| 148 | - errors.add(:base, message) | ||
| 149 | - end | ||
| 150 | - end | ||
| 151 | - | ||
| 152 | - class << self | ||
| 153 | - def lighthouseapp_body_template | ||
| 154 | - @@lighthouseapp_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/lighthouseapp_body.txt.erb").gsub(/^\s*/, '')) | ||
| 155 | - end | 26 | + # Allows us to set the issue tracker class from a single form. |
| 27 | + def type; self._type; end | ||
| 28 | + def type=(t); self._type=t; end | ||
| 156 | 29 | ||
| 157 | - def redmine_body_template | ||
| 158 | - @@redmine_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/redmine_body.txt.erb")) | ||
| 159 | - end | ||
| 160 | - | ||
| 161 | - def pivotal_body_template | ||
| 162 | - @@pivotal_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/pivotal_body.txt.erb")) | ||
| 163 | - end | ||
| 164 | - | ||
| 165 | - def fogbugz_body_template | ||
| 166 | - @@fogbugz_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/fogbugz_body.txt.erb")) | ||
| 167 | - end | ||
| 168 | - | ||
| 169 | - def mingle_body_template | ||
| 170 | - # Mingle also uses textile markup, so the redmine template is perfect. | ||
| 171 | - redmine_body_template | ||
| 172 | - end | ||
| 173 | - end | 30 | + def self.label; "(none)"; end |
| 174 | end | 31 | end |
| 175 | 32 |
| @@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
| 1 | +class FogbugzTracker < IssueTracker | ||
| 2 | + def self.label; "fogbugz"; end | ||
| 3 | + | ||
| 4 | + def check_params | ||
| 5 | + if %w(project_id account username password).detect {|f| self[f].blank? } | ||
| 6 | + errors.add :base, 'You must specify your FogBugz Area Name, FogBugz URL, Username, and Password' | ||
| 7 | + end | ||
| 8 | + end | ||
| 9 | + | ||
| 10 | + def create_issue(err) | ||
| 11 | + fogbugz = Fogbugz::Interface.new(:email => username, :password => password, :uri => "https://#{account}.fogbugz.com") | ||
| 12 | + fogbugz.authenticate | ||
| 13 | + | ||
| 14 | + issue = {} | ||
| 15 | + issue['sTitle'] = issue_title err | ||
| 16 | + issue['sArea'] = project_id | ||
| 17 | + issue['sEvent'] = body_template.result(binding) | ||
| 18 | + issue['sTags'] = ['errbit'].join(',') | ||
| 19 | + issue['cols'] = ['ixBug'].join(',') | ||
| 20 | + | ||
| 21 | + fb_resp = fogbugz.command(:new, issue) | ||
| 22 | + err.update_attribute :issue_link, "https://#{account}.fogbugz.com/default.asp?#{fb_resp['case']['ixBug']}" | ||
| 23 | + end | ||
| 24 | + | ||
| 25 | + def body_template | ||
| 26 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/fogbugz_body.txt.erb")) | ||
| 27 | + end | ||
| 28 | +end | ||
| 29 | + |
| @@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
| 1 | +class LighthouseTracker < IssueTracker | ||
| 2 | + def self.label; "lighthouseapp"; end | ||
| 3 | + | ||
| 4 | + def check_params | ||
| 5 | + if %w(account api_token project_id).detect {|f| self[f].blank? } | ||
| 6 | + errors.add :base, 'You must specify your Lighthouseapp account, API token and Project ID' | ||
| 7 | + end | ||
| 8 | + end | ||
| 9 | + | ||
| 10 | + def create_issue(err) | ||
| 11 | + Lighthouse.account = account | ||
| 12 | + Lighthouse.token = api_token | ||
| 13 | + # updating lighthouse account | ||
| 14 | + Lighthouse::Ticket.site | ||
| 15 | + | ||
| 16 | + ticket = Lighthouse::Ticket.new(:project_id => project_id) | ||
| 17 | + ticket.title = issue_title err | ||
| 18 | + | ||
| 19 | + ticket.body = body_template.result(binding) | ||
| 20 | + | ||
| 21 | + ticket.tags << "errbit" | ||
| 22 | + ticket.save! | ||
| 23 | + 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$/, '') | ||
| 24 | + end | ||
| 25 | + | ||
| 26 | + def body_template | ||
| 27 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/lighthouseapp_body.txt.erb").gsub(/^\s*/, '')) | ||
| 28 | + end | ||
| 29 | +end | ||
| 30 | + |
| @@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
| 1 | +class MingleTracker < IssueTracker | ||
| 2 | + def self.label; "mingle"; end | ||
| 3 | + | ||
| 4 | + def check_params | ||
| 5 | + if %w(account project_id username password).detect {|f| self[f].blank? } or !ticket_properties_hash["card_type"] | ||
| 6 | + errors.add :base, 'You must specify your Mingle URL, Project ID, Card Type (in default card properties), Sign-in name, and Password' | ||
| 7 | + end | ||
| 8 | + end | ||
| 9 | + | ||
| 10 | + def create_issue(err) | ||
| 11 | + properties = ticket_properties_hash | ||
| 12 | + basic_auth = account.gsub(/https?:\/\//, "https://#{username}:#{password}@") | ||
| 13 | + Mingle.set_site "#{basic_auth}/api/v1/projects/#{project_id}/" | ||
| 14 | + | ||
| 15 | + card = Mingle::Card.new | ||
| 16 | + card.card_type_name = properties.delete("card_type") | ||
| 17 | + card.name = issue_title(err) | ||
| 18 | + card.description = body_template.result(binding) | ||
| 19 | + properties.each do |property, value| | ||
| 20 | + card.send("cp_#{property}=", value) | ||
| 21 | + end | ||
| 22 | + | ||
| 23 | + card.save! | ||
| 24 | + err.update_attribute :issue_link, URI.parse("#{account}/projects/#{project_id}/cards/#{card.id}").to_s | ||
| 25 | + end | ||
| 26 | + | ||
| 27 | + def body_template | ||
| 28 | + # Mingle also uses textile markup, so the redmine template is perfect. | ||
| 29 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/redmine_body.txt.erb")) | ||
| 30 | + end | ||
| 31 | + | ||
| 32 | + def ticket_properties_hash | ||
| 33 | + # Parses 'key=value, key2=value2' from ticket_properties into a ruby hash. | ||
| 34 | + self.ticket_properties.split(",").inject({}) do |hash, pair| | ||
| 35 | + key, value = pair.split("=").map(&:strip) | ||
| 36 | + hash[key] = value | ||
| 37 | + hash | ||
| 38 | + end | ||
| 39 | + end | ||
| 40 | +end | ||
| 41 | + |
| @@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
| 1 | +class PivotalLabsTracker < IssueTracker | ||
| 2 | + def self.label; "pivotal"; end | ||
| 3 | + | ||
| 4 | + def check_params | ||
| 5 | + if %w(api_token project_id).detect {|f| self[f].blank? } | ||
| 6 | + errors.add :base, 'You must specify your Pivotal Tracker API token and Project ID' | ||
| 7 | + end | ||
| 8 | + end | ||
| 9 | + | ||
| 10 | + def create_issue(err) | ||
| 11 | + PivotalTracker::Client.token = api_token | ||
| 12 | + PivotalTracker::Client.use_ssl = true | ||
| 13 | + project = PivotalTracker::Project.find project_id.to_i | ||
| 14 | + story = project.stories.create :name => issue_title(err), :story_type => 'bug', :description => body_template.result(binding) | ||
| 15 | + err.update_attribute :issue_link, "https://www.pivotaltracker.com/story/show/#{story.id}" | ||
| 16 | + end | ||
| 17 | + | ||
| 18 | + def body_template | ||
| 19 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/pivotal_body.txt.erb")) | ||
| 20 | + end | ||
| 21 | +end | ||
| 22 | + |
| @@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
| 1 | +class RedmineTracker < IssueTracker | ||
| 2 | + def self.label; "redmine"; end | ||
| 3 | + | ||
| 4 | + def check_params | ||
| 5 | + if %w(account api_token project_id).detect {|f| self[f].blank? } | ||
| 6 | + errors.add :base, 'You must specify your Redmine URL, API token and Project ID' | ||
| 7 | + end | ||
| 8 | + end | ||
| 9 | + | ||
| 10 | + def create_issue(err) | ||
| 11 | + token = api_token | ||
| 12 | + acc = account | ||
| 13 | + RedmineClient::Base.configure do | ||
| 14 | + self.token = token | ||
| 15 | + self.site = acc | ||
| 16 | + end | ||
| 17 | + issue = RedmineClient::Issue.new(:project_id => project_id) | ||
| 18 | + issue.subject = issue_title err | ||
| 19 | + issue.description = body_template.result(binding) | ||
| 20 | + issue.save! | ||
| 21 | + 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}") | ||
| 22 | + end | ||
| 23 | + | ||
| 24 | + def body_template | ||
| 25 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/redmine_body.txt.erb")) | ||
| 26 | + end | ||
| 27 | +end | ||
| 28 | + |
app/views/apps/_fields.html.haml
| @@ -50,40 +50,40 @@ | @@ -50,40 +50,40 @@ | ||
| 50 | = f.fields_for :issue_tracker do |w| | 50 | = f.fields_for :issue_tracker do |w| |
| 51 | %div.issue_tracker.nested | 51 | %div.issue_tracker.nested |
| 52 | %div.choose | 52 | %div.choose |
| 53 | - = w.radio_button :issue_tracker_type, :none | ||
| 54 | - = label_tag :issue_tracker_type_none, '(None)', :for => label_for_attr(w, 'issue_tracker_type_none') | ||
| 55 | - = w.radio_button :issue_tracker_type, :lighthouseapp | ||
| 56 | - = label_tag :issue_tracker_type_lighthouseapp, 'Lighthouse', :for => label_for_attr(w, 'issue_tracker_type_lighthouseapp') | ||
| 57 | - = w.radio_button :issue_tracker_type, :redmine | ||
| 58 | - = label_tag :issue_tracker_type_redmine, 'Redmine', :for => label_for_attr(w, 'issue_tracker_type_redmine') | ||
| 59 | - = w.radio_button :issue_tracker_type, :pivotal | ||
| 60 | - = label_tag :issue_tracker_type_pivotal, 'Pivotal Tracker', :for => label_for_attr(w, 'issue_tracker_type_pivotal') | ||
| 61 | - = w.radio_button :issue_tracker_type, :fogbugz | ||
| 62 | - = label_tag :issue_tracker_type_fogbugz, 'FogBugz', :for => label_for_attr(w, 'issue_tracker_type_fogbugz') | ||
| 63 | - = w.radio_button :issue_tracker_type, :mingle | ||
| 64 | - = label_tag :issue_tracker_type_fogbugz, 'Mingle', :for => label_for_attr(w, 'issue_tracker_type_mingle') | ||
| 65 | - %div.tracker_params.none{:class => no_tracker?(w.object) ? 'chosen' : nil} | 53 | + = w.radio_button :type, "IssueTracker", 'data-section' => 'none' |
| 54 | + = label_tag :type_none, '(None)', :for => label_for_attr(w, 'type_none') | ||
| 55 | + = w.radio_button :type, "LighthouseTracker", 'data-section' => 'lighthouse' | ||
| 56 | + = label_tag :type_lighthouseapp, 'Lighthouse', :for => label_for_attr(w, 'type_lighthouseapp') | ||
| 57 | + = w.radio_button :type, "RedmineTracker", 'data-section' => 'redmine' | ||
| 58 | + = label_tag :type_redmine, 'Redmine', :for => label_for_attr(w, 'type_redmine') | ||
| 59 | + = w.radio_button :type, "PivotalTracker", 'data-section' => 'pivotal' | ||
| 60 | + = label_tag :type_pivotal, 'Pivotal Tracker', :for => label_for_attr(w, 'type_pivotal') | ||
| 61 | + = w.radio_button :type, "FogbugzTracker", 'data-section' => 'fogbugz' | ||
| 62 | + = label_tag :type_fogbugz, 'FogBugz', :for => label_for_attr(w, 'type_fogbugz') | ||
| 63 | + = w.radio_button :type, "MingleTracker", 'data-section' => 'mingle' | ||
| 64 | + = label_tag :type_fogbugz, 'Mingle', :for => label_for_attr(w, 'type_mingle') | ||
| 65 | + %div.tracker_params.none{:class => (w.object && !(w.object.class < IssueTracker)) ? 'chosen' : nil} | ||
| 66 | %p When no issue tracker has been configured, you will be able to leave comments on errors. | 66 | %p When no issue tracker has been configured, you will be able to leave comments on errors. |
| 67 | - %div.tracker_params.lighthouseapp{:class => lighthouseapp_tracker?(w.object) ? 'chosen' : nil} | 67 | + %div.tracker_params.lighthouse{:class => w.object.is_a?(LighthouseTracker) ? 'chosen' : nil} |
| 68 | = w.label :account, "Account" | 68 | = w.label :account, "Account" |
| 69 | = w.text_field :account, :placeholder => "abc from abc.lighthouseapp.com" | 69 | = w.text_field :account, :placeholder => "abc from abc.lighthouseapp.com" |
| 70 | = w.label :api_token, "API token" | 70 | = w.label :api_token, "API token" |
| 71 | = w.text_field :api_token, :placeholder => "API Token for your account" | 71 | = w.text_field :api_token, :placeholder => "API Token for your account" |
| 72 | = w.label :project_id, "Project ID" | 72 | = w.label :project_id, "Project ID" |
| 73 | = w.text_field :project_id | 73 | = w.text_field :project_id |
| 74 | - %div.tracker_params.redmine{:class => redmine_tracker?(w.object) ? 'chosen' : nil} | 74 | + %div.tracker_params.redmine{:class => w.object.is_a?(RedmineTracker) ? 'chosen' : nil} |
| 75 | = w.label :account, "Redmine URL" | 75 | = w.label :account, "Redmine URL" |
| 76 | = w.text_field :account, :placeholder => "like http://www.redmine.org/" | 76 | = w.text_field :account, :placeholder => "like http://www.redmine.org/" |
| 77 | = w.label :api_token, "API token" | 77 | = w.label :api_token, "API token" |
| 78 | = w.text_field :api_token, :placeholder => "API Token for your account" | 78 | = w.text_field :api_token, :placeholder => "API Token for your account" |
| 79 | = w.label :project_id, "Project ID" | 79 | = w.label :project_id, "Project ID" |
| 80 | = w.text_field :project_id | 80 | = w.text_field :project_id |
| 81 | - %div.tracker_params.pivotal{:class => pivotal_tracker?(w.object) ? 'chosen' : nil} | 81 | + %div.tracker_params.pivotal{:class => w.object.is_a?(PivotalLabsTracker) ? 'chosen' : nil} |
| 82 | = w.label :project_id, "Project ID" | 82 | = w.label :project_id, "Project ID" |
| 83 | = w.text_field :project_id | 83 | = w.text_field :project_id |
| 84 | = w.label :api_token, "API token" | 84 | = w.label :api_token, "API token" |
| 85 | = w.text_field :api_token, :placeholder => "API Token for your account" | 85 | = w.text_field :api_token, :placeholder => "API Token for your account" |
| 86 | - %div.tracker_params.fogbugz{:class => fogbugz_tracker?(w.object) ? 'chosen' : nil} | 86 | + %div.tracker_params.fogbugz{:class => w.object.is_a?(FogbugzTracker) ? 'chosen' : nil} |
| 87 | = w.label :project_id, "Area Name" | 87 | = w.label :project_id, "Area Name" |
| 88 | = w.text_field :project_id | 88 | = w.text_field :project_id |
| 89 | = w.label :account, "FogBugz URL" | 89 | = w.label :account, "FogBugz URL" |
| @@ -92,7 +92,7 @@ | @@ -92,7 +92,7 @@ | ||
| 92 | = w.text_field :username, :placeholder => 'Username/Email for your account' | 92 | = w.text_field :username, :placeholder => 'Username/Email for your account' |
| 93 | = w.label :password, 'Password' | 93 | = w.label :password, 'Password' |
| 94 | = w.password_field :password, :placeholder => 'Password for your account' | 94 | = w.password_field :password, :placeholder => 'Password for your account' |
| 95 | - %div.tracker_params.mingle{:class => mingle_tracker?(w.object) ? 'chosen' : nil} | 95 | + %div.tracker_params.mingle{:class => w.object.is_a?(MingleTracker) ? 'chosen' : nil} |
| 96 | = w.label :account, "Mingle URL" | 96 | = w.label :account, "Mingle URL" |
| 97 | = w.text_field :account, :placeholder => "http://mingle.yoursite.com/" | 97 | = w.text_field :account, :placeholder => "http://mingle.yoursite.com/" |
| 98 | = w.label :project_id, "Project ID" | 98 | = w.label :project_id, "Project ID" |
app/views/errs/fogbugz_body.txt.erb
| @@ -1,31 +0,0 @@ | @@ -1,31 +0,0 @@ | ||
| 1 | -"See this exception on Errbit": <%= app_err_url(err.app, err) %> | ||
| 2 | -<% if notice = err.notices.first %> | ||
| 3 | - <%= notice.message %> | ||
| 4 | - | ||
| 5 | - Summary | ||
| 6 | - - Where | ||
| 7 | - <%= notice.err.where %> | ||
| 8 | - | ||
| 9 | - - Occured | ||
| 10 | - <%= notice.created_at.to_s(:micro) %> | ||
| 11 | - | ||
| 12 | - - Similar | ||
| 13 | - <%= (notice.err.notices_count - 1).to_s %> | ||
| 14 | - | ||
| 15 | - Params | ||
| 16 | - <%= pretty_hash(notice.params) %> | ||
| 17 | - | ||
| 18 | - Session | ||
| 19 | - <%= pretty_hash(notice.session) %> | ||
| 20 | - | ||
| 21 | - Backtrace | ||
| 22 | - <% for line in notice.backtrace %> | ||
| 23 | - <%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> | ||
| 24 | - <% end %> | ||
| 25 | - | ||
| 26 | - Environment | ||
| 27 | - <% for key, val in notice.env_vars %> | ||
| 28 | - <%= key %>: <%= val %> | ||
| 29 | - <% end %> | ||
| 30 | -<% end %> | ||
| 31 | - |
app/views/errs/lighthouseapp_body.txt.erb
| @@ -1,34 +0,0 @@ | @@ -1,34 +0,0 @@ | ||
| 1 | -[See this exception on Errbit](<%= app_err_url err.app, err %> "See this exception on Errbit") | ||
| 2 | -<% if notice = err.notices.first %> | ||
| 3 | - # <%= notice.message %> # | ||
| 4 | - ## Summary ## | ||
| 5 | - <% if notice.request['url'].present? %> | ||
| 6 | - ### URL ### | ||
| 7 | - [<%= notice.request['url'] %>](<%= notice.request['url'] %>)" | ||
| 8 | - <% end %> | ||
| 9 | - ### Where ### | ||
| 10 | - <%= notice.err.where %> | ||
| 11 | - | ||
| 12 | - ### Occured ### | ||
| 13 | - <%= notice.created_at.to_s(:micro) %> | ||
| 14 | - | ||
| 15 | - ### Similar ### | ||
| 16 | - <%= (notice.err.notices_count - 1).to_s %> | ||
| 17 | - | ||
| 18 | - ## Params ## | ||
| 19 | - <code><%= pretty_hash(notice.params) %></code> | ||
| 20 | - | ||
| 21 | - ## Session ## | ||
| 22 | - <code><%= pretty_hash(notice.session) %></code> | ||
| 23 | - | ||
| 24 | - ## Backtrace ## | ||
| 25 | - <code> | ||
| 26 | - <% for line in notice.backtrace %><%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> -> **<%= line['method'] %>** | ||
| 27 | - <% end %> | ||
| 28 | - </code> | ||
| 29 | - | ||
| 30 | - ## Environment ## | ||
| 31 | - <% for key, val in notice.env_vars %> | ||
| 32 | - <%= key %>: <%= val %> | ||
| 33 | - <% end %> | ||
| 34 | -<% end %> |
app/views/errs/pivotal_body.txt.erb
| @@ -1,16 +0,0 @@ | @@ -1,16 +0,0 @@ | ||
| 1 | -See this exception on Errbit: <%= app_err_url err.app, err %> | ||
| 2 | -<% if notice = err.notices.first %> | ||
| 3 | - <% if notice.request['url'].present? %>URL: <%= notice.request['url'] %><% end %> | ||
| 4 | - Where: <%= notice.err.where %> | ||
| 5 | - Occurred: <%= notice.created_at.to_s :micro %> | ||
| 6 | - Similar: <%= (notice.err.notices.count - 1).to_s %> | ||
| 7 | - | ||
| 8 | - Params: | ||
| 9 | - <%= pretty_hash notice.params %> | ||
| 10 | - | ||
| 11 | - Session: | ||
| 12 | - <%= pretty_hash notice.session %> | ||
| 13 | - | ||
| 14 | - Backtrace: | ||
| 15 | - <%= notice.backtrace[0..4].map { |line| "#{line['number']}: #{line['file'].sub(/^\[PROJECT_ROOT\]/, '')} -> *#{line['method']}*" }.join "\n" %> | ||
| 16 | -<% end %> |
app/views/errs/redmine_body.txt.erb
| @@ -1,44 +0,0 @@ | @@ -1,44 +0,0 @@ | ||
| 1 | -<% if notice = err.notices.first %> | ||
| 2 | -h1. <%= notice.message %> | ||
| 3 | - | ||
| 4 | -h3. "See this exception on Errbit":<%= app_err_url err.app, err %> | ||
| 5 | - | ||
| 6 | -h2. Summary | ||
| 7 | -<% if notice.request['url'].present? %> | ||
| 8 | -h3. URL | ||
| 9 | - | ||
| 10 | -"<%= notice.request['url'] %>":<%= notice.request['url'] %> | ||
| 11 | -<% end %> | ||
| 12 | -h3. Where | ||
| 13 | - | ||
| 14 | -<%= notice.err.where %> | ||
| 15 | - | ||
| 16 | -h3. Occured | ||
| 17 | - | ||
| 18 | -<%= notice.created_at.to_s(:micro) %> | ||
| 19 | - | ||
| 20 | -h3. Similar | ||
| 21 | - | ||
| 22 | -<%= (notice.err.notices_count - 1).to_s %> | ||
| 23 | - | ||
| 24 | -h2. Params | ||
| 25 | - | ||
| 26 | -<pre><%= pretty_hash(notice.params) %></pre> | ||
| 27 | - | ||
| 28 | -h2. Session | ||
| 29 | - | ||
| 30 | -<pre><%= pretty_hash(notice.session) %></pre> | ||
| 31 | - | ||
| 32 | -h2. Backtrace | ||
| 33 | - | ||
| 34 | -| Line | File | Method | | ||
| 35 | -<% for line in notice.backtrace %>| <%= line['number'] %> | <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> | *<%= line['method'] %>* | | ||
| 36 | -<% end %> | ||
| 37 | - | ||
| 38 | -h2. Environment | ||
| 39 | - | ||
| 40 | -<% for key, val in notice.env_vars %>| <%= key %> | <%= val %> | | ||
| 41 | -<% end %> | ||
| 42 | - | ||
| 43 | -<% end %> | ||
| 44 | - |
app/views/errs/show.html.haml
| @@ -13,9 +13,9 @@ | @@ -13,9 +13,9 @@ | ||
| 13 | - content_for :action_bar do | 13 | - content_for :action_bar do |
| 14 | - if @err.app.issue_tracker_configured? | 14 | - if @err.app.issue_tracker_configured? |
| 15 | - if @err.issue_link.blank? | 15 | - if @err.issue_link.blank? |
| 16 | - %span= link_to 'create issue', create_issue_app_err_path(@app, @err), :method => :post, :class => "#{@app.issue_tracker.issue_tracker_type}_create create-issue" | 16 | + %span= link_to 'create issue', create_issue_app_err_path(@app, @err), :method => :post, :class => "#{@app.issue_tracker.class.label}_create create-issue" |
| 17 | - else | 17 | - else |
| 18 | - %span= link_to 'go to issue', @err.issue_link, :class => "#{@app.issue_tracker.issue_tracker_type}_goto goto-issue" | 18 | + %span= link_to 'go to issue', @err.issue_link, :class => "#{@app.issue_tracker.class.label}_goto goto-issue" |
| 19 | = link_to 'unlink issue', unlink_issue_app_err_path(@app, @err), :method => :delete, :confirm => "Unlink err issues?", :class => "unlink-issue" | 19 | = link_to 'unlink issue', unlink_issue_app_err_path(@app, @err), :method => :delete, :confirm => "Unlink err issues?", :class => "unlink-issue" |
| 20 | - if @err.unresolved? | 20 | - if @err.unresolved? |
| 21 | %span= link_to 'resolve', resolve_app_err_path(@app, @err), :method => :put, :confirm => err_confirm, :class => 'resolve' | 21 | %span= link_to 'resolve', resolve_app_err_path(@app, @err), :method => :put, :confirm => err_confirm, :class => 'resolve' |
| @@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
| 1 | +"See this exception on Errbit": <%= app_err_url(err.app, err) %> | ||
| 2 | +<% if notice = err.notices.first %> | ||
| 3 | + <%= notice.message %> | ||
| 4 | + | ||
| 5 | + Summary | ||
| 6 | + - Where | ||
| 7 | + <%= notice.err.where %> | ||
| 8 | + | ||
| 9 | + - Occured | ||
| 10 | + <%= notice.created_at.to_s(:micro) %> | ||
| 11 | + | ||
| 12 | + - Similar | ||
| 13 | + <%= (notice.err.notices_count - 1).to_s %> | ||
| 14 | + | ||
| 15 | + Params | ||
| 16 | + <%= pretty_hash(notice.params) %> | ||
| 17 | + | ||
| 18 | + Session | ||
| 19 | + <%= pretty_hash(notice.session) %> | ||
| 20 | + | ||
| 21 | + Backtrace | ||
| 22 | + <% for line in notice.backtrace %> | ||
| 23 | + <%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> | ||
| 24 | + <% end %> | ||
| 25 | + | ||
| 26 | + Environment | ||
| 27 | + <% for key, val in notice.env_vars %> | ||
| 28 | + <%= key %>: <%= val %> | ||
| 29 | + <% end %> | ||
| 30 | +<% end %> | ||
| 31 | + |
| @@ -0,0 +1,34 @@ | @@ -0,0 +1,34 @@ | ||
| 1 | +[See this exception on Errbit](<%= app_err_url err.app, err %> "See this exception on Errbit") | ||
| 2 | +<% if notice = err.notices.first %> | ||
| 3 | + # <%= notice.message %> # | ||
| 4 | + ## Summary ## | ||
| 5 | + <% if notice.request['url'].present? %> | ||
| 6 | + ### URL ### | ||
| 7 | + [<%= notice.request['url'] %>](<%= notice.request['url'] %>)" | ||
| 8 | + <% end %> | ||
| 9 | + ### Where ### | ||
| 10 | + <%= notice.err.where %> | ||
| 11 | + | ||
| 12 | + ### Occured ### | ||
| 13 | + <%= notice.created_at.to_s(:micro) %> | ||
| 14 | + | ||
| 15 | + ### Similar ### | ||
| 16 | + <%= (notice.err.notices_count - 1).to_s %> | ||
| 17 | + | ||
| 18 | + ## Params ## | ||
| 19 | + <code><%= pretty_hash(notice.params) %></code> | ||
| 20 | + | ||
| 21 | + ## Session ## | ||
| 22 | + <code><%= pretty_hash(notice.session) %></code> | ||
| 23 | + | ||
| 24 | + ## Backtrace ## | ||
| 25 | + <code> | ||
| 26 | + <% for line in notice.backtrace %><%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> -> **<%= line['method'] %>** | ||
| 27 | + <% end %> | ||
| 28 | + </code> | ||
| 29 | + | ||
| 30 | + ## Environment ## | ||
| 31 | + <% for key, val in notice.env_vars %> | ||
| 32 | + <%= key %>: <%= val %> | ||
| 33 | + <% end %> | ||
| 34 | +<% end %> |
| @@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
| 1 | +See this exception on Errbit: <%= app_err_url err.app, err %> | ||
| 2 | +<% if notice = err.notices.first %> | ||
| 3 | + <% if notice.request['url'].present? %>URL: <%= notice.request['url'] %><% end %> | ||
| 4 | + Where: <%= notice.err.where %> | ||
| 5 | + Occurred: <%= notice.created_at.to_s :micro %> | ||
| 6 | + Similar: <%= (notice.err.notices.count - 1).to_s %> | ||
| 7 | + | ||
| 8 | + Params: | ||
| 9 | + <%= pretty_hash notice.params %> | ||
| 10 | + | ||
| 11 | + Session: | ||
| 12 | + <%= pretty_hash notice.session %> | ||
| 13 | + | ||
| 14 | + Backtrace: | ||
| 15 | + <%= notice.backtrace[0..4].map { |line| "#{line['number']}: #{line['file'].sub(/^\[PROJECT_ROOT\]/, '')} -> *#{line['method']}*" }.join "\n" %> | ||
| 16 | +<% end %> |
| @@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
| 1 | +<% if notice = err.notices.first %> | ||
| 2 | +h1. <%= notice.message %> | ||
| 3 | + | ||
| 4 | +h3. "See this exception on Errbit":<%= app_err_url err.app, err %> | ||
| 5 | + | ||
| 6 | +h2. Summary | ||
| 7 | +<% if notice.request['url'].present? %> | ||
| 8 | +h3. URL | ||
| 9 | + | ||
| 10 | +"<%= notice.request['url'] %>":<%= notice.request['url'] %> | ||
| 11 | +<% end %> | ||
| 12 | +h3. Where | ||
| 13 | + | ||
| 14 | +<%= notice.err.where %> | ||
| 15 | + | ||
| 16 | +h3. Occured | ||
| 17 | + | ||
| 18 | +<%= notice.created_at.to_s(:micro) %> | ||
| 19 | + | ||
| 20 | +h3. Similar | ||
| 21 | + | ||
| 22 | +<%= (notice.err.notices_count - 1).to_s %> | ||
| 23 | + | ||
| 24 | +h2. Params | ||
| 25 | + | ||
| 26 | +<pre><%= pretty_hash(notice.params) %></pre> | ||
| 27 | + | ||
| 28 | +h2. Session | ||
| 29 | + | ||
| 30 | +<pre><%= pretty_hash(notice.session) %></pre> | ||
| 31 | + | ||
| 32 | +h2. Backtrace | ||
| 33 | + | ||
| 34 | +| Line | File | Method | | ||
| 35 | +<% for line in notice.backtrace %>| <%= line['number'] %> | <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> | *<%= line['method'] %>* | | ||
| 36 | +<% end %> | ||
| 37 | + | ||
| 38 | +h2. Environment | ||
| 39 | + | ||
| 40 | +<% for key, val in notice.env_vars %>| <%= key %> | <%= val %> | | ||
| 41 | +<% end %> | ||
| 42 | + | ||
| 43 | +<% end %> | ||
| 44 | + |
config/application.rb
| @@ -19,7 +19,7 @@ module Errbit | @@ -19,7 +19,7 @@ module Errbit | ||
| 19 | # -- all .rb files in that directory are automatically loaded. | 19 | # -- all .rb files in that directory are automatically loaded. |
| 20 | 20 | ||
| 21 | # Custom directories with classes and modules you want to be autoloadable. | 21 | # Custom directories with classes and modules you want to be autoloadable. |
| 22 | - # config.autoload_paths += %W(#{config.root}/extras) | 22 | + config.autoload_paths += %W(app/models/issue_trackers) |
| 23 | 23 | ||
| 24 | # Only load the plugins named here, in the order given (default is alphabetical). | 24 | # Only load the plugins named here, in the order given (default is alphabetical). |
| 25 | # :all can be used as a placeholder for all plugins not explicitly named. | 25 | # :all can be used as a placeholder for all plugins not explicitly named. |
| @@ -53,3 +53,4 @@ module Errbit | @@ -53,3 +53,4 @@ module Errbit | ||
| 53 | config.filter_parameters += [:password] | 53 | config.filter_parameters += [:password] |
| 54 | end | 54 | end |
| 55 | end | 55 | end |
| 56 | + |
config/initializers/issue_trackers.rb
| @@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
| 1 | +class MoveIssueTrackersToSti < Mongoid::Migration | ||
| 2 | + def self.up | ||
| 3 | + App.all.each do |app| | ||
| 4 | + # Update all embedded issue trackers to use STI patterns. | ||
| 5 | + # All issue trackers now subclass the IssueTracker model, | ||
| 6 | + # and their class is stored in the '_type' field, which is | ||
| 7 | + # also aliased to 'type'. | ||
| 8 | + if app.issue_tracker && app.issue_tracker.attributes["issue_tracker_type"] | ||
| 9 | + app.issue_tracker._type = case app.issue_tracker.issue_tracker_type | ||
| 10 | + when 'lighthouseapp'; "LighthouseTracker" | ||
| 11 | + when 'redmine'; "RedmineTracker" | ||
| 12 | + when 'pivotal'; "PivotalLabsTracker" | ||
| 13 | + when 'fogbugz'; "FogbugzTracker" | ||
| 14 | + when 'mingle'; "MingleTracker" | ||
| 15 | + else; nil | ||
| 16 | + end | ||
| 17 | + if app.issue_tracker.issue_tracker_type == "none" | ||
| 18 | + app.issue_tracker = nil | ||
| 19 | + else | ||
| 20 | + app.issue_tracker.issue_tracker_type = nil | ||
| 21 | + end | ||
| 22 | + app.save | ||
| 23 | + end | ||
| 24 | + end | ||
| 25 | + end | ||
| 26 | + | ||
| 27 | + def self.down | ||
| 28 | + end | ||
| 29 | +end | ||
| 30 | + |
| @@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
| 1 | +module Mingle | ||
| 2 | + class Card < ActiveResource::Base | ||
| 3 | + # site template ~> "https://username:password@mingle.example.com/api/v1/projects/:project_id/" | ||
| 4 | + end | ||
| 5 | + def self.set_site(site) | ||
| 6 | + # ActiveResource seems to clone and freeze the @site variable | ||
| 7 | + # after the first use. It seems that the only way to change @site | ||
| 8 | + # is to drop the subclass, and then reload it. | ||
| 9 | + Mingle.send(:remove_const, :Card) | ||
| 10 | + load File.join(Rails.root,'lib','issue_tracker_apis','mingle.rb') | ||
| 11 | + Mingle::Card.site = site | ||
| 12 | + end | ||
| 13 | +end | ||
| 14 | + |
lib/issue_trackers/mingle.rb
| @@ -1,14 +0,0 @@ | @@ -1,14 +0,0 @@ | ||
| 1 | -module Mingle | ||
| 2 | - class Card < ActiveResource::Base | ||
| 3 | - # site template ~> "https://username:password@mingle.example.com/api/v1/projects/:project_id/" | ||
| 4 | - end | ||
| 5 | - def self.set_site(site) | ||
| 6 | - # ActiveResource seems to clone and freeze the @site variable | ||
| 7 | - # after the first use. It seems that the only way to change @site | ||
| 8 | - # is to drop the subclass, and then reload it. | ||
| 9 | - Mingle.send(:remove_const, :Card) | ||
| 10 | - load File.join(Rails.root,'lib','issue_trackers','mingle.rb') | ||
| 11 | - Mingle::Card.site = site | ||
| 12 | - end | ||
| 13 | -end | ||
| 14 | - |
public/javascripts/form.js
| @@ -71,8 +71,8 @@ function activateTypeSelector(field_class, section_class) { | @@ -71,8 +71,8 @@ function activateTypeSelector(field_class, section_class) { | ||
| 71 | $('div.'+field_class+' > div.'+section_class).not('.chosen').find('input') | 71 | $('div.'+field_class+' > div.'+section_class).not('.chosen').find('input') |
| 72 | .attr('disabled','disabled').val(''); | 72 | .attr('disabled','disabled').val(''); |
| 73 | 73 | ||
| 74 | - $('div.'+field_class+' input[name*='+field_class+'_type]').live('click', function(){ | ||
| 75 | - var chosen = $(this).val(); | 74 | + $('div.'+field_class+' input[name*=type]').live('click', function(){ |
| 75 | + var chosen = $(this).data("section"); | ||
| 76 | var wrapper = $(this).closest('.nested'); | 76 | var wrapper = $(this).closest('.nested'); |
| 77 | wrapper.find('div.chosen.'+section_class).removeClass('chosen').find('input').attr('disabled','disabled'); | 77 | wrapper.find('div.chosen.'+section_class).removeClass('chosen').find('input').attr('disabled','disabled'); |
| 78 | wrapper.find('div.'+section_class+'.'+chosen).addClass('chosen').find('input').removeAttr('disabled'); | 78 | wrapper.find('div.'+section_class+'.'+chosen).addClass('chosen').find('input').removeAttr('disabled'); |
spec/controllers/apps_controller_spec.rb
| @@ -263,25 +263,25 @@ describe AppsController do | @@ -263,25 +263,25 @@ describe AppsController do | ||
| 263 | context "unknown tracker type" do | 263 | context "unknown tracker type" do |
| 264 | before(:each) do | 264 | before(:each) do |
| 265 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 265 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 266 | - :issue_tracker_type => 'unknown', :project_id => '1234', :api_token => '123123', :account => 'myapp' | 266 | + :type => 'unknown', :project_id => '1234', :api_token => '123123', :account => 'myapp' |
| 267 | } } | 267 | } } |
| 268 | @app.reload | 268 | @app.reload |
| 269 | end | 269 | end |
| 270 | 270 | ||
| 271 | it "should not create issue tracker" do | 271 | it "should not create issue tracker" do |
| 272 | - @app.issue_tracker.should be_nil | 272 | + @app.issue_tracker_configured?.should == false |
| 273 | end | 273 | end |
| 274 | end | 274 | end |
| 275 | 275 | ||
| 276 | context "lighthouseapp" do | 276 | context "lighthouseapp" do |
| 277 | it "should save tracker params" do | 277 | it "should save tracker params" do |
| 278 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 278 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 279 | - :issue_tracker_type => 'lighthouseapp', :project_id => '1234', :api_token => '123123', :account => 'myapp' | 279 | + :type => 'LighthouseTracker', :project_id => '1234', :api_token => '123123', :account => 'myapp' |
| 280 | } } | 280 | } } |
| 281 | @app.reload | 281 | @app.reload |
| 282 | 282 | ||
| 283 | tracker = @app.issue_tracker | 283 | tracker = @app.issue_tracker |
| 284 | - tracker.issue_tracker_type.should == 'lighthouseapp' | 284 | + tracker.should be_a(LighthouseTracker) |
| 285 | tracker.project_id.should == '1234' | 285 | tracker.project_id.should == '1234' |
| 286 | tracker.api_token.should == '123123' | 286 | tracker.api_token.should == '123123' |
| 287 | tracker.account.should == 'myapp' | 287 | tracker.account.should == 'myapp' |
| @@ -289,11 +289,11 @@ describe AppsController do | @@ -289,11 +289,11 @@ describe AppsController do | ||
| 289 | 289 | ||
| 290 | it "should show validation notice when sufficient params are not present" do | 290 | it "should show validation notice when sufficient params are not present" do |
| 291 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 291 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 292 | - :issue_tracker_type => 'lighthouseapp', :project_id => '1234', :api_token => '123123' | 292 | + :type => 'LighthouseTracker', :project_id => '1234', :api_token => '123123' |
| 293 | } } | 293 | } } |
| 294 | @app.reload | 294 | @app.reload |
| 295 | 295 | ||
| 296 | - @app.issue_tracker.should be_nil | 296 | + @app.issue_tracker_configured?.should == false |
| 297 | response.body.should match(/You must specify your Lighthouseapp account, API token and Project ID/) | 297 | response.body.should match(/You must specify your Lighthouseapp account, API token and Project ID/) |
| 298 | end | 298 | end |
| 299 | end | 299 | end |
| @@ -301,12 +301,12 @@ describe AppsController do | @@ -301,12 +301,12 @@ describe AppsController do | ||
| 301 | context "redmine" do | 301 | context "redmine" do |
| 302 | it "should save tracker params" do | 302 | it "should save tracker params" do |
| 303 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 303 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 304 | - :issue_tracker_type => 'redmine', :project_id => '1234', :api_token => '123123', :account => 'http://myapp.com' | 304 | + :type => 'RedmineTracker', :project_id => '1234', :api_token => '123123', :account => 'http://myapp.com' |
| 305 | } } | 305 | } } |
| 306 | @app.reload | 306 | @app.reload |
| 307 | 307 | ||
| 308 | tracker = @app.issue_tracker | 308 | tracker = @app.issue_tracker |
| 309 | - tracker.issue_tracker_type.should == 'redmine' | 309 | + tracker.should be_a(RedmineTracker) |
| 310 | tracker.project_id.should == '1234' | 310 | tracker.project_id.should == '1234' |
| 311 | tracker.api_token.should == '123123' | 311 | tracker.api_token.should == '123123' |
| 312 | tracker.account.should == 'http://myapp.com' | 312 | tracker.account.should == 'http://myapp.com' |
| @@ -314,11 +314,11 @@ describe AppsController do | @@ -314,11 +314,11 @@ describe AppsController do | ||
| 314 | 314 | ||
| 315 | it "should show validation notice when sufficient params are not present" do | 315 | it "should show validation notice when sufficient params are not present" do |
| 316 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 316 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 317 | - :issue_tracker_type => 'redmine', :project_id => '1234', :api_token => '123123' | 317 | + :type => 'RedmineTracker', :project_id => '1234', :api_token => '123123' |
| 318 | } } | 318 | } } |
| 319 | @app.reload | 319 | @app.reload |
| 320 | 320 | ||
| 321 | - @app.issue_tracker.should be_nil | 321 | + @app.issue_tracker_configured?.should == false |
| 322 | response.body.should match(/You must specify your Redmine URL, API token and Project ID/) | 322 | response.body.should match(/You must specify your Redmine URL, API token and Project ID/) |
| 323 | end | 323 | end |
| 324 | end | 324 | end |
| @@ -326,21 +326,21 @@ describe AppsController do | @@ -326,21 +326,21 @@ describe AppsController do | ||
| 326 | context "pivotal" do | 326 | context "pivotal" do |
| 327 | it "should save tracker params" do | 327 | it "should save tracker params" do |
| 328 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 328 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 329 | - :issue_tracker_type => 'pivotal', :project_id => '1234', :api_token => '123123' } } | 329 | + :type => 'PivotalLabsTracker', :project_id => '1234', :api_token => '123123' } } |
| 330 | @app.reload | 330 | @app.reload |
| 331 | 331 | ||
| 332 | tracker = @app.issue_tracker | 332 | tracker = @app.issue_tracker |
| 333 | - tracker.issue_tracker_type.should == 'pivotal' | 333 | + tracker.should be_a(PivotalLabsTracker) |
| 334 | tracker.project_id.should == '1234' | 334 | tracker.project_id.should == '1234' |
| 335 | tracker.api_token.should == '123123' | 335 | tracker.api_token.should == '123123' |
| 336 | end | 336 | end |
| 337 | 337 | ||
| 338 | it "should show validation notice when sufficient params are not present" do | 338 | it "should show validation notice when sufficient params are not present" do |
| 339 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 339 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 340 | - :issue_tracker_type => 'pivotal', :project_id => '1234' } } | 340 | + :type => 'PivotalLabsTracker', :project_id => '1234' } } |
| 341 | @app.reload | 341 | @app.reload |
| 342 | 342 | ||
| 343 | - @app.issue_tracker.should be_nil | 343 | + @app.issue_tracker_configured?.should == false |
| 344 | response.body.should match(/You must specify your Pivotal Tracker API token and Project ID/) | 344 | response.body.should match(/You must specify your Pivotal Tracker API token and Project ID/) |
| 345 | end | 345 | end |
| 346 | end | 346 | end |
| @@ -349,12 +349,12 @@ describe AppsController do | @@ -349,12 +349,12 @@ describe AppsController do | ||
| 349 | context 'with correct params' do | 349 | context 'with correct params' do |
| 350 | before do | 350 | before do |
| 351 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 351 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 352 | - :issue_tracker_type => 'fogbugz', :account => 'abc', :project_id => 'Service - Peon', :username => '1234', :password => '123123' } } | 352 | + :type => 'FogbugzTracker', :account => 'abc', :project_id => 'Service - Peon', :username => '1234', :password => '123123' } } |
| 353 | @app.reload | 353 | @app.reload |
| 354 | end | 354 | end |
| 355 | 355 | ||
| 356 | subject {@app.issue_tracker} | 356 | subject {@app.issue_tracker} |
| 357 | - its(:issue_tracker_type) {should == 'fogbugz'} | 357 | + its(:type) {should == "FogbugzTracker"} |
| 358 | its(:account) {should == 'abc'} | 358 | its(:account) {should == 'abc'} |
| 359 | its(:project_id) {should == 'Service - Peon'} | 359 | its(:project_id) {should == 'Service - Peon'} |
| 360 | its(:username) {should == '1234'} | 360 | its(:username) {should == '1234'} |
| @@ -364,11 +364,11 @@ describe AppsController do | @@ -364,11 +364,11 @@ describe AppsController do | ||
| 364 | context 'insufficient params' do | 364 | context 'insufficient params' do |
| 365 | it 'shows validation notice' do | 365 | it 'shows validation notice' do |
| 366 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 366 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 367 | - :issue_tracker_type => 'fogbugz', :project_id => '1234' } } | 367 | + :type => 'FogbugzTracker', :project_id => '1234' } } |
| 368 | @app.reload | 368 | @app.reload |
| 369 | 369 | ||
| 370 | - @app.issue_tracker.should be_nil | ||
| 371 | - response.body.should match(/You must specify your FogBugz Area Name, Username, and Password/) | 370 | + @app.issue_tracker_configured?.should == false |
| 371 | + response.body.should match(/You must specify your FogBugz Area Name, FogBugz URL, Username, and Password/) | ||
| 372 | end | 372 | end |
| 373 | end | 373 | end |
| 374 | end | 374 | end |
| @@ -377,14 +377,14 @@ describe AppsController do | @@ -377,14 +377,14 @@ describe AppsController do | ||
| 377 | context 'with correct params' do | 377 | context 'with correct params' do |
| 378 | before do | 378 | before do |
| 379 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 379 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 380 | - :issue_tracker_type => 'mingle', :project_id => 'test', :account => 'http://mingle.example.com', | 380 | + :type => 'MingleTracker', :project_id => 'test', :account => 'http://mingle.example.com', |
| 381 | :username => '1234', :password => '123123', :ticket_properties => "card_type = Defect" | 381 | :username => '1234', :password => '123123', :ticket_properties => "card_type = Defect" |
| 382 | } } | 382 | } } |
| 383 | @app.reload | 383 | @app.reload |
| 384 | end | 384 | end |
| 385 | 385 | ||
| 386 | subject {@app.issue_tracker} | 386 | subject {@app.issue_tracker} |
| 387 | - its(:issue_tracker_type) {should == 'mingle'} | 387 | + its(:type) {should == "MingleTracker"} |
| 388 | its(:project_id) {should == 'test'} | 388 | its(:project_id) {should == 'test'} |
| 389 | its(:username) {should == '1234'} | 389 | its(:username) {should == '1234'} |
| 390 | its(:password) {should == '123123'} | 390 | its(:password) {should == '123123'} |
| @@ -392,12 +392,12 @@ describe AppsController do | @@ -392,12 +392,12 @@ describe AppsController do | ||
| 392 | 392 | ||
| 393 | it "should show validation notice when sufficient params are not present" do | 393 | it "should show validation notice when sufficient params are not present" do |
| 394 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | 394 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 395 | - :issue_tracker_type => 'mingle', :project_id => 'test', :account => 'http://mingle.example.com', | 395 | + :type => 'MingleTracker', :project_id => 'test', :account => 'http://mingle.example.com', |
| 396 | :username => '1234', :password => '1234', :ticket_properties => "cards_type = Defect" | 396 | :username => '1234', :password => '1234', :ticket_properties => "cards_type = Defect" |
| 397 | } } | 397 | } } |
| 398 | @app.reload | 398 | @app.reload |
| 399 | 399 | ||
| 400 | - @app.issue_tracker.should be_nil | 400 | + @app.issue_tracker_configured?.should == false |
| 401 | response.body.should match(/You must specify your Mingle URL, Project ID, Card Type \(in default card properties\), Sign-in name, and Password/) | 401 | response.body.should match(/You must specify your Mingle URL, Project ID, Card Type \(in default card properties\), Sign-in name, and Password/) |
| 402 | end | 402 | end |
| 403 | end | 403 | end |
spec/controllers/errs_controller_spec.rb
| @@ -173,7 +173,7 @@ describe ErrsController do | @@ -173,7 +173,7 @@ describe ErrsController do | ||
| 173 | end | 173 | end |
| 174 | 174 | ||
| 175 | it "should exist for err's app with issue tracker" do | 175 | it "should exist for err's app with issue tracker" do |
| 176 | - tracker = Factory(:lighthouseapp_tracker) | 176 | + tracker = Factory(:lighthouse_tracker) |
| 177 | err = Factory(:err, :app => tracker.app) | 177 | err = Factory(:err, :app => tracker.app) |
| 178 | get :show, :app_id => err.app.id, :id => err.id | 178 | get :show, :app_id => err.app.id, :id => err.id |
| 179 | 179 | ||
| @@ -181,7 +181,7 @@ describe ErrsController do | @@ -181,7 +181,7 @@ describe ErrsController do | ||
| 181 | end | 181 | end |
| 182 | 182 | ||
| 183 | it "should not exist for err with issue_link" do | 183 | it "should not exist for err with issue_link" do |
| 184 | - tracker = Factory(:lighthouseapp_tracker) | 184 | + tracker = Factory(:lighthouse_tracker) |
| 185 | err = Factory(:err, :app => tracker.app, :issue_link => "http://some.host") | 185 | err = Factory(:err, :app => tracker.app, :issue_link => "http://some.host") |
| 186 | get :show, :app_id => err.app.id, :id => err.id | 186 | get :show, :app_id => err.app.id, :id => err.id |
| 187 | 187 | ||
| @@ -262,7 +262,7 @@ describe ErrsController do | @@ -262,7 +262,7 @@ describe ErrsController do | ||
| 262 | context "successful issue creation" do | 262 | context "successful issue creation" do |
| 263 | context "lighthouseapp tracker" do | 263 | context "lighthouseapp tracker" do |
| 264 | let(:notice) { Factory :notice } | 264 | let(:notice) { Factory :notice } |
| 265 | - let(:tracker) { Factory :lighthouseapp_tracker, :app => notice.err.app } | 265 | + let(:tracker) { Factory :lighthouse_tracker, :app => notice.err.app } |
| 266 | let(:err) { notice.err } | 266 | let(:err) { notice.err } |
| 267 | 267 | ||
| 268 | before(:each) do | 268 | before(:each) do |
| @@ -326,7 +326,7 @@ describe ErrsController do | @@ -326,7 +326,7 @@ describe ErrsController do | ||
| 326 | 326 | ||
| 327 | context "pivotal tracker" do | 327 | context "pivotal tracker" do |
| 328 | let(:notice) { Factory :notice } | 328 | let(:notice) { Factory :notice } |
| 329 | - let(:tracker) { Factory :pivotal_tracker, :app => notice.err.app, :project_id => 10 } | 329 | + let(:tracker) { Factory :pivotal_labs_tracker, :app => notice.err.app, :project_id => 10 } |
| 330 | let(:err) { notice.err } | 330 | let(:err) { notice.err } |
| 331 | 331 | ||
| 332 | before(:each) do | 332 | before(:each) do |
| @@ -370,7 +370,7 @@ describe ErrsController do | @@ -370,7 +370,7 @@ describe ErrsController do | ||
| 370 | before(:each) do | 370 | before(:each) do |
| 371 | number = 5 | 371 | number = 5 |
| 372 | @issue_link = "#{tracker.account}/projects/#{tracker.project_id}/cards/#{number}.xml" | 372 | @issue_link = "#{tracker.account}/projects/#{tracker.project_id}/cards/#{number}.xml" |
| 373 | - @basic_auth = tracker.account.gsub("https://", "https://#{tracker.username}:#{tracker.password}@") | 373 | + @basic_auth = tracker.account.gsub("://", "://#{tracker.username}:#{tracker.password}@") |
| 374 | body = "<card><id type=\"integer\">#{number}</id></card>" | 374 | body = "<card><id type=\"integer\">#{number}</id></card>" |
| 375 | stub_request(:post, "#{@basic_auth}/api/v1/projects/#{tracker.project_id}/cards.xml"). | 375 | stub_request(:post, "#{@basic_auth}/api/v1/projects/#{tracker.project_id}/cards.xml"). |
| 376 | to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) | 376 | to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) |
| @@ -415,7 +415,7 @@ describe ErrsController do | @@ -415,7 +415,7 @@ describe ErrsController do | ||
| 415 | 415 | ||
| 416 | context "error during request to a tracker" do | 416 | context "error during request to a tracker" do |
| 417 | context "lighthouseapp tracker" do | 417 | context "lighthouseapp tracker" do |
| 418 | - let(:tracker) { Factory :lighthouseapp_tracker } | 418 | + let(:tracker) { Factory :lighthouse_tracker } |
| 419 | let(:err) { Factory :err, :app => tracker.app } | 419 | let(:err) { Factory :err, :app => tracker.app } |
| 420 | 420 | ||
| 421 | before(:each) do | 421 | before(:each) do |
spec/factories/issue_tracker_factories.rb
| 1 | -Factory.define :generic_tracker, :class => IssueTracker do |e| | 1 | +Factory.define :issue_tracker do |e| |
| 2 | e.api_token { Factory.next :word } | 2 | e.api_token { Factory.next :word } |
| 3 | e.project_id { Factory.next :word } | 3 | e.project_id { Factory.next :word } |
| 4 | e.association :app, :factory => :app | 4 | e.association :app, :factory => :app |
| 5 | -end | ||
| 6 | - | ||
| 7 | -Factory.define :lighthouseapp_tracker, :parent => :generic_tracker do |e| | ||
| 8 | - e.issue_tracker_type 'lighthouseapp' | ||
| 9 | e.account { Factory.next :word } | 5 | e.account { Factory.next :word } |
| 6 | + e.username { Factory.next :word } | ||
| 7 | + e.password { Factory.next :word } | ||
| 10 | end | 8 | end |
| 11 | 9 | ||
| 12 | -Factory.define :redmine_tracker, :parent => :generic_tracker do |e| | ||
| 13 | - e.issue_tracker_type 'redmine' | ||
| 14 | - e.account { "http://#{Factory.next(:word)}.com" } | 10 | +%w(lighthouse pivotal_labs fogbugz).each do |t| |
| 11 | + Factory.define "#{t}_tracker".to_sym, :parent => :issue_tracker, :class => "#{t}_tracker".to_sym do |e|; end | ||
| 15 | end | 12 | end |
| 16 | 13 | ||
| 17 | -Factory.define :pivotal_tracker, :parent => :generic_tracker do |e| | ||
| 18 | - e.issue_tracker_type 'pivotal' | 14 | +Factory.define :redmine_tracker, :parent => :issue_tracker, :class => :redmine_tracker do |e| |
| 15 | + e.account 'http://redmine.example.com' | ||
| 19 | end | 16 | end |
| 20 | 17 | ||
| 21 | -Factory.define :mingle_tracker, :parent => :generic_tracker do |t| | ||
| 22 | - t.issue_tracker_type 'mingle' | ||
| 23 | - t.account "https://mingle.example.com" | ||
| 24 | - t.ticket_properties 'card_type = Defect, defect_status = open, priority = essential' | ||
| 25 | - t.username "test_user" | ||
| 26 | - t.password "test_password" | 18 | +Factory.define :mingle_tracker, :parent => :issue_tracker, :class => :mingle_tracker do |e| |
| 19 | + e.account 'https://mingle.example.com' | ||
| 20 | + e.ticket_properties 'card_type = Defect, defect_status = open, priority = essential' | ||
| 27 | end | 21 | end |
| 28 | 22 |
spec/views/errs/show.html.haml_spec.rb
| @@ -51,7 +51,7 @@ describe "errs/show.html.erb" do | @@ -51,7 +51,7 @@ describe "errs/show.html.erb" do | ||
| 51 | 51 | ||
| 52 | context "with issue tracker" do | 52 | context "with issue tracker" do |
| 53 | def with_issue_tracker(err) | 53 | def with_issue_tracker(err) |
| 54 | - err.app.issue_tracker = IssueTracker.new :issue_tracker_type => "lighthouseapp", :project_id => "1234" | 54 | + err.app.issue_tracker = PivotalLabsTracker.new :api_token => "token token token", :project_id => "1234" |
| 55 | assign :err, err | 55 | assign :err, err |
| 56 | assign :app, err.app | 56 | assign :app, err.app |
| 57 | end | 57 | end |