git-whistles 1.1.3 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +32 -15
- data/README.md +27 -0
- data/bin/git-youtrack-branch +20 -0
- data/git-whistles.gemspec +3 -0
- data/lib/git-whistles/version.rb +1 -1
- data/lib/git-whistles/youtrack/api.rb +79 -0
- data/lib/git-whistles/youtrack/branch.rb +78 -0
- data/lib/git-whistles/youtrack/ticket.rb +60 -0
- data/libexec/git-merge-po.sh +1 -1
- data/spec/fixtures/vcr/get_ticket_auth_failure.yml +77 -0
- data/spec/fixtures/vcr/get_ticket_not_found.yml +81 -0
- data/spec/fixtures/vcr/get_ticket_successfull.yml +184 -0
- data/spec/lib/git-whistles/youtrack/api_spec.rb +108 -0
- data/spec/lib/git-whistles/youtrack/branch_spec.rb +53 -0
- data/spec/spec_helper.rb +2 -82
- data/spec/support/vcr_helper.rb +8 -0
- metadata +62 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b659e30382e1005b596ed3571da52157325a2f4a
|
4
|
+
data.tar.gz: 3951abb1a603b4331cf63303d64676d434af2a4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 425ad5de6807b2e74cff7fc9d1b654311f6a432aa3fefe80620b768ab31d6c088a449702e9406afe4cd53d550cc11ffd0bec279b62cb8a8bbb7d72f039b932e1
|
7
|
+
data.tar.gz: e97c608e01e976ba08dbca45475e9aa92e7bb73c23c5fb3c8be9ba23a469147cbbfbb33934c224003d097dbc59a7db45ecf2cbf1ff2c52428301a98a883cdbed
|
data/Gemfile.lock
CHANGED
@@ -1,42 +1,50 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
git-whistles (1.
|
4
|
+
git-whistles (1.2.0)
|
5
5
|
jira-ruby (~> 1.0.0)
|
6
6
|
pivotal-tracker (~> 0.5.6)
|
7
7
|
term-ansicolor
|
8
|
+
youtrack (~> 0.0.11)
|
8
9
|
|
9
10
|
GEM
|
10
11
|
remote: https://rubygems.org/
|
11
12
|
specs:
|
12
|
-
activesupport (4.2.
|
13
|
+
activesupport (4.2.7.1)
|
13
14
|
i18n (~> 0.7)
|
14
15
|
json (~> 1.7, >= 1.7.7)
|
15
16
|
minitest (~> 5.1)
|
16
17
|
thread_safe (~> 0.3, >= 0.3.4)
|
17
18
|
tzinfo (~> 1.1)
|
19
|
+
addressable (2.4.0)
|
18
20
|
builder (3.2.2)
|
19
21
|
coderay (1.1.0)
|
20
22
|
crack (0.4.3)
|
21
23
|
safe_yaml (~> 1.0.0)
|
22
24
|
diff-lcs (1.2.5)
|
23
|
-
domain_name (0.5.
|
25
|
+
domain_name (0.5.20161021)
|
24
26
|
unf (>= 0.0.5, < 1.0.0)
|
25
|
-
|
27
|
+
hashdiff (0.3.0)
|
28
|
+
http-cookie (1.0.3)
|
26
29
|
domain_name (~> 0.5)
|
30
|
+
httparty (0.14.0)
|
31
|
+
multi_xml (>= 0.5.2)
|
27
32
|
i18n (0.7.0)
|
28
33
|
jira-ruby (1.0.0)
|
29
34
|
activesupport (~> 4.2, >= 4.2.0)
|
30
35
|
oauth (~> 0.5, >= 0.5.0)
|
31
36
|
json (1.8.3)
|
32
37
|
method_source (0.8.2)
|
33
|
-
mime-types (
|
38
|
+
mime-types (3.1)
|
39
|
+
mime-types-data (~> 3.2015)
|
40
|
+
mime-types-data (3.2016.0521)
|
34
41
|
mini_portile2 (2.1.0)
|
35
|
-
minitest (5.9.
|
42
|
+
minitest (5.9.1)
|
43
|
+
multi_xml (0.5.5)
|
44
|
+
multipart-post (2.0.0)
|
36
45
|
netrc (0.11.0)
|
37
|
-
nokogiri (1.6.8)
|
46
|
+
nokogiri (1.6.8.1)
|
38
47
|
mini_portile2 (~> 2.1.0)
|
39
|
-
pkg-config (~> 1.1.7)
|
40
48
|
nokogiri-happymapper (0.5.9)
|
41
49
|
nokogiri (~> 1.5)
|
42
50
|
oauth (0.5.1)
|
@@ -46,7 +54,6 @@ GEM
|
|
46
54
|
nokogiri (>= 1.5.5)
|
47
55
|
nokogiri-happymapper (>= 0.5.4)
|
48
56
|
rest-client (>= 1.8.0)
|
49
|
-
pkg-config (1.1.7)
|
50
57
|
pry (0.10.1)
|
51
58
|
coderay (~> 1.1.0)
|
52
59
|
method_source (~> 0.8.1)
|
@@ -54,10 +61,10 @@ GEM
|
|
54
61
|
pry-nav (0.2.4)
|
55
62
|
pry (>= 0.9.10, < 0.11.0)
|
56
63
|
rake (10.4.2)
|
57
|
-
rest-client (
|
64
|
+
rest-client (2.0.0)
|
58
65
|
http-cookie (>= 1.0.2, < 2.0)
|
59
|
-
mime-types (>= 1.16, <
|
60
|
-
netrc (~> 0.
|
66
|
+
mime-types (>= 1.16, < 4.0)
|
67
|
+
netrc (~> 0.8)
|
61
68
|
rspec (3.2.0)
|
62
69
|
rspec-core (~> 3.2.0)
|
63
70
|
rspec-expectations (~> 3.2.0)
|
@@ -73,15 +80,23 @@ GEM
|
|
73
80
|
rspec-support (3.2.2)
|
74
81
|
safe_yaml (1.0.4)
|
75
82
|
slop (3.6.0)
|
76
|
-
term-ansicolor (1.
|
83
|
+
term-ansicolor (1.4.0)
|
77
84
|
tins (~> 1.0)
|
78
85
|
thread_safe (0.3.5)
|
79
|
-
tins (1.
|
86
|
+
tins (1.12.0)
|
80
87
|
tzinfo (1.2.2)
|
81
88
|
thread_safe (~> 0.1)
|
82
89
|
unf (0.1.4)
|
83
90
|
unf_ext
|
84
91
|
unf_ext (0.0.7.2)
|
92
|
+
vcr (3.0.3)
|
93
|
+
webmock (2.1.0)
|
94
|
+
addressable (>= 2.3.6)
|
95
|
+
crack (>= 0.3.2)
|
96
|
+
hashdiff
|
97
|
+
youtrack (0.0.11)
|
98
|
+
httparty
|
99
|
+
multipart-post
|
85
100
|
|
86
101
|
PLATFORMS
|
87
102
|
ruby
|
@@ -93,6 +108,8 @@ DEPENDENCIES
|
|
93
108
|
pry-nav
|
94
109
|
rake
|
95
110
|
rspec
|
111
|
+
vcr
|
112
|
+
webmock
|
96
113
|
|
97
114
|
BUNDLED WITH
|
98
|
-
1.
|
115
|
+
1.13.1
|
data/README.md
CHANGED
@@ -37,6 +37,8 @@ Install with:
|
|
37
37
|
|
38
38
|
`git stash-and-checkout [branch]` - Stash and checkout another branch.
|
39
39
|
|
40
|
+
`git youtrack-branch <ticket-id>` - Creates a branch name suggestion from the specified Youtrack ticket ID.
|
41
|
+
|
40
42
|
### More details on some of the commands
|
41
43
|
|
42
44
|
#### merge-po
|
@@ -59,6 +61,21 @@ Add this to .gitattributes:
|
|
59
61
|
|
60
62
|
*.po merge=pofile
|
61
63
|
*.pot merge=pofile
|
64
|
+
|
65
|
+
Or, if you want to make this setting global:
|
66
|
+
|
67
|
+
Create a user global file ~/.gitattributes and fill it with:
|
68
|
+
|
69
|
+
*.po merge=pofile
|
70
|
+
*.pot merge=pofile
|
71
|
+
|
72
|
+
Add this to your user global ~/.gitconfig:
|
73
|
+
|
74
|
+
[core]
|
75
|
+
attributesfile = ~/.gitattributes
|
76
|
+
[merge "pofile"]
|
77
|
+
name = Gettext merge driver
|
78
|
+
driver = git merge-po %O %A %B
|
62
79
|
|
63
80
|
### JIRA
|
64
81
|
|
@@ -80,6 +97,16 @@ the Pivotal Tracker UI. The token can then be set locally via the following comm
|
|
80
97
|
$ git config [--global] pivotal-tracker.token <token>
|
81
98
|
```
|
82
99
|
|
100
|
+
### Youtrack
|
101
|
+
|
102
|
+
All Youtrack commands require a Youtrack username, password and url. Please use the following commands to set it up:
|
103
|
+
|
104
|
+
```
|
105
|
+
$ git config [--global] youtrack.username <username>
|
106
|
+
$ git config [--global] youtrack.password <password>
|
107
|
+
$ git config [--global] youtrack.url <https://your_youtrack_url.com>
|
108
|
+
```
|
109
|
+
|
83
110
|
### License
|
84
111
|
|
85
112
|
Released on the MIT license terms.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# git-youtrack-branch
|
5
|
+
#
|
6
|
+
# Suggest a branch name from the given YouTrack ticket ID
|
7
|
+
#
|
8
|
+
# Assumes the branches are named as:
|
9
|
+
# <team>/<branch-title>-<story-id>
|
10
|
+
#
|
11
|
+
require 'rubygems'
|
12
|
+
require 'optparse'
|
13
|
+
require 'youtrack'
|
14
|
+
require 'readline'
|
15
|
+
require 'term/ansicolor'
|
16
|
+
require 'git-whistles/app'
|
17
|
+
require 'git-whistles/youtrack/branch'
|
18
|
+
|
19
|
+
|
20
|
+
Git::Whistles::Youtrack::Branch.run!
|
data/git-whistles.gemspec
CHANGED
@@ -20,10 +20,13 @@ Gem::Specification.new do |gem|
|
|
20
20
|
gem.add_development_dependency "pry"
|
21
21
|
gem.add_development_dependency "pry-nav"
|
22
22
|
gem.add_development_dependency "rspec"
|
23
|
+
gem.add_development_dependency "webmock"
|
24
|
+
gem.add_development_dependency "vcr"
|
23
25
|
|
24
26
|
gem.add_dependency "pivotal-tracker", "~> 0.5.6"
|
25
27
|
gem.add_dependency "term-ansicolor"
|
26
28
|
gem.add_dependency "jira-ruby", "~> 1.0.0"
|
29
|
+
gem.add_dependency "youtrack", "~> 0.0.11"
|
27
30
|
|
28
31
|
gem.files = `git ls-files`.split($\)
|
29
32
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
data/lib/git-whistles/version.rb
CHANGED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'youtrack'
|
2
|
+
require_relative 'ticket'
|
3
|
+
require 'term/ansicolor'
|
4
|
+
|
5
|
+
module Git::Whistles
|
6
|
+
module Youtrack
|
7
|
+
class Api
|
8
|
+
def find_ticket(id)
|
9
|
+
ticket_hash = find_issue(id)
|
10
|
+
Ticket.build_from_remote(ticket_hash)
|
11
|
+
end
|
12
|
+
|
13
|
+
def username
|
14
|
+
username = `git config youtrack.username`.strip
|
15
|
+
|
16
|
+
if username.empty?
|
17
|
+
puts Term::ANSIColor.yellow %Q{
|
18
|
+
Can't find Youtrack username!
|
19
|
+
Please set it with:
|
20
|
+
$ git config [--global] youtrack.username <username>
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
username
|
25
|
+
end
|
26
|
+
|
27
|
+
def password
|
28
|
+
password = `git config youtrack.password`.strip
|
29
|
+
|
30
|
+
if password.empty?
|
31
|
+
puts Term::ANSIColor.yellow %Q{
|
32
|
+
Can't find Youtrack password!
|
33
|
+
Please set it with:
|
34
|
+
$ git config [--global] youtrack.password <password>
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
password
|
39
|
+
end
|
40
|
+
|
41
|
+
def url
|
42
|
+
url = `git config youtrack.url`.strip
|
43
|
+
|
44
|
+
if url.empty?
|
45
|
+
puts Term::ANSIColor.yellow %Q{
|
46
|
+
Can't find Youtrack URL!
|
47
|
+
Please set it with:
|
48
|
+
$ git config [--global] youtrack.url <https://mydomain.youtrack.net>
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
url
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def issues
|
58
|
+
@issues ||= client.issues
|
59
|
+
end
|
60
|
+
|
61
|
+
def client
|
62
|
+
@client ||= ::Youtrack::Client.new do |c|
|
63
|
+
c.url = url
|
64
|
+
c.login = username
|
65
|
+
c.password = password
|
66
|
+
end
|
67
|
+
|
68
|
+
@client.connect! unless @client.connected?
|
69
|
+
@client
|
70
|
+
end
|
71
|
+
|
72
|
+
def find_issue id
|
73
|
+
issues.find(id)
|
74
|
+
rescue
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative '../app'
|
2
|
+
require_relative '../youtrack/api'
|
3
|
+
require_relative '../youtrack/ticket'
|
4
|
+
|
5
|
+
module Git::Whistles
|
6
|
+
module Youtrack
|
7
|
+
class Branch < Git::Whistles::App
|
8
|
+
|
9
|
+
def initialize(current_dir: ENV['PWD'])
|
10
|
+
@current_dir = current_dir
|
11
|
+
super()
|
12
|
+
end
|
13
|
+
|
14
|
+
def main(args)
|
15
|
+
super
|
16
|
+
|
17
|
+
parse_args!(args)
|
18
|
+
if args.count < 1
|
19
|
+
puts Term::ANSIColor.yellow usage
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
|
23
|
+
ticket = get_ticket_from args[0]
|
24
|
+
if ticket.nil?
|
25
|
+
die "Could not find ticket #{args[0]}"
|
26
|
+
return false
|
27
|
+
end
|
28
|
+
|
29
|
+
suggested_branch_name = suggested_branch_name_from(ticket)
|
30
|
+
print_suggested_branch suggested_branch_name
|
31
|
+
|
32
|
+
user_branch_name = read_user_answer
|
33
|
+
show_and_exit "Cancelled by user" if user_branch_name.nil?
|
34
|
+
|
35
|
+
final_branch_name = user_branch_name.empty? ? suggested_branch_name : user_branch_name
|
36
|
+
create_branch final_branch_name
|
37
|
+
|
38
|
+
puts Term::ANSIColor.green 'Created branch'
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def usage
|
45
|
+
'Usage: git youtrack-branch YOUTRACK_STORY_ID'
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_ticket_from ticket_id
|
49
|
+
youtrack_client.find_ticket ticket_id
|
50
|
+
end
|
51
|
+
|
52
|
+
def youtrack_client
|
53
|
+
@youtrack_client ||= Git::Whistles::Youtrack::Api.new
|
54
|
+
end
|
55
|
+
|
56
|
+
def suggested_branch_name_from ticket
|
57
|
+
"#{ticket.project}/#{ticket.title}-#{ticket.id}".
|
58
|
+
downcase.
|
59
|
+
gsub(/[^\w\d\/]/, '-').gsub!(/-+/, '-')
|
60
|
+
end
|
61
|
+
|
62
|
+
def print_suggested_branch branch_name
|
63
|
+
puts 'The suggested branch name is: ' << Term::ANSIColor.yellow(branch_name)
|
64
|
+
puts ' Press ENTER if you agree'
|
65
|
+
puts ' or Write any other name and press ENTER'
|
66
|
+
puts ' or Press CTRL-D to cancel'
|
67
|
+
end
|
68
|
+
|
69
|
+
def read_user_answer
|
70
|
+
Readline.readline ' > ', false
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_branch branch_name
|
74
|
+
`cd #{@current_dir} && git checkout -b #{branch_name}`
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Git::Whistles
|
2
|
+
module Youtrack
|
3
|
+
class Ticket
|
4
|
+
class << self
|
5
|
+
def build_from_remote(ticket_hash)
|
6
|
+
return nil if ticket_hash.nil?
|
7
|
+
return nil if issue_not_found? ticket_hash
|
8
|
+
|
9
|
+
self.new.tap do |ticket|
|
10
|
+
ticket.title = title_from ticket_hash
|
11
|
+
ticket.id = id_from ticket_hash
|
12
|
+
ticket.project = project_from ticket_hash
|
13
|
+
ticket.description = description_from ticket_hash
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def title_from(ticket_hash)
|
18
|
+
ticket_hash
|
19
|
+
.dig('issue', 'field')
|
20
|
+
.select { |f| f['name'] == 'summary' }
|
21
|
+
.first.dig('value')
|
22
|
+
end
|
23
|
+
|
24
|
+
def id_from(ticket_hash)
|
25
|
+
ticket_hash
|
26
|
+
.dig('issue', 'field')
|
27
|
+
.select { |f| f['name'] == 'numberInProject' }
|
28
|
+
.first.dig('value').to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
def project_from(ticket_hash)
|
32
|
+
ticket_hash
|
33
|
+
.dig('issue', 'field')
|
34
|
+
.select { |f| f['name'] == 'projectShortName' }
|
35
|
+
.first.dig('value')
|
36
|
+
end
|
37
|
+
|
38
|
+
def description_from(ticket_hash)
|
39
|
+
ticket_hash
|
40
|
+
.dig('issue', 'field')
|
41
|
+
.select { |f| f['name'] == 'description' }
|
42
|
+
.first.dig('value')
|
43
|
+
end
|
44
|
+
|
45
|
+
def issue_not_found?(ticket_hash)
|
46
|
+
if ticket_hash["error"]
|
47
|
+
true
|
48
|
+
else
|
49
|
+
false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_accessor :title
|
55
|
+
attr_accessor :id
|
56
|
+
attr_accessor :project
|
57
|
+
attr_accessor :description
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/libexec/git-merge-po.sh
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: http://youtrack.com/rest/user/login
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: login=some_username&password=some_password
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 404
|
19
|
+
message: Not Found
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- nginx
|
23
|
+
Date:
|
24
|
+
- Mon, 26 Sep 2016 16:48:12 GMT
|
25
|
+
Content-Type:
|
26
|
+
- text/html
|
27
|
+
Transfer-Encoding:
|
28
|
+
- chunked
|
29
|
+
Connection:
|
30
|
+
- keep-alive
|
31
|
+
Vary:
|
32
|
+
- Accept-Encoding
|
33
|
+
Last-Modified:
|
34
|
+
- Mon, 06 Oct 2014 10:16:51 GMT
|
35
|
+
Etag:
|
36
|
+
- W/"1745269-3fe-504be61a22cc6"
|
37
|
+
X-Powered-By:
|
38
|
+
- PleskLin
|
39
|
+
body:
|
40
|
+
encoding: ASCII-8BIT
|
41
|
+
string: |
|
42
|
+
<HTML>
|
43
|
+
<HEAD>
|
44
|
+
<TITLE>404 Not Found</TITLE>
|
45
|
+
<BASE href="/error_docs/"><!--[if lte IE 6]></BASE><![endif]-->
|
46
|
+
</HEAD>
|
47
|
+
<BODY>
|
48
|
+
<H1>Not Found</H1>
|
49
|
+
The requested document was not found on this server.
|
50
|
+
<P>
|
51
|
+
<HR>
|
52
|
+
<ADDRESS>
|
53
|
+
Web Server at youtrack.com
|
54
|
+
</ADDRESS>
|
55
|
+
</BODY>
|
56
|
+
</HTML>
|
57
|
+
|
58
|
+
<!--
|
59
|
+
- Unfortunately, Microsoft has added a clever new
|
60
|
+
- "feature" to Internet Explorer. If the text of
|
61
|
+
- an error's message is "too small", specifically
|
62
|
+
- less than 512 bytes, Internet Explorer returns
|
63
|
+
- its own error message. You can turn that off,
|
64
|
+
- but it's pretty tricky to find switch called
|
65
|
+
- "smart error messages". That means, of course,
|
66
|
+
- that short error messages are censored by default.
|
67
|
+
- IIS always returns error messages that are long
|
68
|
+
- enough to make Internet Explorer happy. The
|
69
|
+
- workaround is pretty simple: pad the error
|
70
|
+
- message with a big comment like this to push it
|
71
|
+
- over the five hundred and twelve bytes minimum.
|
72
|
+
- Of course, that's exactly what you're reading
|
73
|
+
- right now.
|
74
|
+
-->
|
75
|
+
http_version:
|
76
|
+
recorded_at: Mon, 26 Sep 2016 16:48:55 GMT
|
77
|
+
recorded_with: VCR 3.0.3
|
@@ -0,0 +1,81 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: http://youtrack.com/rest/user/login
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: login=some_username&password=some_password
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- nginx/1.9.5
|
23
|
+
Date:
|
24
|
+
- Mon, 26 Sep 2016 16:44:24 GMT
|
25
|
+
Content-Type:
|
26
|
+
- application/xml;charset=UTF-8
|
27
|
+
Content-Length:
|
28
|
+
- '17'
|
29
|
+
Connection:
|
30
|
+
- keep-alive
|
31
|
+
Set-Cookie:
|
32
|
+
- YTSESSIONID=1mcbb8c57vxc5zoaxfanbijc3;Path=/;HttpOnly
|
33
|
+
- jetbrains.charisma.main.security.PRINCIPAL=ZGM3YzVjNzc4YjkwMWQ2ZmI1OTgwOWQwYzI4MTQ1OGEyNzVhNDFlMWQyOTEwNTNiMzRkZjQ4YmE2ODRiMmUyYjphbGZyZWRvLm1vdHRh;Path=/;Expires=Tue,
|
34
|
+
26-Sep-2017 16:44:24 GMT
|
35
|
+
Expires:
|
36
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
37
|
+
Access-Control-Expose-Headers:
|
38
|
+
- Location
|
39
|
+
Cache-Control:
|
40
|
+
- no-cache, no-store, no-transform, must-revalidate
|
41
|
+
body:
|
42
|
+
encoding: UTF-8
|
43
|
+
string: "<login>ok</login>"
|
44
|
+
http_version:
|
45
|
+
recorded_at: Mon, 26 Sep 2016 16:43:51 GMT
|
46
|
+
- request:
|
47
|
+
method: get
|
48
|
+
uri: http://youtrack.com/rest/issue/non-existent
|
49
|
+
body:
|
50
|
+
encoding: US-ASCII
|
51
|
+
string: ''
|
52
|
+
headers:
|
53
|
+
Cookie:
|
54
|
+
- YTSESSIONID=1mcbb8c57vxc5zoaxfanbijc3;Path=/;HttpOnly, jetbrains.charisma.main.security.PRINCIPAL=ZGM3YzVjNzc4YjkwMWQ2ZmI1OTgwOWQwYzI4MTQ1OGEyNzVhNDFlMWQyOTEwNTNiMzRkZjQ4YmE2ODRiMmUyYjphbGZyZWRvLm1vdHRh;Path=/;Expires=Tue,
|
55
|
+
26-Sep-2017 16:44:24 GMT
|
56
|
+
response:
|
57
|
+
status:
|
58
|
+
code: 404
|
59
|
+
message: Not Found
|
60
|
+
headers:
|
61
|
+
Server:
|
62
|
+
- nginx/1.9.5
|
63
|
+
Date:
|
64
|
+
- Mon, 26 Sep 2016 16:44:24 GMT
|
65
|
+
Content-Type:
|
66
|
+
- application/xml;charset=UTF-8
|
67
|
+
Content-Length:
|
68
|
+
- '86'
|
69
|
+
Connection:
|
70
|
+
- keep-alive
|
71
|
+
Access-Control-Expose-Headers:
|
72
|
+
- Location
|
73
|
+
Cache-Control:
|
74
|
+
- no-cache, no-store, no-transform, must-revalidate
|
75
|
+
body:
|
76
|
+
encoding: UTF-8
|
77
|
+
string: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><error>Issue
|
78
|
+
not found.</error>
|
79
|
+
http_version:
|
80
|
+
recorded_at: Mon, 26 Sep 2016 16:43:51 GMT
|
81
|
+
recorded_with: VCR 3.0.3
|
@@ -0,0 +1,184 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: http://youtrack.com/rest/user/login
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: login=alfredo.motta&password=some_password
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- nginx/1.9.5
|
23
|
+
Date:
|
24
|
+
- Thu, 08 Sep 2016 18:20:27 GMT
|
25
|
+
Content-Type:
|
26
|
+
- application/xml;charset=UTF-8
|
27
|
+
Content-Length:
|
28
|
+
- '17'
|
29
|
+
Connection:
|
30
|
+
- keep-alive
|
31
|
+
Set-Cookie:
|
32
|
+
- YTSESSIONID=24bw6qyuglya1pq9p2oh0qtnj;Path=/;HttpOnly
|
33
|
+
- jetbrains.charisma.main.security.PRINCIPAL=ZGM3YzVjNzc4YjkwMWQ2ZmI1OTgwOWQwYzI4MTQ1OGEyNzVhNDFlMWQyOTEwNTNiMzRkZjQ4YmE2ODRiMmUyYjphbGZyZWRvLm1vdHRh;Path=/;Expires=Fri,
|
34
|
+
08-Sep-2017 18:20:27 GMT
|
35
|
+
Expires:
|
36
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
37
|
+
Cache-Control:
|
38
|
+
- no-cache, no-store, no-transform, must-revalidate
|
39
|
+
Access-Control-Expose-Headers:
|
40
|
+
- Location
|
41
|
+
body:
|
42
|
+
encoding: UTF-8
|
43
|
+
string: "<login>ok</login>"
|
44
|
+
http_version:
|
45
|
+
recorded_at: Thu, 08 Sep 2016 18:19:06 GMT
|
46
|
+
- request:
|
47
|
+
method: get
|
48
|
+
uri: http://youtrack.com/rest/issue/PIO-338
|
49
|
+
body:
|
50
|
+
encoding: US-ASCII
|
51
|
+
string: ''
|
52
|
+
headers:
|
53
|
+
Cookie:
|
54
|
+
- YTSESSIONID=24bw6qyuglya1pq9p2oh0qtnj;Path=/;HttpOnly, jetbrains.charisma.main.security.PRINCIPAL=ZGM3YzVjNzc4YjkwMWQ2ZmI1OTgwOWQwYzI4MTQ1OGEyNzVhNDFlMWQyOTEwNTNiMzRkZjQ4YmE2ODRiMmUyYjphbGZyZWRvLm1vdHRh;Path=/;Expires=Fri,
|
55
|
+
08-Sep-2017 18:20:27 GMT
|
56
|
+
response:
|
57
|
+
status:
|
58
|
+
code: 200
|
59
|
+
message: OK
|
60
|
+
headers:
|
61
|
+
Server:
|
62
|
+
- nginx/1.9.5
|
63
|
+
Date:
|
64
|
+
- Thu, 08 Sep 2016 18:20:27 GMT
|
65
|
+
Content-Type:
|
66
|
+
- application/xml;charset=UTF-8
|
67
|
+
Transfer-Encoding:
|
68
|
+
- chunked
|
69
|
+
Connection:
|
70
|
+
- keep-alive
|
71
|
+
Cache-Control:
|
72
|
+
- no-cache, no-store, no-transform, must-revalidate
|
73
|
+
Access-Control-Expose-Headers:
|
74
|
+
- Location
|
75
|
+
body:
|
76
|
+
encoding: UTF-8
|
77
|
+
string: "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><issue
|
78
|
+
id=\"PIO-338\" entityId=\"75-11159\"><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
79
|
+
xsi:type=\"SingleField\" name=\"projectShortName\"><value>PIO</value></field><field
|
80
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"SingleField\"
|
81
|
+
name=\"numberInProject\"><value>338</value></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
82
|
+
xsi:type=\"SingleField\" name=\"summary\"><value>Header styling changes</value></field><field
|
83
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"SingleField\"
|
84
|
+
name=\"description\"><value>==Why==\n\nCurrent header is taking a lot of space
|
85
|
+
(white space on top of page) which is being wasted/not used for any purpose.
|
86
|
+
\nWe want to push the form to the top, so it stays over the fold as much as
|
87
|
+
possible.\n\n==What==\n\nApply styling changes as seen on the design.\n. white
|
88
|
+
space disappears\n. \"retrieve application\" moves to the top - font color:white;
|
89
|
+
\ hover text-style:underline;\n. zopa logo sits on top of the blue image.\n.
|
90
|
+
font-weight on progress steps: 600;\n. make sure form is left aligned together
|
91
|
+
with car graphic and step 1 circle.\n. logos attached @1x,@2x\n\n***make sure
|
92
|
+
by changing link style on top right, it doesnt change bottom one. We should
|
93
|
+
have 2 link styles:\n1. white text on dark backgrounds\n2. green text on light
|
94
|
+
backgrounds</value></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
95
|
+
xsi:type=\"SingleField\" name=\"created\"><value>1470145056062</value></field><field
|
96
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"SingleField\"
|
97
|
+
name=\"updated\"><value>1473345934647</value></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
98
|
+
xsi:type=\"SingleField\" name=\"updaterName\"><value>Orrin_Ward</value></field><field
|
99
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"SingleField\"
|
100
|
+
name=\"updaterFullName\"><value>Orrin Ward</value></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
101
|
+
xsi:type=\"SingleField\" name=\"reporterName\"><value>natalia.alvarez</value></field><field
|
102
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"SingleField\"
|
103
|
+
name=\"reporterFullName\"><value>Natalia Alvarez</value></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
104
|
+
xsi:type=\"SingleField\" name=\"commentsCount\"><value>12</value></field><field
|
105
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"SingleField\"
|
106
|
+
name=\"votes\"><value>0</value></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
107
|
+
xsi:type=\"LinkField\" name=\"links\"><value type=\"Subtask\" role=\"subtask
|
108
|
+
of\">PIO-287</value></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
109
|
+
xsi:type=\"CustomFieldValue\" name=\"Type\"><value>Functional Story</value><valueId>Functional
|
110
|
+
Story</valueId><color><bg>#0066cc</bg><fg>white</fg></color></field><field
|
111
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"MultiUserField\"
|
112
|
+
name=\"Owner\"><value fullName=\"Natalia Alvarez\">natalia.alvarez</value></field><field
|
113
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CustomFieldValue\"
|
114
|
+
name=\"State\"><value>Acceptance</value><valueId>Acceptance</valueId><color><bg>#d9ffc8</bg><fg>#000</fg></color></field><field
|
115
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CustomFieldValue\"
|
116
|
+
name=\"Status\"><value>Ready</value><valueId>Ready</valueId><color><bg>#0066cc</bg><fg>white</fg></color></field><field
|
117
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CustomFieldValue\"
|
118
|
+
name=\"Size\"><value>2</value><valueId>2</valueId></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
119
|
+
xsi:type=\"MultiUserField\" name=\"Assignee\"><value fullName=\"Greg Baker\">greg.baker</value><value
|
120
|
+
fullName=\"Natalia Alvarez\">natalia.alvarez</value></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
121
|
+
xsi:type=\"CustomFieldValue\" name=\"Sprint\"><value>Sprint Sixxx</value><value>Sprint
|
122
|
+
Seven</value><value>Sprint Eight</value><valueId>Sprint Sixxx</valueId><valueId>Sprint
|
123
|
+
Seven</valueId><valueId>Sprint Eight</valueId></field><field xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
|
124
|
+
xsi:type=\"CustomFieldValue\" name=\"Feature Flag\"><value>No</value><valueId>No</valueId></field><field
|
125
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CustomFieldValue\"
|
126
|
+
name=\"Squad\"><value>Pioneers</value><valueId>Pioneers</valueId></field><field
|
127
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CustomFieldValue\"
|
128
|
+
name=\"Estimation\"><value>240</value><valueId>4h</valueId></field><field
|
129
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CustomFieldValue\"
|
130
|
+
name=\"CombinedBoard\"><value>SharedView</value><valueId>SharedView</valueId></field><field
|
131
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CustomFieldValue\"
|
132
|
+
name=\"Infosec Signoff\"><value>Not required</value><valueId>Not required</valueId><color><bg>#339933</bg><fg>white</fg></color></field><field
|
133
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CustomFieldValue\"
|
134
|
+
name=\"Compliance Signoff\"><value>Not required</value><valueId>Not required</valueId><color><bg>#339933</bg><fg>white</fg></color></field><field
|
135
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CustomFieldValue\"
|
136
|
+
name=\"Risk Signoff\"><value>Not required</value><valueId>Not required</valueId><color><bg>#339933</bg><fg>white</fg></color></field><field
|
137
|
+
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"AttachmentField\"
|
138
|
+
name=\"attachments\"><value id=\"89-3241\" url=\"http://youtrack.zopian.ad.zopa.com/_persistent/header%20changes%402x.png?file=89-3241&v=0&c=true\">header
|
139
|
+
changes@2x.png</value><value id=\"89-3243\" url=\"http://youtrack.zopian.ad.zopa.com/_persistent/ZopaLogo.png?file=89-3243&v=0&c=true\">ZopaLogo.png</value><value
|
140
|
+
id=\"89-3244\" url=\"http://youtrack.zopian.ad.zopa.com/_persistent/ZopaLogo%402x.png?file=89-3244&v=0&c=true\">ZopaLogo@2x.png</value><value
|
141
|
+
id=\"89-3385\" url=\"http://youtrack.zopian.ad.zopa.com/_persistent/header-375%3E%402x.png?file=89-3385&v=0&c=true\">header-375>@2x.png</value></field><comment
|
142
|
+
id=\"88-12408\" author=\"tom.groombridge\" authorFullName=\"Tom Groombridge\"
|
143
|
+
issueId=\"PIO-338\" deleted=\"false\" text=\"can we estimate this? \" shownForIssueAuthor=\"false\"
|
144
|
+
created=\"1470159862211\"><replies/></comment><comment id=\"88-12411\" author=\"natalia.alvarez\"
|
145
|
+
authorFullName=\"Natalia Alvarez\" issueId=\"PIO-338\" deleted=\"false\" text=\"@greg.baker
|
146
|
+
could you please estimate? you ll have a better guess than I\" shownForIssueAuthor=\"false\"
|
147
|
+
created=\"1470212064496\"><replies/></comment><comment id=\"88-12466\" author=\"tom.groombridge\"
|
148
|
+
authorFullName=\"Tom Groombridge\" issueId=\"PIO-338\" deleted=\"false\" text=\"need
|
149
|
+
mobile designs to finish this card off\" shownForIssueAuthor=\"false\" created=\"1470302300253\"
|
150
|
+
updated=\"1470159862199\"><replies/></comment><comment id=\"88-12662\" author=\"alfredo.motta\"
|
151
|
+
authorFullName=\"Alfredo Motta\" issueId=\"PIO-338\" deleted=\"false\" text=\"Why
|
152
|
+
this is not progressing? @natalia.alvarez 
Where is the PR? @tom.groombridge
|
153
|
+
@kate.beavis \" shownForIssueAuthor=\"false\" created=\"1470994574703\"><replies/></comment><comment
|
154
|
+
id=\"88-12664\" author=\"kate.beavis\" authorFullName=\"Kate Beavis\" issueId=\"PIO-338\"
|
155
|
+
deleted=\"false\" text=\"I don't know what is happening with this, I raised
|
156
|
+
it in Hipchat but there was no response, @tom.groombridge should have a better
|
157
|
+
idea than me as he moved it into acceptance\" shownForIssueAuthor=\"false\"
|
158
|
+
created=\"1470994880006\"><replies/></comment><comment id=\"88-12668\" author=\"tom.groombridge\"
|
159
|
+
authorFullName=\"Tom Groombridge\" issueId=\"PIO-338\" deleted=\"false\" text=\"possibly
|
160
|
+
@greg.baker said this was done at the last retro.... Maybe I'm wrong though.\"
|
161
|
+
shownForIssueAuthor=\"false\" created=\"1470995969242\" updated=\"1470302300238\"><replies/></comment><comment
|
162
|
+
id=\"88-13007\" author=\"marie.steinthaler\" authorFullName=\"Marie Steinthaler\"
|
163
|
+
issueId=\"PIO-338\" deleted=\"false\" text=\"@greg.baker what's up with this
|
164
|
+
one? This doesn't seem to be in either sandbox or prod. Let's crush this one,
|
165
|
+
seems easy.\" shownForIssueAuthor=\"false\" created=\"1472055010957\"><replies/></comment><comment
|
166
|
+
id=\"88-13066\" author=\"greg.baker\" authorFullName=\"Greg Baker\" issueId=\"PIO-338\"
|
167
|
+
deleted=\"false\" text=\"we need a mobile design to finish this off. it has
|
168
|
+
been done for web, but the mobile view doesn't look ideal
\" shownForIssueAuthor=\"false\"
|
169
|
+
created=\"1472131737590\"><replies/></comment><comment id=\"88-13166\" author=\"alfredo.motta\"
|
170
|
+
authorFullName=\"Alfredo Motta\" issueId=\"PIO-338\" deleted=\"false\" text=\"have
|
171
|
+
we pushing this forward then?\" shownForIssueAuthor=\"false\" created=\"1472577102355\"><replies/></comment><comment
|
172
|
+
id=\"88-13216\" author=\"marie.steinthaler\" authorFullName=\"Marie Steinthaler\"
|
173
|
+
issueId=\"PIO-338\" deleted=\"false\" text=\"@natalia.alvarez the guys need
|
174
|
+
a mobile design - can you help please :-) Thanks!\" shownForIssueAuthor=\"false\"
|
175
|
+
created=\"1472660527813\"><replies/></comment><comment id=\"88-13220\" author=\"natalia.alvarez\"
|
176
|
+
authorFullName=\"Natalia Alvarez\" issueId=\"PIO-338\" deleted=\"false\" text=\"@marie.steinthaler
|
177
|
+
mobile version attached\" shownForIssueAuthor=\"false\" created=\"1472717148927\"
|
178
|
+
updated=\"1470212064475\"><replies/></comment><comment id=\"88-13515\" author=\"Orrin_Ward\"
|
179
|
+
authorFullName=\"Orrin Ward\" issueId=\"PIO-338\" deleted=\"false\" text=\"This
|
180
|
+
shouldn't be a "Functional Story" in Acceptance unless there is
|
181
|
+
code, and a PR, in UAT.\" shownForIssueAuthor=\"false\" created=\"1473345934653\"><replies/></comment></issue>"
|
182
|
+
http_version:
|
183
|
+
recorded_at: Thu, 08 Sep 2016 18:19:06 GMT
|
184
|
+
recorded_with: VCR 3.0.3
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'webmock'
|
3
|
+
require_relative '../../../support/vcr_helper'
|
4
|
+
require 'git-whistles/youtrack/api'
|
5
|
+
|
6
|
+
describe Git::Whistles::Youtrack::Api do
|
7
|
+
before do
|
8
|
+
allow(subject).to receive(:`).
|
9
|
+
with('git config youtrack.username').
|
10
|
+
and_return('some_username')
|
11
|
+
|
12
|
+
allow(subject).to receive(:`).
|
13
|
+
with('git config youtrack.password').
|
14
|
+
and_return('some_password')
|
15
|
+
|
16
|
+
allow(subject).to receive(:`).
|
17
|
+
with('git config youtrack.url').
|
18
|
+
and_return('http://youtrack.com/')
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#username' do
|
22
|
+
it 'returns the youtrack api username' do
|
23
|
+
expect(subject.username).to eq('some_username')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#password' do
|
28
|
+
it 'returns the youtrack api password' do
|
29
|
+
expect(subject.password).to eq('some_password')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#find_ticket' do
|
34
|
+
context 'when successfull' do
|
35
|
+
it 'returns a ticket with title' do
|
36
|
+
VCR.use_cassette('get_ticket_successfull') do
|
37
|
+
ticket = subject.find_ticket('PIO-338')
|
38
|
+
|
39
|
+
expect(ticket.title).to eq("Header styling changes")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns a ticket with id' do
|
44
|
+
VCR.use_cassette('get_ticket_successfull') do
|
45
|
+
ticket = subject.find_ticket('PIO-338')
|
46
|
+
|
47
|
+
expect(ticket.id).to eq(338)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'returns a ticket project name' do
|
52
|
+
VCR.use_cassette('get_ticket_successfull') do
|
53
|
+
ticket = subject.find_ticket('PIO-338')
|
54
|
+
|
55
|
+
expect(ticket.project).to eq("PIO")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns a ticket description' do
|
60
|
+
VCR.use_cassette('get_ticket_successfull') do
|
61
|
+
ticket = subject.find_ticket('PIO-338')
|
62
|
+
|
63
|
+
expect(ticket.description).to include("==Why==")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when ticket not found' do
|
69
|
+
it 'returns nil' do
|
70
|
+
VCR.use_cassette('get_ticket_not_found') do
|
71
|
+
ticket = subject.find_ticket('non-existent')
|
72
|
+
|
73
|
+
expect(ticket).to be_nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when authentication fails' do
|
79
|
+
it 'returns nil' do
|
80
|
+
VCR.use_cassette('get_ticket_auth_failure') do
|
81
|
+
ticket = subject.find_ticket('PIO-338')
|
82
|
+
|
83
|
+
expect(ticket).to be_nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when credentials not setup' do
|
89
|
+
before do
|
90
|
+
allow(subject).to receive(:`).
|
91
|
+
with('git config youtrack.username').
|
92
|
+
and_return('')
|
93
|
+
|
94
|
+
allow(Term::ANSIColor).to receive(:yellow).and_return "warning for user"
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'prints a message and returns nil' do
|
98
|
+
expect(subject).to receive(:puts).with "warning for user"
|
99
|
+
|
100
|
+
VCR.use_cassette('get_ticket_auth_failure') do
|
101
|
+
ticket = subject.find_ticket('PIO-338')
|
102
|
+
|
103
|
+
expect(ticket).to be_nil
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'git-whistles/youtrack/branch'
|
3
|
+
|
4
|
+
RSpec.describe Git::Whistles::Youtrack::Branch do
|
5
|
+
describe '#main' do
|
6
|
+
subject { described_class.new(current_dir: '/home/myuser') }
|
7
|
+
|
8
|
+
context 'with no arguments' do
|
9
|
+
it 'prints an error message' do
|
10
|
+
expect(subject).to receive(:puts).with("\e[33mUsage: git youtrack-branch YOUTRACK_STORY_ID\e[0m")
|
11
|
+
|
12
|
+
subject.main([])
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns false' do
|
16
|
+
expect(subject).to receive(:puts)
|
17
|
+
|
18
|
+
expect(subject.main([])).to eq(false)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with a ticket id argument' do
|
23
|
+
before do
|
24
|
+
expect(Readline).to receive(:readline).and_return ""
|
25
|
+
expect(Git::Whistles::Youtrack::Api).to receive(:new).and_return youtrack_api
|
26
|
+
expect(subject).to receive(:puts).at_least(:once)
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:youtrack_api) { double(find_ticket: ticket) }
|
30
|
+
let(:ticket_id) { "338" }
|
31
|
+
let(:ticket) do
|
32
|
+
Git::Whistles::Youtrack::Ticket.new.tap do |ticket|
|
33
|
+
ticket.title = "Some title"
|
34
|
+
ticket.project = "PRJ"
|
35
|
+
ticket.id = ticket_id.to_i
|
36
|
+
ticket.description = "Some description"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'issues a neat checkout command' do
|
41
|
+
expect(subject).to receive(:`).with('cd /home/myuser && git checkout -b prj/some-title-338')
|
42
|
+
|
43
|
+
subject.main([ticket_id])
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns true' do
|
47
|
+
expect(subject).to receive(:`)
|
48
|
+
|
49
|
+
expect(subject.main([ticket_id])).to eq(true)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,91 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
4
|
-
# this file to always be loaded, without a need to explicitly require it in any
|
5
|
-
# files.
|
6
|
-
#
|
7
|
-
# Given that it is always loaded, you are encouraged to keep this file as
|
8
|
-
# light-weight as possible. Requiring heavyweight dependencies from this file
|
9
|
-
# will add to the boot time of your test suite on EVERY test run, even for an
|
10
|
-
# individual file that may not need all of that loaded. Instead, consider making
|
11
|
-
# a separate helper file that requires the additional dependencies and performs
|
12
|
-
# the additional setup, and require it from the spec files that actually need
|
13
|
-
# it.
|
14
|
-
#
|
15
|
-
# The `.rspec` file also contains a few flags that are not defaults but that
|
16
|
-
# users commonly want.
|
17
|
-
#
|
18
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
2
|
+
|
19
3
|
RSpec.configure do |config|
|
20
|
-
# rspec-expectations config goes here. You can use an alternate
|
21
|
-
# assertion/expectation library such as wrong or the stdlib/minitest
|
22
|
-
# assertions if you prefer.
|
23
4
|
config.expect_with :rspec do |expectations|
|
24
|
-
# This option will default to `true` in RSpec 4. It makes the `description`
|
25
|
-
# and `failure_message` of custom matchers include text for helper methods
|
26
|
-
# defined using `chain`, e.g.:
|
27
|
-
# be_bigger_than(2).and_smaller_than(4).description
|
28
|
-
# # => "be bigger than 2 and smaller than 4"
|
29
|
-
# ...rather than:
|
30
|
-
# # => "be bigger than 2"
|
31
5
|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
32
6
|
end
|
33
7
|
|
34
|
-
# rspec-mocks config goes here. You can use an alternate test double
|
35
|
-
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
36
8
|
config.mock_with :rspec do |mocks|
|
37
|
-
# Prevents you from mocking or stubbing a method that does not exist on
|
38
|
-
# a real object. This is generally recommended, and will default to
|
39
|
-
# `true` in RSpec 4.
|
40
9
|
mocks.verify_partial_doubles = true
|
41
10
|
end
|
42
|
-
|
43
|
-
# The settings below are suggested to provide a good initial experience
|
44
|
-
# with RSpec, but feel free to customize to your heart's content.
|
45
|
-
=begin
|
46
|
-
# These two settings work together to allow you to limit a spec run
|
47
|
-
# to individual examples or groups you care about by tagging them with
|
48
|
-
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
49
|
-
# get run.
|
50
|
-
config.filter_run :focus
|
51
|
-
config.run_all_when_everything_filtered = true
|
52
|
-
|
53
|
-
# Limits the available syntax to the non-monkey patched syntax that is
|
54
|
-
# recommended. For more details, see:
|
55
|
-
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
56
|
-
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
57
|
-
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
58
|
-
config.disable_monkey_patching!
|
59
|
-
|
60
|
-
# This setting enables warnings. It's recommended, but in some cases may
|
61
|
-
# be too noisy due to issues in dependencies.
|
62
|
-
config.warnings = true
|
63
|
-
|
64
|
-
# Many RSpec users commonly either run the entire suite or an individual
|
65
|
-
# file, and it's useful to allow more verbose output when running an
|
66
|
-
# individual spec file.
|
67
|
-
if config.files_to_run.one?
|
68
|
-
# Use the documentation formatter for detailed output,
|
69
|
-
# unless a formatter has already been configured
|
70
|
-
# (e.g. via a command-line flag).
|
71
|
-
config.default_formatter = 'doc'
|
72
|
-
end
|
73
|
-
|
74
|
-
# Print the 10 slowest examples and example groups at the
|
75
|
-
# end of the spec run, to help surface which specs are running
|
76
|
-
# particularly slow.
|
77
|
-
config.profile_examples = 10
|
78
|
-
|
79
|
-
# Run specs in random order to surface order dependencies. If you find an
|
80
|
-
# order dependency and want to debug it, you can fix the order by providing
|
81
|
-
# the seed, which is printed after each run.
|
82
|
-
# --seed 1234
|
83
|
-
config.order = :random
|
84
|
-
|
85
|
-
# Seed global randomization in this process using the `--seed` CLI option.
|
86
|
-
# Setting this allows you to use `--seed` to deterministically reproduce
|
87
|
-
# test failures related to randomization by passing the same `--seed` value
|
88
|
-
# as the one that triggered the failure.
|
89
|
-
Kernel.srand config.seed
|
90
|
-
=end
|
91
11
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-whistles
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julien Letessier
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-11-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -81,6 +81,34 @@ dependencies:
|
|
81
81
|
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: webmock
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: vcr
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
84
112
|
- !ruby/object:Gem::Dependency
|
85
113
|
name: pivotal-tracker
|
86
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,6 +151,20 @@ dependencies:
|
|
123
151
|
- - "~>"
|
124
152
|
- !ruby/object:Gem::Version
|
125
153
|
version: 1.0.0
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: youtrack
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - "~>"
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: 0.0.11
|
161
|
+
type: :runtime
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - "~>"
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: 0.0.11
|
126
168
|
description: A few helpers for classic Git workflows
|
127
169
|
email:
|
128
170
|
- julien.letessier@gmail.com
|
@@ -142,6 +184,7 @@ executables:
|
|
142
184
|
- git-select
|
143
185
|
- git-stash-and-checkout
|
144
186
|
- git-whistles
|
187
|
+
- git-youtrack-branch
|
145
188
|
extensions: []
|
146
189
|
extra_rdoc_files: []
|
147
190
|
files:
|
@@ -168,6 +211,7 @@ files:
|
|
168
211
|
- bin/git-select
|
169
212
|
- bin/git-stash-and-checkout
|
170
213
|
- bin/git-whistles
|
214
|
+
- bin/git-youtrack-branch
|
171
215
|
- git-whistles.gemspec
|
172
216
|
- lib/git-whistles.rb
|
173
217
|
- lib/git-whistles/app.rb
|
@@ -175,6 +219,9 @@ files:
|
|
175
219
|
- lib/git-whistles/jira.rb
|
176
220
|
- lib/git-whistles/logger.rb
|
177
221
|
- lib/git-whistles/version.rb
|
222
|
+
- lib/git-whistles/youtrack/api.rb
|
223
|
+
- lib/git-whistles/youtrack/branch.rb
|
224
|
+
- lib/git-whistles/youtrack/ticket.rb
|
178
225
|
- libexec/git-chop.sh
|
179
226
|
- libexec/git-list-branches.sh
|
180
227
|
- libexec/git-merge-po.sh
|
@@ -183,8 +230,14 @@ files:
|
|
183
230
|
- spec/data/base.po
|
184
231
|
- spec/data/local.po
|
185
232
|
- spec/data/remote.po
|
233
|
+
- spec/fixtures/vcr/get_ticket_auth_failure.yml
|
234
|
+
- spec/fixtures/vcr/get_ticket_not_found.yml
|
235
|
+
- spec/fixtures/vcr/get_ticket_successfull.yml
|
186
236
|
- spec/git_merge_po_spec.rb
|
237
|
+
- spec/lib/git-whistles/youtrack/api_spec.rb
|
238
|
+
- spec/lib/git-whistles/youtrack/branch_spec.rb
|
187
239
|
- spec/spec_helper.rb
|
240
|
+
- spec/support/vcr_helper.rb
|
188
241
|
homepage: http://github.com/mezis/git-whistles
|
189
242
|
licenses:
|
190
243
|
- MIT
|
@@ -205,7 +258,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
205
258
|
version: 1.3.6
|
206
259
|
requirements: []
|
207
260
|
rubyforge_project:
|
208
|
-
rubygems_version: 2.
|
261
|
+
rubygems_version: 2.5.1
|
209
262
|
signing_key:
|
210
263
|
specification_version: 4
|
211
264
|
summary: 'A few helpers for classic Git workflows: makes branching and merging, PO
|
@@ -214,5 +267,11 @@ test_files:
|
|
214
267
|
- spec/data/base.po
|
215
268
|
- spec/data/local.po
|
216
269
|
- spec/data/remote.po
|
270
|
+
- spec/fixtures/vcr/get_ticket_auth_failure.yml
|
271
|
+
- spec/fixtures/vcr/get_ticket_not_found.yml
|
272
|
+
- spec/fixtures/vcr/get_ticket_successfull.yml
|
217
273
|
- spec/git_merge_po_spec.rb
|
274
|
+
- spec/lib/git-whistles/youtrack/api_spec.rb
|
275
|
+
- spec/lib/git-whistles/youtrack/branch_spec.rb
|
218
276
|
- spec/spec_helper.rb
|
277
|
+
- spec/support/vcr_helper.rb
|