trackinator 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/bin/trackinate CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
3
  require 'trackinator/importer'
4
+ require 'trackinator/you_track'
5
+ require 'trackinator/google'
4
6
  require 'trollop'
5
7
  require 'etc'
6
8
 
@@ -34,6 +36,13 @@ Trollop::die :google_username, "is required" if opts[:google_username].nil?
34
36
  Trollop::die :google_password, "is required" if opts[:google_password].nil?
35
37
  Trollop::die :host, "is required" if opts[:host].nil?
36
38
 
39
+ you_track = Trackinator::YouTrack.new opts
40
+ google = Trackinator::Google.new opts
41
+
42
+ Trollop::die "Check your YouTrack credentials and try again" unless you_track.is_logged_in?
43
+ Trollop::die "Check your Google credentials and try again" unless google.is_logged_in?
44
+ Trollop::die "You must supply a Google doc filename to import" if ARGV.empty? && opts[:create_rc]
45
+
37
46
  if opts[:create_rc]
38
47
  unless File.exists?("#{Etc.getpwuid.dir}/.trackinatorrc")
39
48
  file = File.new("#{Etc.getpwuid.dir}/.trackinatorrc", "w")
@@ -49,5 +58,13 @@ if opts[:create_rc]
49
58
  end
50
59
  end
51
60
 
52
- importer = Trackinator::Importer.new opts
53
- importer.import ARGV[0]
61
+ if ARGV.length == 1
62
+ importer = Trackinator::Importer.new you_track, google
63
+ issues = importer.import ARGV[0], "YTTP"
64
+
65
+ if issues.length > 0
66
+ issues.each do |issue|
67
+ p issue
68
+ end
69
+ end
70
+ end
@@ -1,10 +1,16 @@
1
1
  module Trackinator
2
2
  class Google
3
- @client
4
-
5
3
  def initialize opts
6
4
  @client = GData::Client::Spreadsheets.new
7
- @client.clientlogin(opts[:google_username], opts[:google_password])
5
+ begin
6
+ @token = @client.clientlogin(opts[:google_username], opts[:google_password])
7
+ rescue
8
+ @token = nil
9
+ end
10
+ end
11
+
12
+ def is_logged_in?
13
+ !@token.nil?
8
14
  end
9
15
 
10
16
  def get_tickets file_name
@@ -20,6 +26,8 @@ module Trackinator
20
26
  tickets
21
27
  end
22
28
 
29
+ private
30
+
23
31
  def get_spreadsheet_key file_name
24
32
  doc_feed = @client.get("http://spreadsheets.google.com/feeds/spreadsheets/private/full").to_xml
25
33
 
@@ -3,25 +3,69 @@ require 'CSV'
3
3
 
4
4
  require 'gdata'
5
5
 
6
- require 'trackinator/google'
7
- require 'trackinator/you_track'
6
+ require 'trackinator'
8
7
 
9
8
  module Trackinator
10
9
  class Importer
11
- @you_track
12
10
 
13
- def initialize opts
14
- @you_track = YouTrack.new opts
15
- @google = Google.new opts
11
+ def initialize you_track, google
12
+ @you_track = you_track
13
+ @google = google
16
14
  end
17
15
 
18
- def import file_name
16
+ def import file_name, project = nil
19
17
  ticket_data = @google.get_tickets file_name
20
18
 
21
- ticket_data.each do |entry|
22
- issue_id = @you_track.is_issue_exists? entry
23
- false unless !issue_id.nil? ? @you_track.update_ticket(issue_id, entry) : @you_track.create_ticket(entry)
19
+ issues = validate_tickets(project, ticket_data)
20
+
21
+ if issues.length == 0
22
+ ticket_data.each do |entry|
23
+ issue_id = @you_track.is_issue_exists? entry
24
+ #false unless !issue_id.nil? ? @you_track.update_ticket(issue_id, entry) : @you_track.create_ticket(entry)
25
+ end
26
+ end
27
+
28
+ issues
29
+ end
30
+
31
+ private
32
+
33
+ def validate_tickets project, tickets
34
+ issues = []
35
+
36
+ issues.concat(@you_track.project_exists?(project))
37
+ issues.concat(@you_track.you_track_fields_defined?(project, tickets[0].keys))
38
+
39
+ tickets.each do |ticket|
40
+ issues.concat(validate_fields(ticket))
41
+ issues.concat(validate_formats(ticket))
24
42
  end
43
+
44
+ issues
45
+ end
46
+
47
+ def validate_fields ticket
48
+ issues = []
49
+
50
+ REQUIRED.each do |req_field|
51
+ unless ticket.keys.include?(req_field) || ticket["type"].downcase.eql?("story")
52
+ issues << "Validation Error: Ticket with ID: #{ticket["id"]} is missing required field '#{req_field}'"
53
+ end
54
+ end
55
+
56
+ issues
57
+ end
58
+
59
+ def validate_formats ticket
60
+ issues = []
61
+
62
+ ticket.keys.each do |key|
63
+ if Trackinator.const_defined?("#{key.upcase}") && Trackinator.const_get("#{key.upcase}").match(ticket[key].downcase).nil?
64
+ issues << "Validation Error: Ticket with ID: #{ticket["id"]} has field '#{key}' with invalid format"
65
+ end
66
+ end
67
+
68
+ issues
25
69
  end
