story_branch 0.7.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38598ac513a6f1681731cfd2fa3c01a59adb5ceefd21b13c1f522f278d0dbfeb
4
- data.tar.gz: 19aa50f492337817aeaab621f12db12cb7b035cfc1323cff704063cb689520f6
3
+ metadata.gz: 53a5f42efde29c37e024d47aa0d0542d3645499eaf8ae518a7b1fbc03eb2d50f
4
+ data.tar.gz: 7ffdcf865cbd091cff86dc516ac4bc3daa8fc29f55cbbea3f4b9f707b41d9990
5
5
  SHA512:
6
- metadata.gz: 2a7f8523bc5dd537eaf6195d51449843d4cb6c9860da05cb1a5caf582cf7244ff7dc481881d517221b6e3772fb9492a59a821351fdee786ed902b938e5773282
7
- data.tar.gz: 716a2494b92218c4ba0ce1b2b73aa8fe1b8ea635a549312e31b2721405710d706cbe4ad905c30a3b4a8f6700732aa677bcfc10d1490b3ad9fecf17f536681521
6
+ metadata.gz: 911475a7844a3efe57ffa0fe0f2aab02abf42b8c90ad4083ecefd1b0d03dc987d5987bde4a512902cf76048ee3132521f98f4d36db1b2be1453a363de6831578
7
+ data.tar.gz: 270037755290c76896cd4c288d1741bb70a34c0dbd60e702e21b9fa59b95a1284efb4dbbf7a260ef780afdfd620c40fcdec8546771a7236c6ba05246d18a8f26
data/.circleci/config.yml CHANGED
@@ -1,15 +1,14 @@
1
- version: 2
2
-
3
- defaults: &defaults
4
- docker:
5
- - image: circleci/ruby:2.6.5-node
6
- working_directory: ~/repo
1
+ version: 2.1
7
2
 
8
3
  workflows:
9
4
  version: 2
10
5
  test-and-publish:
11
6
  jobs:
12
7
  - test:
8
+ matrix:
9
+ parameters:
10
+ ruby_version: ["ruby:2.6-buster", "ruby:2.7-buster", "ruby:3.0-buster"]
11
+
13
12
  filters:
14
13
  tags:
15
14
  # this enables circleci to trigger on tags
@@ -26,14 +25,22 @@ workflows:
26
25
 
27
26
  jobs:
28
27
  test:
29
- <<: *defaults
28
+ parameters:
29
+ ruby_version:
30
+ type: string
31
+ docker:
32
+ - image: circleci/<< parameters.ruby_version >>
33
+ working_directory: ~/repo
34
+
30
35
  steps:
31
36
  - checkout
32
37
 
33
- - restore_cache:
34
- keys:
35
- - v1-dependencies-{{ checksum "Gemfile.lock" }}
36
- - v1-dependencies-
38
+ - run:
39
+ name: Install Code Climate Test Reporter
40
+ command: |
41
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
42
+ chmod +x ./cc-test-reporter
43
+ - run: ./cc-test-reporter before-build
37
44
 
38
45
  - run:
39
46
  name: install dependencies
@@ -41,11 +48,6 @@ jobs:
41
48
  gem install bundler
42
49
  bundle install --jobs=4 --retry=3 --path vendor/bundle
43
50
 
44
- - save_cache:
45
- paths:
46
- - ./vendor/bundle
47
- key: v1-dependencies-{{ checksum "Gemfile.lock" }}
48
-
49
51
  - run:
50
52
  name: run tests
51
53
  command: |
@@ -61,29 +63,31 @@ jobs:
61
63
  path: /tmp/test-results
62
64
  - store_artifacts:
63
65
  path: /tmp/test-results
