jira-cli 0.0.3 → 0.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 26e38024a72dacde2712cf36890c7343dd878241
4
- data.tar.gz: 1e5ee3a5a3719235da6f4890847c419708af349b
3
+ metadata.gz: 24aaafc8c0cbd9ae1830d16781ccfdae4d57c695
4
+ data.tar.gz: 64d3470c5ae4c3b0bcb5f9adfa403e0d0c4f0cf1
5
5
  SHA512:
6
- metadata.gz: d7fcc3a1fb30afb8d9adfa180d6c36a0529ad9feb9f197a74bd273d244ce30e717bee96adc921583b5ca8faaa877942fea75e08de642c8b388f9bb86c85f9108
7
- data.tar.gz: d2ddb2c5c015c9ba04492d3f7c7f31de6c52b928b1d5218001a3b1ea920ebbc91e4575c1f2aef00056837f85c2ea7e2e6fb41f467f91309102a1da254368fb6f
6
+ metadata.gz: ff546c7868f58330d07439fb52cbf01f9db9a076696f3b7d77b1ebde128ac5ea96f246484eb34e9194e262b75f748aba7ac3b7de6487507386e23cd60218cc8c
7
+ data.tar.gz: 88acd2274a38804e271b0a0f9dbbb00d19ea9e26cf3577cb72fba1f34d0cb3c8539e5030b31896b450a178379459a0fd6cdeb4671c140bfcb0dfaadab2eb0f0e
data/README.md CHANGED
@@ -1,4 +1,18 @@
1
- jira-cli
1
+ JIRA CLI
2
2
  ========
3
3
 
4
4
  Ruby gem CLI tool used to manage JIRA workflows leveraging git
5
+
6
+ Disclaimer
7
+ ----------
8
+ This tool is in very early alpha and its architecture and commands
9
+ are expected to change drastically. Please only use this tool for testing
10
+ purposes.
11
+
12
+ Installation
13
+ ------------
14
+ cd path/to/jira/repo
15
+ jira install
16
+
17
+ Note: Authentication files are expected to drastically change. Currently, they
18
+ are completely unencrypted. Use are your own risk... (see disclaimer above)
@@ -1,6 +1,9 @@
1
1
  require 'thor'
2
2
  require 'fileutils'
3
3
  require 'jira/constants'
4
+ require 'jira/core'
5
+ require 'jira/api'
6
+ require 'jira/format'
4
7
  require 'jira/mixins'
5
8
  require 'jira/version'
6
9
  require 'jira/install'
@@ -9,5 +12,11 @@ require 'jira/lookup'
9
12
  module Jira
10
13
  class CLI < Thor
11
14
 
15
+ def initialize(args=[], options={}, config={})
16
+ super
17
+ Jira::Core.setup
18
+ @api = Jira::API.new
19
+ end
20
+
12
21
  end
13
22
  end
@@ -0,0 +1,51 @@
1
+ module Jira
2
+ class API
3
+
4
+ #
5
+ # Initialize Jira::API
6
+ #
7
+ def initialize
8
+ @client = Faraday.new
9
+ @client.basic_auth(Jira::Core.username, Jira::Core.password)
10
+ end
11
+
12
+ #
13
+ # Issue an API GET request and return parsed JSON
14
+ #
15
+ # @param path [String] API path
16
+ #
17
+ # @return [JSON] parsed API response
18
+ #
19
+ def get(path)
20
+ response = @client.get(self.endpoint(path))
21
+ JSON.parse(response.body)
22
+ end
23
+
24
+ #
25
+ # Issue an API POST request and return parsed JSON
26
+ #
27
+ # @param path [String] API path
28
+ # @param params [Hash] params to post
29
+ #
30
+ # @return [JSON] parsed API response
31
+ #
32
+ def post(path, params)
33
+ response = @client.post(self.endpoint(path), params)
34
+ JSON.parse(response.body)
35
+ end
36
+
37
+ protected
38
+
39
+ #
40
+ # Returns the full JIRA REST API endpoint
41
+ #
42
+ # @param path [String] API path
43
+ #
44
+ # @return [String] API endpoint
45
+ #
46
+ def endpoint(path)
47
+ "#{Jira::Core.url}/rest/api/2/#{path}"
48
+ end
49
+
50
+ end
51
+ end
@@ -1,5 +1,5 @@
1
1
  module Jira
2
2
 
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
 
5
5
  end
