bugmail.rb

Carl Nygard, 2008-04-25 20:31

Download (6.3 KB)

 
1
#!/usr/bin/env ruby
2
3
RAILS_ENV = 'test'
4
REDMINE_ROOT = '/var/www/html/redmine/'
5
# This does _NOT_ work. I looked back 3 revisions and found the correct line
6
#require File.dirname(__FILE__) + '/../config/boot'
7
require REDMINE_ROOT + 'config/environment'
8
9
require 'getoptlong'
10
11
class BugMail
12
13
  attr_accessor :issue, :desc, :subject, :category, :project, :status, 
14
      :tracker, :priority, :author, :email, :allow_override, 
15
      :use_email_header, :input, :debug
16
17
  def initialize
18
19
    @issue = nil
20
    @desc = nil
21
    @subject = nil
22
    @category = nil
23
    @project = nil
24
    @status = nil
25
    @tracker = 'Bug'
26
    @priority = nil
27
    @author = nil
28
    @email = nil
29
    @allow_override = false
30
    @use_email_header = false
31
    @debug = false
32
  end
33
34
  def process(msg)
35
    @issue = line_match(msg, "Issue", @issue)
36
    @subject = line_match(msg, "Subject", @subject)
37
# we can generalize via mail-aliases setup to be <project>@<fqdn>
38
    @project = match(msg, /^To:.*?(\w+)@.*$/, @project) if(@use_email_header)
39
    @project = line_match(msg, "Project", @project)
40
    @status = line_match(msg, "Status", @status)
41
    @tracker = line_match(msg, "Tracker", @racker)
42
    @priority = line_match(msg, "Priority", @priority)
43
    @category = line_match(msg, "Category", @category)
44
    @email = match(msg, /^From:.*?(\w+@[A-Za-z0-9.-]+).*?$/, @email) if(@use_email_header)
45
    @author = line_match(msg, "Author", @author)
46
47
    @desc = block_match(msg, "Description", @desc)
48
49
    puts "Issue: [#{@issue}]" if @debug
50
    puts "Project: [#{@project}]" if @debug
51
    puts "Subject: [#{@subject}]" if @debug
52
    puts "Tracker: [#{@tracker}]" if @debug
53
    puts "Priority: [#{@priority}]" if @debug
54
    puts "Category: [#{@category}]" if @debug
55
    puts "Status: [#{@status}]" if @debug
56
    puts "Author/email: [#{@author}/#{@email}]" if @debug
57
    puts "Desc: [#{@desc}]" if @debug
58
59
    ic = Iconv.new('UTF-8', 'UTF-8')
60
61
    p = Project.find_by_identifier(@project)
62
    if(! p) 
63
      puts 'Unable to find project [#{@project}]'
64
      return false
65
    end
66
67
    priorities = Enumeration.get_values('IPRI')
68
    @DEFAULT_PRIORITY = priorities[0]
69
    @DEFAULT_TRACKER = p.trackers.find_by_position(1) || Tracker.find_by_position(1)
70
    @PRIORITY_MAPPING = {}
71
    priorities.each { |prio| @PRIORITY_MAPPING[prio.name] = prio }
72
73
    puts "Searching for user [#{author}/#{email}]" if debug
74
75
    u = User.find_by_login(@author)
76
    if(! u && @use_email_header)
77
      puts "Searching for user via email: [#{@email}]" if @debug
78
      u = User.find_by_mail(@email)
79
    end
80
81
    if(!u)
82
      puts "Unable to find user"
83
      return false
84
    else
85
      puts "Found user [#{u.login}/#{u.mail}]"
86
    end
87
88
    puts "Searching for issue [#{@issue}]" if @debug
89
    i = Issue.find_by_id(@issue)
90
91
    if(i == nil) 
92
      prio = @PRIORITY_MAPPING[@priority] || @DEFAULT_PRIORITY
93
      st = IssueStatus.find_by_name(@status) || IssueStatus.default
94
      t = p.trackers.find_by_name(@tracker) || @DEFAULT_TRACKER
95
      c = p.issue_categories.find_by_name(@category)