64
- destination: test-results
66
+
67
+ - run:
68
+ name: Code Climate Test Coverage convert to json
69
+ command: |
70
+ ./cc-test-reporter format-coverage -t simplecov
71
+
72
+ - run:
73
+ name: Code Climate Test Coverage upload results
74
+ command: |
75
+ ./cc-test-reporter after-build -t simplecov --exit-code $?
65
76
 
66
77
  publish:
67
- <<: *defaults
78
+ docker:
79
+ - image: circleci/ruby:3.0-buster
80
+ working_directory: ~/repo
81
+
68
82
  steps:
69
83
  - checkout
70
84
 
71
- - restore_cache:
72
- keys:
73
- - v1-dependencies-{{ checksum "Gemfile.lock" }}
74
- - v1-dependencies-
75
-
76
85
  - run:
77
86
  name: install dependencies
78
87
  command: |
79
88
  gem install bundler
80
89
  bundle install --jobs=4 --retry=3 --path vendor/bundle
81
90
 
82
- - save_cache:
83
- paths:
84
- - ./vendor/bundle
85
- key: v1-dependencies-{{ checksum "Gemfile.lock" }}
86
-
87
91
  - run:
88
92
  name: Setup Rubygems
89
93
  command: bash .circleci/setup-rubygems.sh
@@ -0,0 +1,7 @@
1
+ # Configuration for weekly-digest - https://github.com/apps/weekly-digest
2
+ publishDay: sun
3
+ canPublishIssues: true
4
+ canPublishPullRequests: true
5
+ canPublishContributors: true
6
+ canPublishStargazers: true
7
+ canPublishCommits: true
data/.gitignore CHANGED
@@ -2,3 +2,6 @@
2
2
  story_branch-*.gem
3
3
  /.pairs
4
4
  .byebug_history
5
+ coverage
6
+ tools/release*.*
7
+ Gemfile.lock
data/.rubocop.yml CHANGED
@@ -7,3 +7,45 @@ AllCops:
7
7
  - 'exe/*'
8
8
  - '**/Gemfile'
9
9
  - '.github/**/*'
10
+
11
+ Layout/EmptyLinesAroundAttributeAccessor:
12
+ Enabled: true
13
+
14
+ Layout/SpaceAroundMethodCallOperator:
15
+ Enabled: true
16
+
17
+ Lint/DeprecatedOpenSSLConstant:
18
+ Enabled: true
19
+
20
+ Lint/MixedRegexpCaptureTypes:
21
+ Enabled: true
22
+
23
+ Lint/RaiseException:
24
+ Enabled: true
25
+
26
+ Lint/StructNewOverride:
27
+ Enabled: true
28
+
29
+ Style/ExponentialNotation:
30
+ Enabled: true
31
+
32
+ Style/HashEachMethods:
33
+ Enabled: true
34
+
35
+ Style/HashTransformKeys:
36
+ Enabled: true
37
+
38
+ Style/HashTransformValues:
39
+ Enabled: true
40
+
41
+ Style/RedundantFetchBlock:
42
+ Enabled: true
43
+
44
+ Style/RedundantRegexpCharacterClass:
45
+ Enabled: true
46
+
47
+ Style/RedundantRegexpEscape:
48
+ Enabled: true
49
+
50
+ Style/SlicingWithRange:
51
+ Enabled: true
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.1
1
+ 2.7.1
data/README.md CHANGED
@@ -4,11 +4,17 @@
4
4
 
5
5
  # Story Branch
6
6
 
7
- Story branch is a CLI application that interacts with Pivotal Tracker or Github at the
7
+ Story branch is a CLI application that interacts with Pivotal Tracker, Github and Jira
8
8
  at the moment.
9
- It allows you to start and un-start stories in Pivotal Tracker, as well as creating
10
- branches based on the story name and id and have a final commit message marking
11
- the story as Finished.
9
+
10
+ For all the trackers it supports creating local branches from the tickets or
11
+ opening the ticket in your browser from the branch you're working on. In the future
12
+ I plan to support different workflows in order to integrate your individual
13
+ process in the tool.
14
+
15
+ As for PivotalTracker, since the flow is mostly the same for everyone, it allows
16
+ you to start and un-start stories as well.
17
+
12
18
 