@@ -0,0 +1,125 @@
1
+ module Jira
2
+ class Core
3
+ class << self
4
+
5
+ #
6
+ # Memoizes url, username, and password
7
+ #
8
+ def setup
9
+ self.url
10
+ self.auth
11
+ end
12
+
13
+ ### Virtual Attributes
14
+
15
+ #
16
+ # @return [String] JIRA project endpoint
17
+ #
18
+ def url
19
+ @url ||= self.read(self.url_path)
20
+ end
21
+
22
+ #
23
+ # @return [String] JIRA username
24
+ #
25
+ def username
26
+ @username ||= self.auth.first
27
+ end
28
+
29
+ #
30
+ # @return [String] JIRA password
31
+ #
32
+ def password
33
+ @password ||= self.auth.last
34
+ end
35
+
36
+ #
37
+ # Determines whether or not the input ticket matches the expected JIRA
38
+ # ticketing syntax.
39
+ #
40
+ # @param ticket [String] input ticket name
41
+ #
42
+ # @return [Boolean] whether input string matches JIRA ticket syntax
43
+ #
44
+ def ticket?(ticket)
45
+ !!ticket[/^[a-zA-Z]+-[0-9]+$/]
46
+ end
47
+
48
+ ### Relevant Paths
49
+
50
+ #
51
+ # @return [String] path to .jira-url file
52
+ #
53
+ def url_path
54
+ @url_path ||= self.root_path + "/.jira-url"
55
+ end
56
+
57
+ #
58
+ # @return [String] path to .jira-auth file
59
+ #
60
+ def auth_path
61
+ @auth_path ||= self.root_path + "/.jira-auth"
62
+ end
63
+
64
+ #
65
+ # @return [String] path of root git directory
66
+ #
67
+ def root_path
68
+ return @root_path if !@root_path.nil?
69
+ if !system('git rev-parse')
70
+ puts "JIRA commands can only be run within a git repository."
71
+ abort
72
+ end
73
+ @root_path ||= `git rev-parse --show-toplevel`.strip
74
+ end
75
+
76
+ protected
77
+
78
+ #
79
+ # Determines and parses the auth file
80
+ #
81
+ # @return [String] JIRA username
82
+ # @return [String] JIRA password
83
+ #
84
+ def auth
85
+ self.read(self.auth_path).split(':')
86
+ end
87
+
88
+ ### Core Actions
89
+
90
+ #
91
+ # Discards memozied class variables
92
+ #
93
+ def discard_memoized
94
+ @url = nil
95
+ @username = nil
96
+ @password = nil
97
+ end
98
+
99
+ #
100
+ # Validates the location and reads the contents of the input path
101
+ #
102
+ # @param path [String] path of file to read
103
+ #
104
+ # @return [String] contents of the file at the input path
105
+ #
106
+ def read(path)
107
+ self.validate_path!(path)
108
+ File.read(path).strip
109
+ end
110
+
111
+ #
112
+ # Aborts command if no file at the input path exists.
113
+ #
114
+ # @param path [String] path to validate
115
+ #
116
+ def validate_path!(path)
117
+ if !File.exists?(path)
118
+ say "Please run `jira install` before running this command."
119
+ abort
120
+ end
121
+ end
122
+
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,35 @@
1
+ module Jira
2
+ class Format
3
+ class << self
4
+
5
+ def star
6
+ "#{Thor::Shell::Color::BOLD}"\
7
+ "#{Thor::Shell::Color::YELLOW}"\
8
+ "*"\
9
+ "#{Thor::Shell::Color::CLEAR}"
10
+ end
11
+
12
+ def ticket(ticket)
13
+ "#{Thor::Shell::Color::RED}"\
14
+ "#{ticket}"\
15
+ "#{Thor::Shell::Color::CLEAR}"
16
+ end
17
+
18
+ def status(status)
19
+ "["\
20
+ "#{Thor::Shell::Color::BLUE}"\
21
+ "#{status}"\
22
+ "#{Thor::Shell::Color::CLEAR}"\
23
+ "]".center(26)
24
+ end
25
+
26
+ def summary(summary)
27
+ "#{Thor::Shell::Color::BOLD}"\
28
+ "#{Thor::Shell::Color::WHITE}"\
29
+ "#{summary}"\
30
+ "#{Thor::Shell::Color::CLEAR}"
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -7,11 +7,12 @@ module Jira
7
7
 
8
8
  desc "install", "Guides the user through JIRA installation"
