trackinator 0.0.13 → 0.0.14

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
@@ -13,6 +13,7 @@ opts = Trollop::options do
13
13
  opt :port, "YouTrack port", :type => :int, :default => 80, :short => "r"
14
14
  opt :path_prefix, "YouTrack path prefix (e.g. '/youtrack/')", :type => :string, :default => "/", :short =>"e"
15
15
  opt :create_rc, "Create a .trackinatorrc file in your home dir", :default => false, :short => "c"
16
+ opt :dry_run, "Try it out but don't actually import", :default => false, :short => "d"
16
17
  end
17
18
 
18
19
  unless opts[:create_rc]
@@ -36,7 +37,9 @@ Trollop::die :google_password, "is required" if opts[:google_password].nil?
36
37
  Trollop::die :host, "is required" if opts[:host].nil?
37
38
 
38
39
  you_track = Trackinator::YouTrack.new opts
39
- google = Trackinator::Google.new opts
40
+ you_track.login(opts[:youtrack_username], opts[:youtrack_password])
41
+ google = Trackinator::Google.new(GData::Client::Spreadsheets.new)
42
+ google.login(opts)
40
43
 
41
44
  Trollop::die "Check your YouTrack credentials and try again" unless you_track.is_logged_in?
42
45
  Trollop::die "Check your Google credentials and try again" unless google.is_logged_in?
@@ -63,6 +66,7 @@ end
63
66
 
64
67
  if ARGV.length == 1
65
68
  importer = Trackinator::Importer.new you_track, google
69
+ importer.dry_run = opts[:dry_run]
66
70
  issues = importer.import(ARGV[0])
67
71
 
68
72
  if issues.length > 0
@@ -70,4 +74,6 @@ if ARGV.length == 1
70
74
  p issue
71
75
  end
72
76
  end
77
+
78
+ puts "done..."
73
79
  end
@@ -1,10 +1,13 @@
1
1
  module Trackinator
2
2
  class Google
3
- def initialize opts
4
- @client = GData::Client::Spreadsheets.new
3
+ def initialize client
4
+ @client = client
5
+ end
6
+
7
+ def login opts
5
8
  begin
6
9
  @token = @client.clientlogin(opts[:google_username], opts[:google_password])
7
- rescue
10
+ rescue Exception => e
8
11
  @token = nil
9
12
  end
10
13
  end
@@ -16,9 +19,7 @@ module Trackinator
16
19
  def get_tickets file_name
17
20
  puts "reading document..."
18
21
 
19
- spreadsheet_feed = @client.get("http://spreadsheets.google.com/feeds/worksheets/#{get_spreadsheet_key(file_name)}/private/full").to_xml
20
- spreadsheet_list_data = @client.get(spreadsheet_feed.elements[1, 'entry'].elements[1, 'content'].attributes['src']).to_xml
21
-
22
+ spreadsheet_list_data = get_spreadsheet_list_data file_name
22
23
  tickets = []
23
24
 
24
25
  spreadsheet_list_data.elements.each('entry') do |entry|
@@ -30,6 +31,12 @@ module Trackinator
30
31
 
31
32
  private
32
33
 
34
+ def get_spreadsheet_list_data file_name
35
+ spreadsheet_feed = @client.get("http://spreadsheets.google.com/feeds/worksheets/#{get_spreadsheet_key(file_name)}/private/full").to_xml
36
+ spreadsheet_list_url = spreadsheet_feed.elements[1, 'entry'].elements[1, 'content'].attributes['src']
37
+ @client.get(spreadsheet_list_url).to_xml
38
+ end
39
+
33
40
  def get_spreadsheet_key file_name
34
41
  doc_feed = @client.get("http://spreadsheets.google.com/feeds/spreadsheets/private/full").to_xml
35
42
 
@@ -8,6 +8,8 @@ require 'trackinator'
8
8
  module Trackinator
9
9
  class Importer
10
10
 
11
+ attr_accessor :dry_run
12
+
11
13
  def initialize you_track, google
12
14
  @you_track = you_track
13
15
  @google = google
@@ -18,7 +20,7 @@ module Trackinator
18
20
 
19
21
  issues = validate_tickets(ticket_data)
20
22
 
21
- if issues.length == 0
23
+ if issues.length == 0 && !@dry_run
22
24
  puts "importing..."
23
25
 
24
26
  ticket_data.each do |entry|
