Skip to content
Browse files

jira plugin refactor to not rely on issue ordering in rss feed

  • Loading branch information...
1 parent 30e5047 commit dd69c9e376197b63fec2ac2808e5f6914c1dde84 joshwand committed with Jun 17, 2009
Showing with 94 additions and 53 deletions.
  1. +93 −52 plugins/jira.rb
  2. +1 −1 spec/jira_spec.rb
View
145 plugins/jira.rb
@@ -4,85 +4,126 @@
class Jira < CampfireBot::Plugin
- at_interval 3.minutes, :fetch_jira
- on_command 'checkjira', :check_jira
+ at_interval 3.minutes, :check_jira
+ on_command 'checkjira', :checkjira_command
def initialize
- puts "#{Time.now} | #{bot.config['room']} | JIRA Plugin | initializing... "
+ log "initializing... "
@data_file = File.join(BOT_ROOT, 'tmp', "jira-#{BOT_ENVIRONMENT}-#{bot.config['room']}.yml")
@cached_ids = YAML::load(File.read(@data_file)) rescue {}
@last_checked ||= 10.minutes.ago
end
-
- def fetch_jira(msg)
+ # respond to checkjira command-- same as interval except we answer with 'no issues found' if
+ def checkjira_command(msg)
+ msg.speak "no new issues since I last checked #{lastlast} ago" if check_jira(msg)
+ end
+
+ def check_jira(msg)
- issuecount = 0
- @cached_ids ||= {}
+ saw_an_issue = false
old_cache = Marshal::load(Marshal.dump(@cached_ids)) # since ruby doesn't have deep copy
- puts "#{Time.now} | #{msg[:room].name} | JIRA Plugin | checking jira for new issues..."
-
- begin
-
- xmldata = open(bot.config['jira_url']).read
- doc = REXML::Document.new(xmldata)
-
-
- tix = []
- doc.elements.each('rss/channel/item') do |ele|
- tix.push(ele)
- end
-
- # need to reverse these elements so we get the oldest one first
- tix.reverse.each do |ele|
- id = ele.elements['key'].text
- id, key = split_spacekey_and_id(id)
-
- if !old_cache.key?(key) or old_cache[key] < id
-
- # puts "#{Time.now} | #{msg[:room].name} | JIRA Plugin | ticket #{ele.elements['key'].text} is new, updating cache and speaking"
- @cached_ids[key] = id if !@cached_ids.key?(id) or @cached_ids[key] < id
-
- issuecount += 1
- link = ele.elements['link'].text
- title = ele.elements['title'].text
- reporter = ele.elements['reporter'].text
- type = ele.elements['type'].text
- priority = ele.elements['priority'].text
- msg.speak("#{type} - #{title} - #{link} - reported by #{reporter} - #{priority}")
- puts "#{Time.now} | #{msg[:room].name} | JIRA Plugin | #{type} - #{title} - #{link} - reported by #{reporter} - #{priority}"
- end
- end
- rescue Exception => e
- puts "#{Time.now} | #{msg[:room].name} | JIRA Plugin | error connecting to jira: #{e.message}"
- end
+ lastlast = time_ago_in_words(@last_checked)
+ tix = fetch_jira_url
- File.open(@data_file, 'w') do |out|
- YAML.dump(@cached_ids, out)
+ tix.each do |ticket|
+ if seen?(ticket, old_cache)
+ saw_an_issue = true
+
+ @cached_ids = update_cache(ticket, @cached_ids)
+ flush_cache(@cached_ids)
+
+ messagetext = "#{ticket[:type]} - #{ticket[:title]} - #{ticket[:link]} - reported by #{ticket[:reporter]} - #{ticket[:priority]}"
+ msg.speak(messagetext)
+ log messagetext
+
+ end
end
@last_checked = Time.now
- puts "#{Time.now} | #{msg[:room].name} | JIRA Plugin | no new issues." if issuecount == 0
- issuecount
+ log "no new issues." if !saw_an_issue
+ saw_an_issue
end
- def check_jira(msg)
- lastlast = time_ago_in_words(@last_checked)
- count = fetch_jira(msg)
- msg.speak "no new issues since I last checked #{lastlast} ago" if count == 0
+ protected
+
+ # fetch jira url and return a list of ticket Hashes
+ def fetch_jira_url()
+ begin
+ log "checking jira for new issues..."
+ xmldata = open(bot.config['jira_url']).read
+ doc = REXML::Document.new(xmldata)
+ rescue Exception => e
+ log "error connecting to jira: #{e.message}"
+ end
+
+ doc.elements.inject('rss/channel/item', []) do |tix, element|
+ tix.push(parse_ticket_info(element))
+ end
+
end
- protected
+ # extract ticket hash from individual xml element
+ def parse_ticket_info(xml_element)
+ id = xml_element.elements['key'].text
+ id, spacekey = split_spacekey_and_id(id)
+
+ link = xml_element.elements['link'].text
+ title = xml_element.elements['title'].text
+ reporter = xml_element.elements['reporter'].text
+ type = xml_element.elements['type'].text
+ priority = xml_element.elements['priority'].text
+
+ return {
+ :spacekey => spacekey,
+ :id => id,
+ :link => link,
+ :title => title,
+ :reporter => reporter,
+ :type => type,
+ :priority => priority
+ }
+ end
+ # extract the spacekey and id from the ticket id
def split_spacekey_and_id(key)
spacekey = key.scan(/^([A-Z]+)/).to_s
id = key.scan(/([0-9]+)$/)[0].to_s.to_i
return id, spacekey
end
+ # has this ticket been seen before this run?
+ def seen?(ticket, old_cache)
+ !old_cache.key?(ticket[:spacekey]) or old_cache[ticket[:spacekey]] < ticket[:id]
+ end
+
+ # only update the cached highest ID if it is in fact the highest ID
+ def update_cache(ticket, cache)
+ cache[ticket[:spacekey]] = ticket[:id] if seen?(ticket, cache)
+ cache
+ end
+
+ # write the cache to disk
+ def flush_cache(cache)
+ File.open(@data_file, 'w') do |out|
+ YAML.dump(cache, out)
+ end
+ end
+
+ # log
+ def log(message)
+ puts "#{Time.now} | #{bot.config['room']} | JIRA Plugin | #{message}"
+ end
+
+
+ #
+ # time/utility functions
+ #
+
+
def time_ago_in_words(from_time, include_seconds = false)
distance_of_time_in_words(from_time, Time.now, include_seconds)
end
View
2 spec/jira_spec.rb
@@ -78,7 +78,7 @@ def jira_response(ticketarray)
@jira.stub!(:open).and_return(mock('foo', :read => xmldata))
- @jira.fetch_jira(@message)
+ @jira.check_jira(@message)
end
describe "seeing a ticket higher than the last stored id" do

0 comments on commit dd69c9e

Please sign in to comment.
Something went wrong with that request. Please try again.