9
9
  def install
10
- create_file self.jira_url_path, nil, verbose:false do
10
+
11
+ create_file Jira::Core.url_path, nil, verbose:false do
11
12
  self.cli.ask("Enter your JIRA URL: ")
12
13
  end
13
14
 
14
- create_file self.jira_auth_path, nil, verbose:false do
15
+ create_file Jira::Core.auth_path, nil, verbose:false do
15
16
  username = self.cli.ask("Enter your JIRA username: ")
16
17
  password = self.cli.ask("Enter your JIRA password: ") do |q|
17
18
  q.echo = false
@@ -19,7 +20,7 @@ module Jira
19
20
  "#{username}:#{password}"
20
21
  end
21
22
 
22
- self.discard_memoized
23
+ Jira::Core.send(:discard_memoized)
23
24
  end
24
25
 
25
26
  end
@@ -1,42 +1,52 @@
1
1
  module Jira
2
2
  class CLI < Thor
3
3
 
4
- desc "summarize", "Outputs the summary of the input ticket"
5
- def summarize(ticket=nil)
6
- ticket ||= ex('git rev-parse --abbrev-ref HEAD')
7
- json = self.api_get("issue/#{ticket}")
8
- summary = json['fields']['summary']
9
- status = json['fields']['status']['name']
10
- self.mutex.synchronize do
11
- say "#{self.colored_ticket(ticket)} "\
12
- "#{self.colored_status(status).center(26)} "\
13
- "#{self.colored_summary(summary)}"
14
- end
4
+ desc "describe", "Describes the input ticket"
5
+ def describe(ticket=nil)
6
+ ticket ||= `git rev-parse --abbrev-ref HEAD`.strip
7
+ output_summary(ticket)
15
8
  end
16
9
 
17
- desc "all", "Summarizes all tickets that have local branches"
10
+ desc "all", "Describes all local branches that match JIRA ticketing syntax"
18
11
  def all
19
- tickets = []
20
- branches = ex("git branch").delete("*").split("\n")
12
+ # determine which local branches match JIRA ticket syntax
13
+ # TODO - move to Jira::Git
14
+ tickets = {
15
+ current: nil,
16
+ others: []
17
+ }
18
+ branches = `git branch`.strip.split("\n")
21
19
  branches.each do |branch|
22
- stripped = branch.strip
23
- if !!stripped[/^[a-zA-Z]+-[0-9]+$/]
24
- tickets << stripped
20
+ ticket = branch.delete('*').strip
21
+ if Jira::Core.ticket?(ticket)
22
+ if branch.include?('*')
23
+ tickets[:current] = ticket
24
+ else
25
+ tickets[:others] << ticket
26
+ end
25
27
  end
26
28
  end
27
29
 
30
+
31
+ # asynchronously fetch and describe tickets
32
+ output = ""
28
33
  threads = []
29
- tickets.each do |ticket|
30
- threads << Thread.new{ self.summarize(ticket) }
34
+ threads << Thread.new{ puts description(tickets[:current], true) }
35
+ mutex = Mutex.new
36
+ tickets[:others].each do |ticket|
37
+ threads << Thread.new do
38
+ out = description(ticket) + "\n"
39
+ mutex.synchronize{ output << out }
40
+ end
31
41
  end
32
42
  threads.each{ |thread| thread.join }
43
+
44
+ puts output
33
45
  end
34
46
 
35
47
  desc "comment", "Add a comment to the input ticket"
36
48
  def comment(ticket=nil)
37
49
  say "Coming soon"
38
- #ticket ||= ex('get rev-parse --abbrev-ref HEAD')
39
- #json = self.api_post("issue/#{ticket}")
40
50
  end
41
51
 
42
52
  desc "transition", "Transitions the input ticket to the next state"
@@ -46,55 +56,22 @@ module Jira
46
56
 
47
57
  protected
48
58
 