@@ -27,8 +29,6 @@ module Trackinator
27
29
  end
28
30
  end
29
31
 
30
- puts "done..."
31
-
32
32
  issues
33
33
  end
34
34
 
@@ -38,12 +38,17 @@ module Trackinator
38
38
  puts "validating..."
39
39
  issues = []
40
40
 
41
+ if tickets.length == 0
42
+ return issues
43
+ end
44
+
41
45
  project = tickets[0]['project']
42
46
 
43
47
  issues.concat(@you_track.project_exists?(project))
44
48
 
45
49
  tickets.each do |ticket|
46
50
  issues.concat(@you_track.you_track_fields_defined?(project, ticket.keys.collect! { |key| key.downcase }))
51
+
47
52
  issues.concat(validate_fields(ticket))
48
53
  issues.concat(validate_formats(ticket))
49
54
  end
@@ -67,12 +72,16 @@ module Trackinator
67
72
  issues = []
68
73
 
69
74
  ticket.keys.each do |key|
70
- if Trackinator.const_defined?("#{key.upcase}") && Trackinator.const_get("#{key.upcase}").match(ticket[key].downcase).nil?
71
- issues << "Validation Error: Ticket with ID: #{ticket["id"]} has field '#{key}' with invalid format"
72
- end
75
+ validate_format(key, ticket[key])
73
76
  end
74
77
 
75
78
  issues
76
79
  end
80
+
81
+ def validate_format key, value
82
+ if Trackinator.const_defined?("#{key.upcase}") && Trackinator.const_get("#{key.upcase}").match(value.downcase).nil?
83
+ issues << "Validation Error: Ticket with ID: #{ticket["id"]} has field '#{key}' with invalid format"
84
+ end
85
+ end
77
86
  end
78
87
  end
@@ -1,3 +1,3 @@
1
1
  module Trackinator
2
- VERSION = "0.0.13"
2
+ VERSION = "0.0.14"
3
3
  end
@@ -9,8 +9,6 @@ module Trackinator
9
9
  @host = opts[:host]
10
10
  @port = opts[:port]
11
11
  @path_prefix = opts[:path_prefix]
12
-
13
- login opts[:youtrack_username], opts[:youtrack_password]
14
12
  end
15
13
 
16
14
  def is_logged_in?
@@ -34,7 +32,7 @@ module Trackinator
34
32
  end
35
33
 
36
34
  def update_ticket issue_id, data
37
- success = set_platform(issue_id, data['platform'])
35
+ success = set_subsystem(issue_id, data['subsystem'])
38
36
  success ? (success = set_summary_and_description(issue_id, data['summary'], data['description'], data['outcome'])) : (return success)
39
37
  success ? (success = set_type(issue_id, data['type'])) : (return success)
40
38
  success ? (success = set_import_identifier(issue_id, "#{data['project']}-#{data['id']}")) : (return success)
@@ -78,7 +76,7 @@ module Trackinator
78
76
  end
79
77
 
80
78
  def is_issue_exists? data
81
- 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)
79
+ find_response_xml = REXML::Document.new(@connection.get("#{@path_prefix}rest/issue/byproject/#{data['project']}?filter=Import+Identifier:+#{data['project']}-#{data['id']}+Subsystem:+#{data['subsystem']}", { 'Cookie' => @cookie, 'Content-Type' => 'text/plain; charset=utf-8' }).body)
82
80
  find_response_xml.elements['issues'].length > 0 ? find_response_xml.elements['issues/issue'].attributes['id'] : nil
83
81
  end
84
82
 
@@ -122,10 +120,10 @@ module Trackinator
122
120
  response.header.msg.eql? "OK"
123
121
  end
124
122
 
125
- def set_platform issue_id, platform
126
- return true if platform.nil?
123
+ def set_subsystem issue_id, subsystem
124
+ return true if subsystem.nil?
127
125
 
128
- response = @connection.post("#{@path_prefix}rest/issue/#{issue_id}/execute?command=Platform+#{URI.escape(platform)}&disableNotifications=true", nil, { 'Cookie' => @cookie })
126
+ response = @connection.post("#{@path_prefix}rest/issue/#{issue_id}/execute?command=Subsystem+#{URI.escape(subsystem)}&disableNotifications=true", nil, { 'Cookie' => @cookie })
129
127
  response.header.msg.eql? "OK"
130
128
  end
131
129
 
data/lib/trackinator.rb CHANGED
@@ -11,6 +11,8 @@ module Trackinator
11
11
 