96
      i = Issue.create( :priority => prio,
97
                        :status => st,
98
                        :tracker => t,
99
                        :project => p,
100
                        :category => c,
101
                        :start_date => Date.today,
102
                        :author => u,
103
                        :description => ic.iconv(@desc),
104
                        :subject => ic.iconv(@subject) )
105
      puts "Created issue [#{i.id}] [#{i.to_yaml}]" if @debug
106
107
      if(!i.save)
108
        puts "Failed to save new issue"
109
        exit 1 
110
      end
111
    else
112
      puts "Issue exists, adding comment..."
113
      n = Journal.new(:notes => ic.iconv(@desc),
114
                      :journalized => i,
115
                      :user => u);
116
      if(!n.save)
117
        puts "Failed to add comment"
118
        return false
119
      end
120
    end
121
122
    return true
123
  end
124
125
private
126
  def match(msg, regex, default)
127
    if((@allow_override || default == nil) && (msg =~ regex))
128
      return $1
129
    end
130
    return default
131
  end
132
133
134
  def line_match(msg, label, default)
135
    return match(msg, /^#{label}:[ \t]*(.*)$/, default)
136
  end
137
138
  def block_match(msg, label, default)
139
    return match(msg, /^#{label}:[ \t]*(.*)$/m, default)
140
  end
141
142
end
143
144
opts = GetoptLong.new(
145
      [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
146
      [ '--debug', GetoptLong::NO_ARGUMENT ],
147
      [ '--issue', '-i', GetoptLong::REQUIRED_ARGUMENT ],
148
      [ '--desc', '-d', GetoptLong::REQUIRED_ARGUMENT ],
149
      [ '--subject', '-s', GetoptLong::REQUIRED_ARGUMENT ],
150
      [ '--category', '-c', GetoptLong::REQUIRED_ARGUMENT ],
151
      [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
152
      [ '--tracker', '-t', GetoptLong::REQUIRED_ARGUMENT ],
153
      [ '--status', GetoptLong::REQUIRED_ARGUMENT ],
154
      [ '--priority', GetoptLong::REQUIRED_ARGUMENT ],
155
      [ '--author', '-a',  GetoptLong::REQUIRED_ARGUMENT ],
156
      [ '--file', '-f',  GetoptLong::REQUIRED_ARGUMENT ],
157
      [ '--allow-override',  GetoptLong::NO_ARGUMENT ],
158
      [ '--use-email-header',  GetoptLong::NO_ARGUMENT ]
159
    )
160
161
def usage
162
  puts "Usage: [--help] [--debug] [--allow-override] [--use-email-header] [--file <filename> ] [--<param> <value> ...]"
163
  puts " --help  show this help"
164
  puts " --debug show extra debug information"
165
  puts " --allow-override   allow message contents to override cmd line args"
166
  puts " --use-email-header search in email header for user, subject and project"
167
  puts " --file      get input from a file instead of STDIN"
168
  puts " --<param>   set a parameter's value.  Parameter is one of:"
169
  puts "             issue, project, subject, desc, status, tracker, priority"
170
  puts "             category, author"
171
  exit
172
end
173
174
input = $stdin
175
mailer = BugMail.new
176
177
opts.each do |opt, arg|
178
  case opt
179
  when '--help'
180
    usage
181
  when '--issue'
182
    mailer.issue = arg.to_i
183
  when '--project'
184
    mailer.project = arg
185
  when '--subject'
186
    mailer.subject = arg
187
  when '--desc'
188
    mailer.desc = arg
189
  when '--status'
190
    mailer.status = arg
191
  when '--tracker'
192
    mailer.tracker = arg
193
  when '--priority'
194
    mailer.priority = arg
195
  when '--category'
196
    mailer.category = arg
197
  when '--author'
198
    mailer.author = arg
199
  when '--file'
200
    input = FILE.open(arg, "r")
201
  when '--debug'
202
    mailer.debug = true
203
  when '--allow-override'
204
    mailer.allow_override = true
205
  when '--use-email-header'
206
    mailer.use_email_header = true
207
  end
208
end
209
210
msg = input.read
211
212
mailer.process(msg)
213