49
- def colored_ticket(ticket)
50
- "("\
51
- "#{Thor::Shell::Color::RED}"\
52
- "#{ticket}"\
53
- "#{Thor::Shell::Color::CLEAR}"\
54
- ")"
55
- end
56
-
57
- def colored_status(status)
58
- "["\
59
- "#{Thor::Shell::Color::BLUE}"\
60
- "#{status}"\
61
- "#{Thor::Shell::Color::CLEAR}"\
62
- "]"
63
- end
64
-
65
- def colored_summary(summary)
66
- "#{Thor::Shell::Color::BOLD}"\
67
- "#{Thor::Shell::Color::WHITE}"\
68
- "#{summary}"\
69
- "#{Thor::Shell::Color::CLEAR}"
70
- end
71
-
72
- def api_get(path)
73
- response = self.client.get self.api_path(path)
74
- return JSON.parse(response.body)
75
- end
76
-
77
- def api_post(path, params)
78
- response = self.client.post self.api_path(path), params
79
- return JSON.parse(response)
80
- end
81
-
82
- def api_path(path)
83
- "#{self.jira_url}/rest/api/2/#{path}"
84
- end
85
-
86
- def mutex
87
- @mutex ||= Mutex.new
88
- end
89
-
90
- def client
91
- self.mutex.synchronize do
92
- return @client if !@client.nil?
93
- @client = Faraday.new
94
- username, password = self.jira_auth
95
- @client.basic_auth(username, password)
96
- return @client
97
- end
59
+ #
60
+ # Returns a formatted description of the input ticket
61
+ #
62
+ # @param ticket [String] the ticket to describe
63
+ # @param star [Boolean] if true, adds a * indicator
64
+ #
65
+ # @return [String] formatted summary string
66
+ #
67
+ def description(ticket, star=false)
68
+ json = @api.get("issue/#{ticket}")
69
+ summary = json['fields']['summary']
70
+ status = json['fields']['status']['name']
71
+ return Jira::Format.ticket(ticket) +
72
+ (star ? Jira::Format.star : " ") +
73
+ Jira::Format.status(status) +
74
+ Jira::Format.summary(summary)
98
75
  end
99
76
 
100
77
  end
@@ -5,57 +5,9 @@ module Jira
5
5
  require 'json'
6
6
  require 'faraday'
7
7
  include Thor::Actions
8
- include Thor::Shell
9
8
 
10
9
  protected
11
10
 
12
- #
13
- # @return [String] JIRA endpoint
14
- #
15
- def jira_url
16
- return @jira_url if !@jira_url.nil?
17
- path = self.jira_url_path
18
- self.validate_path!(path)
19
- @jira_url ||= File.read(path).strip
20
- end
21
-
22
- #
23
- # @return [String] JIRA authorization
24
- #
25
- # @return [String] username
26
- # @return [String] password
27
- #
28
- def jira_auth
29
- if !@username.nil? && !@password.nil?
30
- return @username, @password
31
- end
32
- path = self.jira_auth_path
33
- self.validate_path!(path)
34
- @username, @password = File.read(path).strip.split(':')
35
- return @username, @password
36
- end
37
-
38
- #
39
- # @return [String] path to .jira-url file
40
- #
41
- def jira_url_path
42
- @url_path ||= self.root_path + "/.jira-url"
43
- end
44
-
45
- #
46
- # @return [String] path to .jira-auth file
47
- #
48
- def jira_auth_path
49
- @auth_path ||= self.root_path + "/.jira-auth"
50
- end
51
-
52
- #
53
- # @return [String] path to root git directory
54
- #
55
- def root_path
56
- @root_path ||= ex "git rev-parse --show-toplevel"
57
- end
58
-
59
11
  #
60
12
  # @return [Highline] HighLine instance for handling input
61
13
  #
@@ -63,28 +15,5 @@ module Jira
63
15
  @highline ||= ::HighLine.new
64
16
  end
65
17
 
66
- #
67
- # Execute shell command
68
- #
69
- # @param command [String] command to run
70
- # @return [String] output of the run command
71
- #
72
- def ex(command)
73
- run(command, verbose:false, capture:true).strip
74
- end
75
-
76
- def validate_path!(path)
77
- if !File.exists?(path)
78
- say "Please run `jira install` before running this action..."
79
- abort
80
- end
81
- end
82
-
83
- def discard_memoized
84
- @username = nil
85
- @password = nil
86
- @jira_url = nil
87
- end
88
-
89
18
  end
90
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jira-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darren Lin Cheng
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-05 00:00:00.000000000 Z
11
+ date: 2013-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -60,7 +60,10 @@ extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
62
  - bin/jira
63
+ - lib/jira/api.rb
63
64
  - lib/jira/constants.rb
65
+ - lib/jira/core.rb
66
+ - lib/jira/format.rb
64
67
  - lib/jira/install.rb
65
68
  - lib/jira/lookup.rb
66
69
  - lib/jira/mixins.rb