13
19
  [View Changelog](Changelog.md)
14
20
 
@@ -30,8 +36,8 @@ You can see all the commands available by running
30
36
  $ story_branch -h
31
37
 
32
38
  Commands:
33
- story_branch add # Add a new story branch configuration
34
- story_branch create # Create branch from estimated stories in pivotal tracker
39
+ story_branch configure # Configure a new story branch configuration
40
+ story_branch create # Create branch from a ticket in the tracker
35
41
  story_branch finish # Creates a git commit message for the staged changes with a [Finishes] tag
36
42
  story_branch help [COMMAND] # Describe available commands or one specific command
37
43
  story_branch migrate # Migrate old story branch configuration to the new format
@@ -113,14 +119,14 @@ the full list.
113
119
 
114
120
  ## Configuring PivotalTracker
115
121
 
116
- When running the command `story_branch add` you'll be asked 3 things:
122
+ When running the command `story_branch configure` you'll be asked 3 things:
117
123
  1. tracker - You should select Pivotal Tracker
118
124
  2. project id - This can be fetched from the PivotalTracker url. E.g in the url `https://www.pivotaltracker.com/n/projects/651417`, the project id would be `651417`
119
125
  3. api key - this is your personal api key. You can get that from [your profile page](https://www.pivotaltracker.com/profile)
120
126
 
121
127
  ## Configuring Github
122
128
 
123
- When running the command `story_branch add` you'll be asked 3 things:
129
+ When running the command `story_branch configure` you'll be asked 3 things:
124
130
  1. project id - This is the github repository name in the format `<owner>/<repo_name>`. E.g. `story-branch/story_branch`.
125
131
  2. tracker - You should select Github
126
132
  3. api key - this is your personal api token. You can create one under your
data/docs/index.md CHANGED
@@ -33,13 +33,13 @@ You can see all the commands available by running
33
33
  $ story_branch -h
34
34
 
35
35
  Commands:
36
- story_branch add # Add a new story branch configuration
37
- story_branch create # Create branch from estimated stories in pivotal tracker
36
+ story_branch configure # Setup story branch with a new/existing project
37
+ story_branch create # Create branch from a ticket in the tracker
38
38
  story_branch finish # Creates a git commit message for the staged changes with a [Finishes] tag
39
39
  story_branch help [COMMAND] # Describe available commands or one specific command
40
40
  story_branch migrate # Migrate old story branch configuration to the new format
41
- story_branch start # Mark an estimated story as started in Pivotal Tracker
42
- story_branch unstart # Mark a started story as un-started in Pivotal Tracker
41
+ story_branch start # Mark an estimated story as started [Only for Pivotal Tracker]
42
+ story_branch unstart # Mark a started story as un-started [Only for Pivotal Tracker]
43
43
  story_branch version # story_branch gem version
44
44
  ```
45
45
 
@@ -116,14 +116,14 @@ the full list.
116
116
 
117
117
  ## Configuring PivotalTracker
118
118
 
119
- When running the command `story_branch add` you'll be asked 3 things:
119
+ When running the command `story_branch configure` you'll be asked 3 things:
120
120
  1. tracker - You should select Pivotal Tracker
121
121
  2. project id - This can be fetched from the PivotalTracker url. E.g in the url `https://www.pivotaltracker.com/n/projects/651417`, the project id would be `651417`
122
122
  3. api key - this is your personal api key. You can get that from [your profile page](https://www.pivotaltracker.com/profile)
123
123
 
124
124
  ## Configuring Github
125
125
 
126
- When running the command `story_branch add` you'll be asked 3 things:
126
+ When running the command `story_branch configure` you'll be asked 3 things:
127
127
  1. project id - This is the github repository name in the format `<owner>/<repo_name>`. E.g. `story-branch/story_branch`.
128
128
  2. tracker - You should select Github
129
129
  3. api key - this is your personal api token. You can create one under your
@@ -18,7 +18,19 @@ module StoryBranch
18
18
  end
19
19
  map %w[--version -v] => :version
20
20
 
21
- desc 'unstart', 'Mark a started story as un-started in Pivotal Tracker'
21
+ desc 'open_issue', 'Open ticket in the configured tracker'
22
+ method_option :help, aliases: '-h', type: :boolean,
23
+ desc: 'Display usage information'
24
+ def open_issue(*)
25
+ if options[:help]
26
+ invoke :help, ['open_issue']
27
+ else
28
+ require_relative 'commands/open_issue'
29
+ StoryBranch::Commands::OpenIssue.new(options).execute
30
+ end
31
+ end
32
+
33
+ desc 'unstart', 'Mark a started story as un-started [Only for Pivotal Tracker]'
22
34
  method_option :help, aliases: '-h', type: :boolean,
23
35
  desc: 'Display usage information'
24
36
  def unstart(*)
@@ -30,7 +42,7 @@ module StoryBranch
30
42
  end
31
43
  end
32
44
 
33
- desc 'start', 'Mark an estimated story as started in Pivotal Tracker'
45
+ desc 'start', 'Mark an estimated story as started [Only for Pivotal Tracker]'
34
46
  method_option :help, aliases: '-h', type: :boolean,
35
47
  desc: 'Display usage information'
36
48
  def start(*)
@@ -55,7 +67,7 @@ module StoryBranch
55
67
  end
56
68
  end
57
69
 
58
- desc 'create', 'Create branch from estimated stories in pivotal tracker'
70
+ desc 'create', 'Create branch from a ticket in the tracker'
59
71
  method_option :help, aliases: '-h', type: :boolean,
60
72
  desc: 'Display usage information'
61
73
  def create(*)
@@ -67,15 +79,15 @@ module StoryBranch
67
79
  end
68
80
  end
69
81
 
70
- desc 'add', 'Add a new story branch configuration'
82
+ desc 'configure', 'Setup story branch with a new/existing project'
71
83
  method_option :help, aliases: '-h', type: :boolean,
72
84
  desc: 'Display usage information'
73
- def add(*)
85
+ def configure(*)
74
86
  if options[:help]
75
- invoke :help, ['add']
87
+ invoke :help, ['configure']
76
88
  else
77
- require_relative 'commands/add'
78
- StoryBranch::Commands::Add.new(options).execute
89
+ require_relative 'commands/configure'
90
+ StoryBranch::Commands::Configure.new(options).execute
79
91
  end
80
92
  end
81
93
  end
@@ -12,8 +12,9 @@ module StoryBranch
12
12
  #
13
13
  # It will try to load the existing global story branch config
14
14
  # and then add the project id specified by the user.
15
- class Add < StoryBranch::Command
15
+ class Configure < StoryBranch::Command
16
16
  def initialize(_options)
17
+ super()
17
18
  @new_config = ConfigManager.new
18
19
  end
19
20
 
@@ -45,10 +46,8 @@ module StoryBranch
45
46
 
46
47
  return unless tracker == 'jira'
47
48
 
48
- # rubocop:disable Metrics/LineLength
49
49
  username = prompt.ask('Please provide username (email most of the times) for this key:',
50
50
  required: true)
51
- # rubocop:enable Metrics/LineLength
52
51
  @new_config.username = username
53
52
  end
54
53
 
@@ -8,6 +8,7 @@ module StoryBranch
8
8
  # started stories in the tracker
9
9
  class Create < StoryBranch::Command
10
10
  def initialize(options)
11
+ super()
11
12
  @options = options
12
13
  end
13
14
 
@@ -7,6 +7,7 @@ module StoryBranch
7
7
  # Command to finish a story
8
8
  class Finish < StoryBranch::Command
9
9
  def initialize(options)
10
+ super()
10
11
  @options = options
11
12
  end
12
13
 
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../command'
4
+
5
+ module StoryBranch
6
+ module Commands
7
+ # OpenIssue command is used to open the associated ticket in the browser
8
+ class OpenIssue < StoryBranch::Command
9
+ def initialize(options)
10
+ super()
11
+ @options = options
12
+ end
13
+
14
+ def execute(_input: $stdin, output: $stdout)
15
+ require_relative '../main'
16
+ sb = StoryBranch::Main.new
17
+ res = sb.open_current_url
18
+ output.write(res)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -7,6 +7,7 @@ module StoryBranch
7
7
  # Command to start an estimated story
8
8
  class Start < StoryBranch::Command
9
9
  def initialize(options)
10
+ super()
10
11
  @options = options
11
12
  end
12
13
 
@@ -7,6 +7,7 @@ module StoryBranch
7
7
  # Command to unstart a previously started story
8
8
  class Unstart < StoryBranch::Command
9
9
  def initialize(options)
10
+ super()
10
11
  @options = options
11
12
  end
12
13
 
@@ -20,25 +20,8 @@ module StoryBranch
20
20
  false
21
21
  end
22
22
 
23
- def self.branch_for_story_exists?(id)
24
- GitWrapper.branch_names.each do |n|
25
- branch_id = n.match(/-[1-9]+[0-9]*$/)
26
- next unless branch_id
27
- return true if branch_id.to_s == "-#{id}"
28
- end
29
- false
30
- end
31
-
32
- def self.current_story
33
- /(.*)-(\d+$)/.match GitWrapper.current_branch
34
- end
35
-
36
- def self.current_branch_story_parts
37
- matches = current_story
38
- return {} unless matches&.length == 3
39
-
40
- title = matches[1].tr('-', ' ').strip
41
- { title: title, id: matches[2].to_i }
23
+ def self.branch_to_story_string(regex_matcher = /.*-(\d+$)/)
24
+ GitWrapper.current_branch.match(regex_matcher)
42
25
  end
43
26
 
44
27
  def self.status?(state)
@@ -36,7 +36,7 @@ module StoryBranch
36
36
  # remotes/origin/allow.... <- remote branch (remove 'remotes/origin')
37
37
  # * allow.... <- * indicates current branch (remove '* ')
38
38
  # allow <- local branch (do nothing)
39
- regex = %r{(^remotes\/.*\/|\s|[*])}
39
+ regex = %r{(^remotes/.*/|\s|[*])}
40
40
  all_branches.map do |line|
41
41
  line = line.sub(regex, '')
42
42
  line
@@ -47,7 +47,7 @@ module StoryBranch
47
47
  current_branch_line = all_branches.detect do |line|
48
48
  line.match(/\*/)
49
49
  end
50
- current_branch_line.tr('*', ' ')
50
+ current_branch_line.tr('*', ' ').strip
51
51
  end
52
52
 
53
53
  def self.all_branches
@@ -7,7 +7,7 @@ module StoryBranch
7
7
  module Github
8
8
  # GitHub Issue representation
9
9
  class Issue
10
- attr_accessor :title, :id
10
+ attr_accessor :title, :id, :html_url
11
11
 
12
12
  def initialize(blanket_story, repo)
13
13
  @repo = repo
@@ -15,9 +15,8 @@ module StoryBranch
15
15
  @title = blanket_story.title
16
16
  @id = blanket_story.number
17
17
  @labels = blanket_story.labels.map { |label| Label.new(label) }
18
- @milestone = if blanket_story.milestone
19
- Milestone.new(blanket_story.milestone)
20
- end
18
+ @milestone = Milestone.new(blanket_story.milestone) if blanket_story.milestone
19
+ @html_url = blanket_story.html_url
21
20
  end
22
21
 
23
22
  def update_state
@@ -5,6 +5,7 @@ module StoryBranch
5
5
  # Github Labels representation
6
6
  class Label
7
7
  attr_accessor :name, :color
8
+
8
9
  def initialize(label_data)
9
10
  @name = label_data.name
10
11
  @color = label_data.color
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'blanket'
4
- require 'story_branch/tracker_base'
4
+ require_relative '../tracker_base'
5
5
  require_relative './project'
6
6
 
7
7
  module StoryBranch
@@ -11,6 +11,7 @@ module StoryBranch
11
11
  API_URL = 'https://api.github.com/'
12
12
 
13
13
  def initialize(project_id:, api_key:, **)
14
+ super
14
15
  # NOTE: RepoName should follow owner/repo_name format
15
16
  @repo_name = project_id
16
17
  @api_key = api_key
@@ -4,7 +4,7 @@ module StoryBranch
4
4
  module Jira
5
5
  # Jira Issue representation
6
6
  class Issue
7
- attr_accessor :title, :id
7
+ attr_accessor :title, :id, :html_url
8
8
 
9
9
  # TODO: Add component and labels to the info of the issue
10
10
  def initialize(jira_issue, project)
@@ -12,6 +12,7 @@ module StoryBranch
12
12
  @story = jira_issue
13
13
  @title = jira_issue.summary
14
14
  @id = jira_issue.key
15
+ @html_url = transform_url(jira_issue.self)
15
16
  end
16
17
 
17
18
  def update_state
@@ -25,6 +26,12 @@ module StoryBranch
25
26
  def dashed_title
26
27
  StoryBranch::StringUtils.normalised_branch_name @title
27
28
  end
29
+
30
+ private
31
+
32
+ def transform_url(url)
33
+ url.gsub(%r{rest/api.*$}, "browse/#{@id}")
34
+ end
28
35
  end
29
36
  end
30
37
  end
@@ -16,7 +16,7 @@ module StoryBranch
16
16
  # Probably will need a specific query builder per tracker
17
17
  def stories(options = {})
18
18
  stories = if options[:id]
19
- [@project.issues.find(options[:id])]
19
+ [@project.client.Issue.find(options[:id])]
20
20
  else
21
21
  @project.client.Issue.jql(jql_query)
22
22
  end
@@ -5,22 +5,23 @@
5
5
  # my tracker and issues will still provide a similar api. This jira-ruby
6
6
  # is used to get the data.
7
7
  require 'jira-ruby'
8
- require 'story_branch/tracker_base'
8
+ require_relative '../tracker_base'
9
9
  require_relative './project'
10
10
 
11
11
  module StoryBranch
12
12
  module Jira
13
13
  # JIRA API wrapper for story branch tracker
14
14
  class Tracker < StoryBranch::TrackerBase
15
- # rubocop:disable Metrics/LineLength
16
15
  def initialize(tracker_domain:, project_id:, api_key:, username:, extra_query:)
16
+ super
17
+
17
18
  @tracker_url = "https://#{tracker_domain}.atlassian.net"
18
19
  @project_id = project_id
20
+ @issue_regex = Regexp.new("#{@project_id}-(\\d+)")
19
21
  @api_key = api_key
20
22
  @username = username
21
23
  @extra_query = extra_query
22
24
  end
23
- # rubocop:enable Metrics/LineLength
24
25
 
25
26
  def valid?
26
27
  [@api_key, @project_id, @username, @tracker_url].none?(&:nil?)
@@ -61,6 +62,8 @@ module StoryBranch
61
62
 
62
63
  jira_project = api.Project.find(@project_id)
63
64
  @project = Project.new(jira_project, @extra_query)
65
+ rescue JIRA::HTTPError => e
66
+ raise "failed to authenticate: #{e.inspect}"
64
67
  end
65
68
  end
66
69
  end