story_branch 0.7.0 → 2.0.1

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
  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