trackinator 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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