26
70
  end
27
71
  end
@@ -1,3 +1,3 @@
1
1
  module Trackinator
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
@@ -1,14 +1,5 @@
1
1
  module Trackinator
2
2
  class YouTrack
3
- @stack
4
-
5
- @cookie
6
- @connection
7
-
8
- @host
9
- @port
10
- @path_prefix
11
-
12
3
  def initialize opts
13
4
  @stack = []
14
5
 
@@ -19,10 +10,16 @@ module Trackinator
19
10
  login opts[:youtrack_username], opts[:youtrack_password]
20
11
  end
21
12
 
13
+ def is_logged_in?
14
+ !@cookie.nil?
15
+ end
16
+
22
17
  def login username, password
23
18
  @connection = Net::HTTP.new @host, @port
24
19
  response = @connection.post "#{@path_prefix}rest/user/login", "login=#{username}&password=#{password}"
25
- @cookie = response.response['Set-Cookie'].split('; ')[0]
20
+ if response.header.msg.eql? "OK"
21
+ @cookie = response.response['Set-Cookie'].split('; ')[0]
22
+ end
26
23
  end
27
24
 
28
25
  def create_ticket data
@@ -43,6 +40,43 @@ module Trackinator
43
40
  success
44
41
  end
45
42
 
43
+ def project_exists?(project)
44
+ issues = []
45
+
46
+ response = @connection.get("#{@path_prefix}rest/admin/project/#{project}", { 'Cookie' => @cookie, 'Content-Type' => 'text/plain; charset=utf-8' })
47
+ if response.header.msg.eql?("Not Found")
48
+ issues << "Project Error: Project doesn't exist!"
49
+ end
50
+
51
+ issues
52
+ end
53
+
54
+ def you_track_fields_defined?(project, fields)
55
+ issues = []
56
+
57
+ response = @connection.get("#{@path_prefix}rest/admin/project/#{project}/customfield", { 'Cookie' => @cookie, 'Content-Type' => 'text/plain; charset=utf-8' })
58
+ response_xml = REXML::Document.new(response.body)
59
+
60
+ you_track_fields = []
61
+
62
+ response_xml.elements.each('projectCustomFieldRefs/projectCustomField') { |element| you_track_fields << element.attributes["name"].downcase }
63
+
64
+ (fields - REQUIRED).each do |document_field|
65
+ unless you_track_fields.include?(document_field)
66
+ issues << "Validation Error: Custom field '#{document_field}' not found in YouTrack"
67
+ end
68
+ end
69
+
70
+ issues
71
+ end
72
+
73
+ def is_issue_exists? data
74
+ find_response_xml = REXML::Document.new(@connection.get("#{@path_prefix}rest/issue/byproject/#{data['project']}?filter=Import+Identifier:+#{data['project']}-#{data['id']}", { 'Cookie' => @cookie, 'Content-Type' => 'text/plain; charset=utf-8' }).body)
75
+ find_response_xml.elements['issues'].length > 0 ? find_response_xml.elements['issues/issue'].attributes['id'] : nil
76
+ end
77
+
78
+ private
79
+
46
80
  def update_dependencies issue
47
81
  issue_id = issue[0]
48
82
  issue_level = issue[1]
@@ -66,13 +100,6 @@ module Trackinator
66
100
  end
67
101
  end
68
102
 
69
- # YouTrack API calls
70
-
71
- def is_issue_exists? data
72
- find_response_xml = REXML::Document.new(@connection.get("#{@path_prefix}rest/issue/byproject/#{data['project']}?filter=Import+Identifier:+#{data['project']}-#{data['id']}", { 'Cookie' => @cookie, 'Content-Type' => 'text/plain; charset=utf-8' }).body)
73
- find_response_xml.elements['issues'].length > 0 ? find_response_xml.elements['issues/issue'].attributes['id'] : nil
74
- end
75
-
76
103
  def create_youtrack_ticket data
77
104
  response = @connection.put("#{@path_prefix}rest/issue?project=#{data['project']}&summary=#{data['summary']}&description=#{data['description']}&priority=#{data['priority']}", nil, { 'Cookie' => @cookie, 'Content-Type' => 'text/plain; charset=utf-8' })
78
105
  return response.header["Location"].split("/").last, response.header.msg
data/lib/trackinator.rb CHANGED
@@ -1,5 +1,22 @@
1
- require "trackinator/version"
1
+ require 'trackinator/version'
2
+ require 'trackinator/google'
3
+ require 'trackinator/you_track'
4
+
2
5
 
3
6
  module Trackinator
4
- # Your code goes here...
7
+
8
+ ID = /^(?:\d+\.?)+$/
9
+
10
+ TYPE = /^story$|^feature$|^task$|^bug$/
11
+
12
+ PRIORITY = /^low$|^normal$|^high$|^show-stopper$/
13
+
14
+ REQUIRED = %w{
15
+ project
16
+ id
17
+ summary
18
+ description
19
+ outcome
20
+ }
21
+
5
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trackinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-01 00:00:00.000000000 Z
12
+ date: 2012-08-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gdata_19