12
12
  PRIORITY = /^low$|^normal$|^high$|^show-stopper$/
13
13
 
14
+ SUBSYSTEM = /^android$|^backend$|^ios$/
15
+
14
16
  REQUIRED = %w{
15
17
  project
16
18
  id
@@ -2,6 +2,65 @@ require File.expand_path(File.dirname(__FILE__)) + '/../spec_helper'
2
2
 
3
3
  module Trackinator
4
4
  describe Google do
5
- pending "write it"
5
+ context "login" do
6
+ before(:each) do
7
+ @client = mock(GData::Client::Spreadsheets)
8
+ @google = Google.new(@client)
9
+ end
10
+
11
+ it "#login should assign a token" do
12
+ @client.stub!(:clientlogin).and_return(true)
13
+ @google.login({})
14
+ @google.is_logged_in?.should == true
15
+ end
16
+
17
+ it "#login should not assign a token" do
18
+ @client.stub!(:clientlogin).and_raise(Exception.new)
19
+ @google.login({})
20
+ @google.is_logged_in?.should == false
21
+ end
22
+ end
23
+
24
+ context "get_tickets" do
25
+ before(:each) do
26
+ @client = mock(GData::Client::Spreadsheets)
27
+ @google = Google.new(@client)
28
+ @spreadsheet_list_data = mock(REXML::Document)
29
+ @spreadsheet_list_data.stub!(:elements).and_return(@spreadsheet_list_data)
30
+ @google.stub!(:get_spreadsheet_list_data).and_return(@spreadsheet_list_data)
31
+ @google.stub!(:get_ticket_data).and_return( {"foo" => "bar"} )
32
+ end
33
+
34
+ it "#get_tickets should return an empty array" do
35
+ @spreadsheet_list_data.stub!(:each).with("entry")
36
+ tickets = @google.get_tickets("filename")
37
+ tickets.length.should == 0
38
+ end
39
+
40
+ it "#get_tickets should return an array of 1" do
41
+ @spreadsheet_list_data.stub!(:each).with("entry").and_yield(%{entry})
42
+ tickets = @google.get_tickets("filename")
43
+ tickets.length.should == 1
44
+ tickets[0]["foo"].should == "bar"
45
+ end
46
+ end
47
+
48
+ context "get_spreadsheet_list_data" do
49
+ it "#get_spreadsheet_list_data should do something" do
50
+ pending
51
+ end
52
+ end
53
+
54
+ context "get_spreadsheet_key" do
55
+ it "#get_spreadsheet_key should do something" do
56
+ pending
57
+ end
58
+ end
59
+
60
+ context "get_ticket_data" do
61
+ it "#get_ticket_data should do something" do
62
+ pending
63
+ end
64
+ end
6
65
  end
7
66
  end
@@ -2,6 +2,147 @@ require File.expand_path(File.dirname(__FILE__)) + '/../spec_helper'
2
2
 
3
3
  module Trackinator
4
4
  describe Importer do
5
- pending "write it"
5
+ context "import" do
6
+ before(:each) do
7
+ @google = mock(Google)
8
+
9
+ @you_track = mock(YouTrack)
10
+ @you_track.stub!(:is_issue_exists?).and_return(nil)
11
+ @you_track.stub!(:create_ticket).and_return(true)
12
+
13
+ @importer = Importer.new @you_track, @google
14
+ @importer.stub!(:validate_tickets).and_return([])
15
+ end
16
+
17
+ it "#import should return no issues and import" do
18
+ @google.stub!(:get_tickets).and_return([{"type" => "story"}])
19
+ $stdout.should_receive(:puts).with("importing...")
20
+
21
+ issues = @importer.import "filename"
22
+ issues.should == []
23
+ end
24
+
25
+ it "#import should return no issues and not import" do
26
+ @google.stub!(:get_tickets).and_return([])
27
+ $stdout.should_receive(:puts).with("importing...")
28
+
29
+ issues = @importer.import "filename"
30
+ issues.should == []
31
+ end
32
+ end
33
+
34
+ context "validate_tickets" do
35
+ before(:each) do
36
+ @you_track = mock(YouTrack)
37
+ @you_track.stub!(:project_exists?).and_return([])
38
+ @you_track.stub!(:you_track_fields_defined?).and_return([])
39
+
40
+ @google = mock(Google)
41
+
42
+ @importer = Importer.new @you_track, @google
43
+ end
44
+
45
+ it "#validate_tickets should return no issues and validate" do
46
+ @importer.stub!(:validate_fields).and_return([])
47
+ @importer.stub!(:validate_formats).and_return([])
48
+
49
+ issues = @importer.send(:validate_tickets, [{}])
50
+ issues.should == []
51
+ end
52
+
53
+ it "#validate_tickets should return no issues and not validate" do
54
+ @importer.stub!(:validate_fields).and_return([])
55
+ @importer.stub!(:validate_formats).and_return([])
56
+
57
+ issues = @importer.send(:validate_tickets, [])
58
+ issues.should == []
59
+ end
60
+ end
61
+
62
+ context "validate_fields" do
63
+ before(:each) do
64
+ @you_track = mock(YouTrack)
65
+ @google = mock(Google)
66
+
67
+ @importer = Importer.new @you_track, @google
68
+ end
69
+
70
+ it "#validate_fields should return no issues and validate feature" do
71
+ issues = @importer.send(:validate_fields, { "type" => "feature", "project" => "YTTP", "id" => "1.2", "summary" => "A summary", "description" => "A description", "outcome" => "An outcome" })
72
+ issues.should == []
73
+ end
74
+
75
+ it "#validate_fields should return 1 issue: missing project" do
76
+ issues = @importer.send(:validate_fields, { "type" => "feature", "id" => "1.2", "summary" => "A summary", "description" => "A description", "outcome" => "An outcome" })
77
+ issues.size.should == 1
78
+ issues[0].should == "Validation Error: Ticket with ID: 1.2 is missing required field 'project'"
79
+ end
80
+
81
+ it "#validate_fields should return 1 issue: missing id" do
82
+ issues = @importer.send(:validate_fields, { "type" => "feature", "project" => "YTTP", "summary" => "A summary", "description" => "A description", "outcome" => "An outcome" })
83
+ issues.size.should == 1
84
+ issues[0].should == "Validation Error: Ticket with ID: is missing required field 'id'"
85
+ end
86
+
87
+ it "#validate_fields should return 1 issue: missing summary" do
88
+ issues = @importer.send(:validate_fields, { "type" => "feature", "project" => "YTTP", "id" => "1.2", "description" => "A description", "outcome" => "An outcome" })
89
+ issues.size.should == 1
90
+ issues[0].should == "Validation Error: Ticket with ID: 1.2 is missing required field 'summary'"
91
+ end
92
+
93
+ it "#validate_fields should return 1 issue: missing description" do
94
+ issues = @importer.send(:validate_fields, { "type" => "feature", "project" => "YTTP", "id" => "1.2", "summary" => "A summary", "outcome" => "An outcome" })
95
+ issues.size.should == 1
96
+ issues[0].should == "Validation Error: Ticket with ID: 1.2 is missing required field 'description'"
97
+ end
98
+
99
+ it "#validate_fields should return 1 issue: missing outcome" do
100
+ issues = @importer.send(:validate_fields, { "type" => "feature", "project" => "YTTP", "id" => "1.2", "summary" => "A summary", "description" => "A description" })
101
+ issues.size.should == 1
102
+ issues[0].should == "Validation Error: Ticket with ID: 1.2 is missing required field 'outcome'"
103
+ end
104
+ end
105
+
106
+ context "validate_formats" do
107
+ before(:each) do
108
+ @you_track = mock(YouTrack)
109
+ @google = mock(Google)
110
+
111
+ @importer = Importer.new @you_track, @google
112
+ end
113
+
114
+ it "#validate_formats should return no issues and validate" do
115
+ issues = @importer.send(:validate_formats, { "type" => "feature" })
116
+ issues.should == []
117
+ end
118
+
119
+ it "#validate_formats should return no issues and validate" do
120
+ issues = @importer.send(:validate_formats, { "type" => "foo" })
121
+ issues.size.should == 1
122
+ issues[0].should == "Validation Error: Ticket with ID: has field 'type' with invalid format"
123
+ end
124
+
125
+ it "#validate_formats should return no issues and validate" do
126
+ issues = @importer.send(:validate_formats, { "id" => "1.2" })
127
+ issues.should == []
128
+ end
129
+
130
+ it "#validate_formats should return no issues and validate" do
131
+ issues = @importer.send(:validate_formats, { "id" => "junk" })
132
+ issues.size.should == 1
133
+ issues[0].should == "Validation Error: Ticket with ID: junk has field 'id' with invalid format"
134
+ end
135
+
136
+ it "#validate_formats should return no issues and validate" do
137
+ issues = @importer.send(:validate_formats, { "priority" => "normal" })
138
+ issues.should == []
139
+ end
140
+
141
+ it "#validate_formats should return no issues and validate" do
142
+ issues = @importer.send(:validate_formats, { "priority" => "junk" })
143
+ issues.size.should == 1
144
+ issues[0].should == "Validation Error: Ticket with ID: has field 'priority' with invalid format"
145
+ end
146
+ end
6
147
  end
7
148
  end
@@ -2,6 +2,146 @@ require File.expand_path(File.dirname(__FILE__)) + '/../spec_helper'
2
2
 
3
3
  module Trackinator
4
4
  describe YouTrack do
5
- pending "write it"
5
+ context "login" do
6
+ it "#login should assign a cookie" do
7
+ pending
8
+ end
9
+ end
10
+
11
+ context "create_ticket" do
12
+ it "#create_ticket should return true" do
13
+ pending
14
+ end
15
+
16
+ it "#create_ticket should return false" do
17
+ pending
18
+ end
19
+ end
20
+
21
+ context "update_ticket" do
22
+ it "#update_ticket should return true" do
23
+ pending
24
+ end
25
+
26
+ it "#update_ticket should return false" do
27
+ pending
28
+ end
29
+ end
30
+
31
+ context "project_exists?" do
32
+ it "#project_exists? should return no issues" do
33
+ pending
34
+ end
35
+
36
+ it "#project_exists? should return 1 issue" do
37
+ pending
38
+ end
39
+ end
40
+
41
+ context "you_track_fields_defined?" do
42
+ it "#you_track_fields_defined? should return no issues" do
43
+ pending
44
+ end
45
+
46
+ it "#you_track_fields_defined? should return some issues" do
47
+ pending
48
+ end
49
+ end
50
+
51
+ context "is_issue_exists?" do
52
+ it "#is_issue_exists? should return nil" do
53
+ pending
54
+ end
55
+
56
+ it "#is_issue_exists? should return a YouTrack issue id" do
57
+ pending
58
+ end
59
+ end
60
+
61
+ context "update_dependencies" do
62
+ it "#update_dependencies should return true" do
63
+ pending
64
+ end
65
+
66
+ it "#update_dependencies should return false" do
67
+ pending
68
+ end
69
+ end
70
+
71
+ context "create_youtrack_ticket" do
72
+ it "#create_youtrack_ticket should return true" do
73
+ pending
74
+ end
75
+
76
+ it "#create_youtrack_ticket should return false" do
77
+ pending
78
+ end
79
+ end
80
+
81
+ context "create_dependency" do
82
+ it "#create_dependency should return true" do
83
+ pending
84
+ end
85
+
86
+ it "#create_dependency should return false" do
87
+ pending
88
+ end
89
+ end
90
+
91
+ context "set_summary_and_description" do
92
+ it "#set_summary_and_description should return true" do
93
+ pending
94
+ end
95
+
96
+ it "#set_summary_and_description should return false" do
97
+ pending
98
+ end
99
+ end
100
+
101
+ context "set_platform" do
102
+ it "#set_platform should return true" do
103
+ pending
104
+ end
105
+
106
+ it "#set_platform should return false" do
107
+ pending
108
+ end
109
+ end
110
+
111
+ context "set_type" do
112
+ it "#set_type should return true" do
113
+ pending
114
+ end
115
+
116
+ it "#set_type should return false" do
117
+ pending
118
+ end
119
+ end
120
+
121
+ context "set_import_identifier" do
122
+ it "#set_import_identifier should return true" do
123
+ pending
124
+ end
125
+
126
+ it "#set_import_identifier should return false" do
127
+ pending
128
+ end
129
+ end
130
+
131
+ context "set_design_reference" do
132
+ it "#set_design_reference should return true" do
133
+ pending
134
+ end
135
+
136
+ it "#set_design_reference should return false" do
137
+ pending
138
+ end
139
+ end
140
+
141
+ context "construct_description" do
142
+ it "#construct_description should render a template" do
143
+ pending
144
+ end
145
+ end
6
146
  end
7
147
  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.13
4
+ version: 0.0.14
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-16 00:00:00.000000000 Z
12
+ date: 2012-09-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gdata_19