pivotal-to-trello 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +102 -0
- data/Dockerfile +24 -0
- data/Gemfile +5 -4
- data/README.markdown +11 -2
- data/Rakefile +10 -10
- data/VERSION +1 -1
- data/lib/pivotal-to-trello.rb +1 -1
- data/lib/pivotal_to_trello/core.rb +91 -83
- data/lib/pivotal_to_trello/pivotal_wrapper.rb +10 -11
- data/lib/pivotal_to_trello/trello_wrapper.rb +44 -25
- data/pivotal-to-trello.gemspec +22 -17
- data/spec/pivotal_to_trello/core_spec.rb +44 -44
- data/spec/pivotal_to_trello/pivotal_wrapper_spec.rb +12 -10
- data/spec/pivotal_to_trello/trello_wrapper_spec.rb +75 -53
- data/spec/spec_helper.rb +35 -34
- metadata +35 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b07f7cf563cfd39dd77fea8ddea116c13442c800
|
4
|
+
data.tar.gz: d1a9f8d00c58de04c1e46bdff752fd32d0c1f482
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe887375672d6a14d4c6ad9d534dd721f5ef1ee7c5d01702212ae05712eba40cbef054d9b3180fb5a2c42e543edc0ca09e9447d21dc3400410e041a1bf80e68e
|
7
|
+
data.tar.gz: 2795928fd620bf9243634b596bfd360d358a554bc15b8f522ba8ea46fc6887e985267b216e19dcdcf549609ef76376efbb25a453b480f8f93be8e44bce00d998
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# See example at https://github.com/bbatsov/rubocop/blob/master/config/default.yml
|
2
|
+
AllCops:
|
3
|
+
TargetRubyVersion: 2.2
|
4
|
+
Exclude:
|
5
|
+
- 'Gemfile'
|
6
|
+
- 'pivotal-to-trello.gemspec'
|
7
|
+
|
8
|
+
# Align the elements of a hash literal if they span more than one line.
|
9
|
+
AlignHash:
|
10
|
+
# Alignment of entries using hash rocket as separator. Valid values are:
|
11
|
+
#
|
12
|
+
# key - left alignment of keys
|
13
|
+
# 'a' => 2
|
14
|
+
# 'bb' => 3
|
15
|
+
# separator - alignment of hash rockets, keys are right aligned
|
16
|
+
# 'a' => 2
|
17
|
+
# 'bb' => 3
|
18
|
+
# table - left alignment of keys, hash rockets, and values
|
19
|
+
# 'a' => 2
|
20
|
+
# 'bb' => 3
|
21
|
+
EnforcedHashRocketStyle: table
|
22
|
+
# Alignment of entries using colon as separator. Valid values are:
|
23
|
+
#
|
24
|
+
# key - left alignment of keys
|
25
|
+
# a: 0
|
26
|
+
# bb: 1
|
27
|
+
# separator - alignment of colons, keys are right aligned
|
28
|
+
# a: 0
|
29
|
+
# bb: 1
|
30
|
+
# table - left alignment of keys and values
|
31
|
+
# a: 0
|
32
|
+
# bb: 1
|
33
|
+
EnforcedColonStyle: table
|
34
|
+
|
35
|
+
Documentation:
|
36
|
+
Enabled: false
|
37
|
+
|
38
|
+
EmptyLines:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
Layout/EmptyLinesAroundBlockBody:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
LineLength:
|
45
|
+
Max: 180
|
46
|
+
|
47
|
+
Metrics/AbcSize:
|
48
|
+
Enabled: true
|
49
|
+
Max: 40
|
50
|
+
|
51
|
+
Metrics/ClassLength:
|
52
|
+
Enabled: false
|
53
|
+
CountComments: false
|
54
|
+
|
55
|
+
Metrics/BlockLength:
|
56
|
+
Enabled: false
|
57
|
+
CountComments: false
|
58
|
+
|
59
|
+
Metrics/MethodLength:
|
60
|
+
Enabled: true
|
61
|
+
CountComments: false
|
62
|
+
Max: 25
|
63
|
+
|
64
|
+
ParameterLists:
|
65
|
+
Max: 7
|
66
|
+
CountKeywordArgs: true
|
67
|
+
|
68
|
+
SpaceInsideParens:
|
69
|
+
Enabled: false
|
70
|
+
|
71
|
+
SpaceBeforeFirstArg:
|
72
|
+
Enabled: false
|
73
|
+
|
74
|
+
Style/AndOr:
|
75
|
+
Enabled: false
|
76
|
+
|
77
|
+
Style/BlockComments:
|
78
|
+
Enabled: false
|
79
|
+
|
80
|
+
Style/BlockDelimiters:
|
81
|
+
Enabled: false
|
82
|
+
|
83
|
+
Style/ClassAndModuleChildren:
|
84
|
+
Enabled: true
|
85
|
+
EnforcedStyle: nested
|
86
|
+
|
87
|
+
Style/FrozenStringLiteralComment:
|
88
|
+
Enabled: false
|
89
|
+
|
90
|
+
Style/RedundantReturn:
|
91
|
+
Enabled: false
|
92
|
+
|
93
|
+
Style/TrailingCommaInArguments:
|
94
|
+
Enabled: true
|
95
|
+
EnforcedStyleForMultiline: comma
|
96
|
+
|
97
|
+
Style/TrailingCommaInLiteral:
|
98
|
+
Enabled: true
|
99
|
+
EnforcedStyleForMultiline: comma
|
100
|
+
|
101
|
+
Style/WordArray:
|
102
|
+
Enabled: false
|
data/Dockerfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
FROM ubuntu:14.04
|
2
|
+
|
3
|
+
MAINTAINER "Dave Perrett" https://github.com/Dockerfile
|
4
|
+
|
5
|
+
# Dependencies
|
6
|
+
RUN apt-get -y update &&\
|
7
|
+
apt-get install -y software-properties-common &&\
|
8
|
+
apt-add-repository ppa:brightbox/ruby-ng &&\
|
9
|
+
apt-get update -q
|
10
|
+
|
11
|
+
RUN apt-get install -y build-essential zlib1g-dev libxml2-dev \
|
12
|
+
ruby2.2 ruby2.2-dev &&\
|
13
|
+
gem install bundler --no-rdoc --no-ri
|
14
|
+
|
15
|
+
# Prepare
|
16
|
+
RUN mkdir /app
|
17
|
+
COPY . /app
|
18
|
+
|
19
|
+
# Install lean
|
20
|
+
RUN cd /app && bundle install --without development
|
21
|
+
|
22
|
+
# And run
|
23
|
+
WORKDIR /app
|
24
|
+
ENTRYPOINT ["bundle", "exec", "/app/bin/pivotal-to-trello"]
|
data/Gemfile
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
source 'http://rubygems.org'
|
2
2
|
|
3
|
-
gem 'highline', '
|
4
|
-
gem 'ruby-trello', '
|
5
|
-
gem 'pivotal-tracker', '
|
3
|
+
gem 'highline', '~> 1.7.8'
|
4
|
+
gem 'ruby-trello', '~> 2.0.0'
|
5
|
+
gem 'pivotal-tracker', '~> 0.5.13'
|
6
6
|
|
7
7
|
group :development do
|
8
8
|
gem 'rspec', '>= 2.14.1'
|
9
9
|
gem 'rdoc', '>= 4.1.1'
|
10
|
-
gem 'jeweler', '>= 2.
|
10
|
+
gem 'jeweler', '>= 2.3.7'
|
11
|
+
gem 'rubocop', '>= 0.49.1'
|
11
12
|
end
|
data/README.markdown
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
pivotal-to-trello [![Build Status](https://travis-ci.org/recurser/pivotal-to-trello.png?branch=master)](https://travis-ci.org/recurser/pivotal-to-trello)
|
2
2
|
=================
|
3
3
|
|
4
|
-
This
|
4
|
+
This repo provides a command for exporting a [Pivotal Tracker](https://www.pivotaltracker.com/) project to [Trello](https://trello.com/). The command is available as a gem or a docker container.
|
5
5
|
|
6
6
|
Getting started
|
7
7
|
---------------
|
@@ -10,6 +10,12 @@ Getting started
|
|
10
10
|
|
11
11
|
> gem install pivotal-to-trello
|
12
12
|
|
13
|
+
Or pull the container down using Docker:
|
14
|
+
|
15
|
+
> docker pull recurser/pivotal-to-trello
|
16
|
+
|
17
|
+
When using the docker container, substitute every occurance of `pivotal-to-tracker` with `sudo docker run -a -i recurser/pivotal-to-tracker`
|
18
|
+
|
13
19
|
2. Run the importer:
|
14
20
|
|
15
21
|
> pivotal-to-trello import --trello-key TRELLO_API_KEY --trello-token TRELLO_TOKEN --pivotal-token PIVOTAL_TOKEN
|
@@ -229,6 +235,9 @@ The Pivotal Tracker token can be found at the bottom of your [Pivotal profile pa
|
|
229
235
|
Change history
|
230
236
|
--------------
|
231
237
|
|
238
|
+
* **Version 0.2.0 (2017-08-10)** : Fix label creation, update gem dependencies, add checklist support (thanks @rikthevik!), add docker support (thanks @kennethkalmer!).
|
239
|
+
* **Version 0.1.2 (2014-01-13)** : Update version number in the gemspec.
|
240
|
+
* **Version 0.1.1 (2014-01-13)** : Specify gem dependencies.
|
232
241
|
* **Version 0.1.0 (2014-01-13)** : Initial version.
|
233
242
|
|
234
243
|
Bug Reports
|
@@ -257,4 +266,4 @@ Dave Perrett :: hello@daveperrett.com :: [@daveperrett](http://twitter.com/davep
|
|
257
266
|
Copyright
|
258
267
|
---------
|
259
268
|
|
260
|
-
Copyright (c)
|
269
|
+
Copyright (c) 2017 Dave Perrett. See [License](https://github.com/recurser/jquery-i18n/blob/master/LICENSE) for details.
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ begin
|
|
6
6
|
Bundler.setup(:default, :development)
|
7
7
|
rescue Bundler::BundlerError => e
|
8
8
|
$stderr.puts e.message
|
9
|
-
$stderr.puts
|
9
|
+
$stderr.puts 'Run `bundle install` to install missing gems'
|
10
10
|
exit e.status_code
|
11
11
|
end
|
12
12
|
require 'rake'
|
@@ -14,13 +14,13 @@ require 'rake'
|
|
14
14
|
require 'jeweler'
|
15
15
|
Jeweler::Tasks.new do |gem|
|
16
16
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
-
gem.name =
|
18
|
-
gem.license =
|
19
|
-
gem.homepage =
|
20
|
-
gem.summary = %
|
21
|
-
gem.description = %
|
22
|
-
gem.email =
|
23
|
-
gem.authors = [
|
17
|
+
gem.name = 'pivotal-to-trello'
|
18
|
+
gem.license = 'MIT'
|
19
|
+
gem.homepage = 'http://github.com/recurser/pivotal-to-trello'
|
20
|
+
gem.summary = %(Pivotal Tracker to Trello exporter)
|
21
|
+
gem.description = %(Pulls stories from Pivotal Tracker and imports them into Trello)
|
22
|
+
gem.email = 'hello@daveperrett.com'
|
23
|
+
gem.authors = ['Dave Perrett', 'Erik Frederiksen', 'Kenneth Kalmer']
|
24
24
|
# dependencies defined in Gemfile
|
25
25
|
end
|
26
26
|
Jeweler::RubygemsDotOrgTasks.new
|
@@ -36,11 +36,11 @@ RSpec::Core::RakeTask.new(:rcov) do |spec|
|
|
36
36
|
spec.rcov = true
|
37
37
|
end
|
38
38
|
|
39
|
-
task :
|
39
|
+
task default: :spec
|
40
40
|
|
41
41
|
require 'rdoc/task'
|
42
42
|
Rake::RDocTask.new do |rdoc|
|
43
|
-
version = File.exist?('VERSION') ? File.read('VERSION') :
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ''
|
44
44
|
|
45
45
|
rdoc.rdoc_dir = 'rdoc'
|
46
46
|
rdoc.title = "pivotal-to-trello #{version}"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/pivotal-to-trello.rb
CHANGED
@@ -4,113 +4,121 @@ require 'highline/import'
|
|
4
4
|
module PivotalToTrello
|
5
5
|
# The core entry point of the gem, which handles the import process.
|
6
6
|
class Core
|
7
|
-
|
8
7
|
# Constructor
|
9
8
|
def initialize(options = OpenStruct.new)
|
10
9
|
@options = options
|
11
10
|
end
|
12
11
|
|
13
|
-
#
|
14
|
-
# to the given output path.
|
12
|
+
# Imports a Pivotal project into Trello.
|
15
13
|
def import!
|
16
14
|
prompt_for_details
|
17
15
|
|
18
16
|
puts "\nBeginning import..."
|
19
17
|
pivotal.stories(options.pivotal_project_id).each do |story|
|
20
|
-
list_id =
|
21
|
-
|
22
|
-
if story.current_state == 'accepted'
|
23
|
-
list_id = options.accepted_list_id
|
24
|
-
elsif story.current_state == 'rejected'
|
25
|
-
list_id = options.rejected_list_id
|
26
|
-
elsif story.current_state == 'finished'
|
27
|
-
list_id = options.finished_list_id
|
28
|
-
elsif story.current_state == 'delivered'
|
29
|
-
list_id = options.delivered_list_id
|
30
|
-
elsif story.current_state == 'started'
|
31
|
-
list_id = options.current_list_id
|
32
|
-
elsif story.current_state == 'unscheduled'
|
33
|
-
list_id = options.icebox_list_id
|
34
|
-
elsif story.current_state == 'unstarted' && story.story_type == 'feature'
|
35
|
-
list_id = options.feature_list_id
|
36
|
-
elsif story.current_state == 'unstarted' && story.story_type == 'chore'
|
37
|
-
list_id = options.chore_list_id
|
38
|
-
elsif story.current_state == 'unstarted' && story.story_type == 'bug'
|
39
|
-
list_id = options.bug_list_id
|
40
|
-
elsif story.current_state == 'unstarted' && story.story_type == 'release'
|
41
|
-
list_id = options.release_list_id
|
42
|
-
else
|
43
|
-
puts "Ignoring story #{story.id} - type is '#{story.story_type}', state is '#{story.current_state}'"
|
44
|
-
end
|
45
|
-
|
46
|
-
if story.story_type == 'bug' && options.bug_label
|
47
|
-
label = options.bug_label
|
48
|
-
elsif story.story_type == 'feature' && options.feature_label
|
49
|
-
label = options.feature_label
|
50
|
-
elsif story.story_type == 'chore' && options.chore_label
|
51
|
-
label = options.chore_label
|
52
|
-
elsif story.story_type == 'release' && options.release_label
|
53
|
-
label = options.release_label
|
54
|
-
end
|
18
|
+
list_id = get_list_id(story, options)
|
19
|
+
next unless list_id
|
55
20
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
21
|
+
card = trello.create_card(list_id, story)
|
22
|
+
label_color = get_label_color(story, options)
|
23
|
+
trello.add_label(card, story.story_type, label_color) unless label_color.nil?
|
60
24
|
end
|
61
25
|
end
|
62
26
|
|
63
27
|
# Returns the options struct.
|
64
|
-
|
65
|
-
@options
|
66
|
-
end
|
28
|
+
attr_reader :options
|
67
29
|
|
68
30
|
private
|
69
31
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
32
|
+
# Returns the Trello list_id to import the given story into, based on the users input.
|
33
|
+
def get_list_id(story, options)
|
34
|
+
list_id = nil
|
35
|
+
|
36
|
+
if story.current_state == 'accepted'
|
37
|
+
list_id = options.accepted_list_id
|
38
|
+
elsif story.current_state == 'rejected'
|
39
|
+
list_id = options.rejected_list_id
|
40
|
+
elsif story.current_state == 'finished'
|
41
|
+
list_id = options.finished_list_id
|
42
|
+
elsif story.current_state == 'delivered'
|
43
|
+
list_id = options.delivered_list_id
|
44
|
+
elsif story.current_state == 'started'
|
45
|
+
list_id = options.current_list_id
|
46
|
+
elsif story.current_state == 'unscheduled'
|
47
|
+
list_id = options.icebox_list_id
|
48
|
+
elsif story.current_state == 'unstarted' && story.story_type == 'feature'
|
49
|
+
list_id = options.feature_list_id
|
50
|
+
elsif story.current_state == 'unstarted' && story.story_type == 'chore'
|
51
|
+
list_id = options.chore_list_id
|
52
|
+
elsif story.current_state == 'unstarted' && story.story_type == 'bug'
|
53
|
+
list_id = options.bug_list_id
|
54
|
+
elsif story.current_state == 'unstarted' && story.story_type == 'release'
|
55
|
+
list_id = options.release_list_id
|
56
|
+
else
|
57
|
+
puts "Ignoring story #{story.id} - type is '#{story.story_type}', state is '#{story.current_state}'"
|
88
58
|
end
|
89
59
|
|
90
|
-
|
91
|
-
|
92
|
-
say("\n#{question}")
|
93
|
-
choose do |menu|
|
94
|
-
menu.prompt = "Please select an option : "
|
95
|
-
|
96
|
-
choices.each do |key, value|
|
97
|
-
menu.choice value do
|
98
|
-
return key
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
60
|
+
list_id
|
61
|
+
end
|
102
62
|
|
63
|
+
# Returns the Trello label for the given story into, based on the users input.
|
64
|
+
def get_label_color(story, options)
|
65
|
+
label_color = nil
|
66
|
+
|
67
|
+
if story.story_type == 'bug' && options.bug_label
|
68
|
+
label_color = options.bug_label
|
69
|
+
elsif story.story_type == 'feature' && options.feature_label
|
70
|
+
label_color = options.feature_label
|
71
|
+
elsif story.story_type == 'chore' && options.chore_label
|
72
|
+
label_color = options.chore_label
|
73
|
+
elsif story.story_type == 'release' && options.release_label
|
74
|
+
label_color = options.release_label
|
103
75
|
end
|
104
76
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
77
|
+
label_color
|
78
|
+
end
|
79
|
+
|
80
|
+
# Prompts the user for details about the import/export.
|
81
|
+
def prompt_for_details
|
82
|
+
options.pivotal_project_id = prompt_selection('Which Pivotal project would you like to export?', pivotal.project_choices)
|
83
|
+
options.trello_board_id = prompt_selection('Which Trello board would you like to import into?', trello.board_choices)
|
84
|
+
options.icebox_list_id = prompt_selection("Which Trello list would you like to put 'icebox' stories into?", trello.list_choices(options.trello_board_id))
|
85
|
+
options.current_list_id = prompt_selection("Which Trello list would you like to put 'current' stories into?", trello.list_choices(options.trello_board_id))
|
86
|
+
options.finished_list_id = prompt_selection("Which Trello list would you like to put 'finished' stories into?", trello.list_choices(options.trello_board_id))
|
87
|
+
options.delivered_list_id = prompt_selection("Which Trello list would you like to put 'delivered' stories into?", trello.list_choices(options.trello_board_id))
|
88
|
+
options.accepted_list_id = prompt_selection("Which Trello list would you like to put 'accepted' stories into?", trello.list_choices(options.trello_board_id))
|
89
|
+
options.rejected_list_id = prompt_selection("Which Trello list would you like to put 'rejected' stories into?", trello.list_choices(options.trello_board_id))
|
90
|
+
options.bug_list_id = prompt_selection("Which Trello list would you like to put 'backlog' bugs into?", trello.list_choices(options.trello_board_id))
|
91
|
+
options.chore_list_id = prompt_selection("Which Trello list would you like to put 'backlog' chores into?", trello.list_choices(options.trello_board_id))
|
92
|
+
options.feature_list_id = prompt_selection("Which Trello list would you like to put 'backlog' features into?", trello.list_choices(options.trello_board_id))
|
93
|
+
options.release_list_id = prompt_selection("Which Trello list would you like to put 'backlog' releases into?", trello.list_choices(options.trello_board_id))
|
94
|
+
options.bug_label = prompt_selection('What color would you like to label bugs with?', trello.label_choices)
|
95
|
+
options.feature_label = prompt_selection('What color would you like to label features with?', trello.label_choices)
|
96
|
+
options.chore_label = prompt_selection('What color would you like to label chores with?', trello.label_choices)
|
97
|
+
options.release_label = prompt_selection('What color would you like to label releases with?', trello.label_choices)
|
98
|
+
end
|
109
99
|
|
110
|
-
|
111
|
-
|
112
|
-
|
100
|
+
# Prompts the user to select an option from the given list of choices.
|
101
|
+
def prompt_selection(question, choices)
|
102
|
+
say("\n#{question}")
|
103
|
+
choose do |menu|
|
104
|
+
menu.prompt = 'Please select an option : '
|
105
|
+
|
106
|
+
choices.each do |key, value|
|
107
|
+
menu.choice value do
|
108
|
+
return key
|
109
|
+
end
|
110
|
+
end
|
113
111
|
end
|
112
|
+
end
|
114
113
|
|
114
|
+
# Returns an instance of the pivotal wrapper.
|
115
|
+
def pivotal
|
116
|
+
@pivotal ||= PivotalToTrello::PivotalWrapper.new(options.pivotal_token)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns an instance of the trello wrapper.
|
120
|
+
def trello
|
121
|
+
@trello ||= PivotalToTrello::TrelloWrapper.new(options.trello_key, options.trello_token)
|
122
|
+
end
|
115
123
|
end
|
116
|
-
end
|
124
|
+
end
|