story_branch 1.0.0 → 2.2.0

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: 4196567f738d9eefe7e9b689bba4a082f3604d41c7e4b198f10295e3f867a0ba
4
- data.tar.gz: 4bd0f419c7fce7703c1b5df98d906137bfd6b3c53e400273c59caf8bea923d26
3
+ metadata.gz: 470bb59ffdc939bd91f9700a00f467ca2b68535d7a30740b95792cb6c43b37e3
4
+ data.tar.gz: 49ca86d91a3f963f4096b84a3192ebc9a8da547a6dc0bb44fc465c4ca5eb149b
5
5
  SHA512:
6
- metadata.gz: 60993c9099b5112018ea6949ad47901bc27349473296ba96590bed89b499d96eea9ad185623d66d16ba28216b71d8efcbbd91131e89cb51e17da370037416eca
7
- data.tar.gz: 0a5154411fdb3c53b5efc0e444af8383b9a197e241bb0ffbe0322c38ccf56d92ee5501e1f3b25026aa1b181b10c66736f9fce90fb25a1a3df1d0530defea7729
6
+ metadata.gz: 9627d3631e828b32bb5d064f0580d4b940c23dd6c19d809583be4d32e52298646978355316c009870c8d9fb05b8611137137374dfbb644c6554bb0d176f21c6a
7
+ data.tar.gz: cc087771f69a847b3822181c8156aec52515993aba41a4fb7c3af01f33961c8a32826eae0d242d931595cebf9c00c6a8f4301a8498e87bbeeb218bfcf69ef715
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,7 +25,12 @@ 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
30
34
 
31
35
  steps:
32
36
  - checkout
@@ -38,22 +42,12 @@ jobs:
38
42
  chmod +x ./cc-test-reporter
39
43
  - run: ./cc-test-reporter before-build
40
44
 
41
- - restore_cache:
42
- keys:
43
- - v2-dependencies-{{ checksum "Gemfile.lock" }}
44
- - v2-dependencies-
45
-
46
45
  - run:
47
46
  name: install dependencies
48
47
  command: |
49
48
  gem install bundler
50
49
  bundle install --jobs=4 --retry=3 --path vendor/bundle
51
50
 
52
- - save_cache:
53
- paths:
54
- - ./vendor/bundle
55
- key: v2-dependencies-{{ checksum "Gemfile.lock" }}
56
-
57
51
  - run:
58
52
  name: run tests
59
53
  command: |
@@ -81,26 +75,19 @@ jobs:
81
75
  ./cc-test-reporter after-build -t simplecov --exit-code $?
82
76
 
83
77
  publish:
84
- <<: *defaults
78
+ docker:
79
+ - image: circleci/ruby:3.0-buster
80
+ working_directory: ~/repo
81
+
85
82
  steps:
86
83
  - checkout
87
84
 
88
- - restore_cache:
89
- keys:
90
- - v2-dependencies-{{ checksum "Gemfile.lock" }}
91
- - v2-dependencies-
92
-
93
85
  - run:
94
86
  name: install dependencies
95
87
  command: |
96
88
  gem install bundler
97
89
  bundle install --jobs=4 --retry=3 --path vendor/bundle
98
90
 
99
- - save_cache:
100
- paths:
101
- - ./vendor/bundle
102
- key: v2-dependencies-{{ checksum "Gemfile.lock" }}
103
-
104
91
  - run:
105
92
  name: Setup Rubygems
106
93
  command: bash .circleci/setup-rubygems.sh
@@ -8,12 +8,10 @@ jobs:
8
8
  runs-on: ubuntu-latest
9
9
 
10
10
  steps:
11
- - uses: actions/checkout@v1
12
- - name: Set up Ruby 2.6
13
- uses: actions/setup-ruby@v1
14
- with:
15
- ruby-version: 2.6.x
11
+ - uses: actions/checkout@v3
12
+ - name: Set up Ruby 2.7
13
+ uses: ruby/setup-ruby@v1
16
14
  - name: Rubocop Linter
17
- uses: andrewmcodes/rubocop-linter-action@v0.1.2
15
+ uses: andrewmcodes/rubocop-linter-action@v3.3.0
18
16
  env:
19
17
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
data/.gitignore CHANGED
@@ -4,3 +4,4 @@ story_branch-*.gem
4
4
  .byebug_history
5
5
  coverage
6
6
  tools/release*.*
7
+ Gemfile.lock
data/.story_branch.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- finish_tag: 'Resolves'
3
- tracker: 'github'
2
+ finish_tag: Resolves
3
+ tracker: github
4
4
  project_id:
5
5
  - story-branch/story_branch
data/Changelog.md CHANGED
@@ -1,3 +1,16 @@
1
+ # 2.2.0
2
+
3
+ Wed Aug 11 07:37:00 2022 +0800
4
+
5
+ - Add support for linear.app (#127)
6
+ - Adds dependency on story branch's graphql client
7
+ - Update README to match closer to current gem behavior
8
+
9
+ # 2.1.0
10
+ Wed Jul 20 18:30:00 2022 +0800
11
+
12
+ - Add configuration support to prepend branch name with a user prefix (#122)
13
+
1
14
  # 0.3.3
2
15
  Tue Jun 26 15:18:37 2018 +0800
3
16
 
data/README.md CHANGED
@@ -2,6 +2,29 @@
2
2
  [![CircleCI](https://circleci.com/gh/story-branch/story_branch/tree/master.svg?style=svg)](https://circleci.com/gh/story-branch/story_branch/tree/master)
3
3
  [![Maintainability](https://api.codeclimate.com/v1/badges/7dbd75908417656853d7/maintainability)](https://codeclimate.com/github/story-branch/story_branch/maintainability)
4
4
 
5
+ # Table of Contents
6
+
7
+ * [Installing](#installing)
8
+ * [Usage](#usage)
9
+ * [Commands available](#commands-available)
10
+ * [Commentary](#commentary)
11
+ * [Configuration](#configuration)
12
+ * [Configuring PivotalTracker](#configuring-pivotaltracker)
13
+ * [Configuring Github](#configuring-github)
14
+ * [Configuring JIRA](#configuring-jira)
15
+ * [Configuring LinearApp](#configuring-linearapp)
16
+ * [Available settings](#available-settings)
17
+ * [Issue placement](#issue-placement)
18
+ * [Branch username](#branch-username)
19
+ * [Finish tag](#finish-tag)
20
+ * [Creating a new branch following the naming convention](#creating-a-new-branch-following-the-naming-convention)
21
+ * [PivotalTracker specific commands](#pivotaltracker-specific-commands)
22
+ * [Migrating](#migrating)
23
+ * [Old configuration](#old-configuration)
24
+ * [Old commands](#old-commands)
25
+ * [Contributing](#contributing)
26
+
27
+
5
28
  # Story Branch
6
29
 
7
30
  Story branch is a CLI application that interacts with Pivotal Tracker, Github and Jira
@@ -46,25 +69,97 @@ Commands:
46
69
  story_branch version # story_branch gem version
47
70
  ```
48
71
 
49
- ## Settings
72
+ ## Commentary
73
+
74
+ `story_branch configure`: Step by step configuration of a new tracker for your project
75
+
76
+ ### Configuration
77
+
78
+ The configuration is split into two different files: a `.story_branch.yml` in the root folder
79
+ of the project where you're configuring the tool and a `.story_branch.yml` in user's home directory.
80
+
81
+ For the management of the home directory, story_branch relies on [XDG](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
82
+ specification, so if configured, it'll be installed under `~/.config` or whatever your machine
83
+ specifies.
84
+
85
+ The idea behind the two files is that the one in the root of the project should be committed to your
86
+ repository and defines basic tracker configuration settings to be shared across the contributors
87
+ to your repository. These configuration settings include the tracker type, project id in the tracker,
88
+ where you want the ticket number to be placed amongst others.
89
+
90
+ The file under your config directory is meant to be stored only locally as it will contain the api
91
+ keys needed for story branch to access your tracker. The story_branch file under your config directory
92
+ should not be published anywhere.
50
93
 
51
- Story branch has a command available that will help you creating the configurations
52
- for the projects, but essentially you'll be asked for the pivotal tracker project id and your api key.
94
+ #### Configuring PivotalTracker
95
+
96
+ When running the command `story_branch configure` you'll be asked 3 things:
97
+ 1. tracker - You should select Pivotal Tracker
98
+ 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`
99
+ 3. api key - this is your personal api key. You can get that from [your profile page](https://www.pivotaltracker.com/profile)
100
+
101
+ #### Configuring Github
102
+
103
+ When running the command `story_branch configure` you'll be asked 3 things:
104
+ 1. tracker - You should select Github
105
+ 2. project id - This is the github repository name in the format `<owner>/<repo_name>`. E.g. `story-branch/story_branch`.
106
+ 3. api key - this is your personal api token. You can create one under your [developer profile tokens page](https://github.com/settings/tokens)
107
+
108
+ #### Configuring JIRA
109
+
110
+ The configuration for JIRA is slightly more complex as the endpoint changes according
111
+ to your project setup. You will need an API token, which you can create a new one in your [JIRA id management page](https://id.atlassian.com/manage/api-tokens)
112
+ 1. tracker - You should select JIRA
113
+ 2. JIRA's subdomain - you should type the JIRA's subdomain that you use to access in your browser. E.g I'd type perxtechnologies to access to <https://perxtechnologies.atlassian.net>
114
+ 3. JIRA's project key - this should match which project you want to fetch the issues from. E.g. PW is the key for my Project Whistler, so I'd type PW
115
+ 4. API key that you should have gotten in the first description step
116
+ 5. username used for login in the JIRA usually. If you use google email authentication, the username should be your email
117
+
118
+ #### Configuring LinearApp
119
+
120
+ When running the command `story_branch configure` you'll be asked 3 things:
121
+ 1. tracker - You should select LinearApp
122
+ 2. project id - This should be your team's id.
123
+ 3. api key - this is your personal api token. You can create one under your [account API settings](https://linear.app/settings/api)
124
+
125
+ #### Available settings
126
+
127
+ ##### Issue placement
128
+
129
+ On your local config you can add a line with `issue_placement: <Beginning|End>`.
130
+ Based on this configuration, when running `story_branch create`, the ticket id will be
131
+ used as prefix or suffix on the branch name.
132
+
133
+ E.g.
134
+ `issue_placement: Beginning`
53
135
 
54
- ### Configuring the project id
136
+ `story_branch create` will create a branch in the format: `<issue_number>-<issue_title>`
55
137
 
56
- The project id you can get it easily from the url when viewing the project.
57
- This value will be stored in the local configuration file that will be committed
58
- to the working repository
138
+ While
59
139
 
60
- ### Configuring the api key
140
+ `issue_placement: End`
61
141
 
62
- The api key you can get it from your account settings.
63
- This value will be stored in your global configuration file that typically is
64
- not shared with your co-workers in the repository. This way, each user will
65
- be properly identified in the tracker
142
+ `story_branch create` will create a branch in the format: `<issue_title>-<issue_number>`
66
143
 
67
- ### Configuring the finish tag
144
+ ##### Branch username
145
+
146
+ In some cases your workflow requires you to have an identifier prefixing the branch name.
147
+ You can configure that by setting the configuration `branch_username` under your project's
148
+ name in the global `story_branch.yml` file (`defaults to: ~/.config/.story_branch.yml`)
149
+
150
+ E.g.
151
+
152
+ ```
153
+ story-branch/story_branch:
154
+ api_key: my_fantastic_api_key
155
+ branch_username: rui
156
+ ```
157
+
158
+ Doing so, when running `story_branch create`, it will create a branch in the format: `rui/<issue_number>-<issue_title>`
159
+
160
+ Naturally, the issue number will be placed based on the issue placement setting
161
+
162
+ ##### Finish tag
68
163
 
69
164
  On your local config you can add a line with `finish_tag: <Some random word>`.
70
165
  This tag will be used in the commit message when running `story_branch finish`.
@@ -75,28 +170,11 @@ E.g.
75
170
  `story_branch finish` will make a commit with the message
76
171
  `[Resolves #12313] story title`
77
172
 
173
+ ### Creating a new branch following the naming convention
78
174
 
79
- ### .story_branch files
80
-
81
- When configuring story branch, it will create two .story_branch.yml files: one in
82
- your home folder (`~/`) and one in your project's root (`./`).
83
- The one in your home folder will be used to store the different project's configurations
84
- such as which api key to use. This is done so you don't need to commit your
85
- api key to the repository but still be able to use different keys in case you
86
- have different accounts.
87
-
88
- The one in your project root will keep a reference to the project configuration.
89
- For now, this reference is the project id. This file can be safely committed to
90
- the repository and shared amongst your co-workers.
91
-
92
- ## Commentary
93
-
94
- `story_branch create`: Creates a git branch with automatic reference to a
95
- Pivotal Tracker Story. It will get started stories from your active
96
- project. You can enter text and press TAB to search for a story
97
- name, or TAB to show the full list. It will then suggest an editable
98
- branch name. When the branch is created the `story_id` will
99
- be appended to it.
175
+ `story_branch create`: Creates a git branch with automatic reference to a tracker ticket.
176
+ The tickets/stories that will be fetched will depend on the project type. Once you choose the
177
+ ticket to work on, a new branch will be created based on the ticket title and id.
100
178
 
101
179
  e.g. `my-story-name-1234567`
102
180
 
@@ -107,6 +185,8 @@ e.g: `[Finishes #1234567] My story name`
107
185
  You must stage all changes (or stash them) first. Note the commit will not
108
186
  be pushed. Note: You'll be able to bail out of the commit.
109
187
 
188
+ ### PivotalTracker specific commands
189
+
110
190
  `story_branch start`: Start a story in Pivotal Tracker from the terminal.
111
191
  It'll get all un-started stories in your current project. You can
112
192
  enter text and press TAB to search for a story name, or TAB to show
@@ -117,31 +197,6 @@ It'll get all started stories in your current project. You can
117
197
  enter text and press TAB to search for a story name, or TAB to show
118
198
  the full list.
119
199
 
120
- ## Configuring PivotalTracker
121
-
122
- When running the command `story_branch configure` you'll be asked 3 things:
123
- 1. tracker - You should select Pivotal Tracker
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`
125
- 3. api key - this is your personal api key. You can get that from [your profile page](https://www.pivotaltracker.com/profile)
126
-
127
- ## Configuring Github
128
-
129
- When running the command `story_branch configure` you'll be asked 3 things:
130
- 1. project id - This is the github repository name in the format `<owner>/<repo_name>`. E.g. `story-branch/story_branch`.
131
- 2. tracker - You should select Github
132
- 3. api key - this is your personal api token. You can create one under your
133
- [developer profile tokens page](https://github.com/settings/tokens)
134
-
135
- ## Configuring JIRA
136
-
137
- The configuration for JIRA is slightly more complex as the endpoint changes according
138
- to your project setup. You will need an API token, which you can create a new one in your [JIRA id management page](https://id.atlassian.com/manage/api-tokens)
139
- 1. tracker - You should select JIRA
140
- 2. JIRA's subdomain - you should type the JIRA's subdomain that you use to access in your browser. E.g I'd type perxtechnologies to access to https://perxtechnologies.atlassian.net
141
- 3. JIRA's project key - this should match which project you want to fetch the issues from. E.g. PW is the key for my Project Whistler, so I'd type PW
142
- 4. API key that you should have gotten in the first description step
143
- 5. username used for login in the JIRA usually. If you use google email authentication, the username should be your email
144
-
145
200
  ## Migrating
146
201
 
147
202
  ### Old configuration
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../config_manager'
4
4
  require_relative '../command'
5
+ require_relative '../constants'
5
6
  require 'tty-config'
6
7
  require 'tty-prompt'
7
8
 
@@ -14,6 +15,7 @@ module StoryBranch
14
15
  # and then add the project id specified by the user.
15
16
  class Configure < StoryBranch::Command
16
17
  def initialize(_options)
18
+ super()
17
19
  @new_config = ConfigManager.new
18
20
  end
19
21
 
@@ -72,12 +74,7 @@ module StoryBranch
72
74
  def tracker
73
75
  return @tracker if @tracker
74
76
 
75
- trackers = {
76
- 'Pivotal Tracker' => 'pivotal-tracker',
77
- 'Github' => 'github',
78
- 'JIRA' => 'jira'
79
- }
80
- @tracker = prompt.select('Which tracker are you using?', trackers)
77
+ @tracker = prompt.select('Which tracker are you using?', StoryBranch::AVAILABLE_TRACKERS)
81
78
  end
82
79
  end
83
80
  end
@@ -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
 
@@ -7,6 +7,7 @@ module StoryBranch
7
7
  # OpenIssue command is used to open the associated ticket in the browser
8
8
  class OpenIssue < 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 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
 
@@ -34,6 +34,10 @@ module StoryBranch
34
34
  @issue_placement ||= @config.fetch(:issue_placement, default: 'End')
35
35
  end
36
36
 
37
+ def branch_username
38
+ @branch_username ||= @config.fetch(project_key, :branch_username)
39
+ end
40
+
37
41
  def finish_tag
38
42
  @finish_tag ||= @config.fetch(project_key,
39
43
  :finish_tag, default: 'Finishes')
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StoryBranch
4
+ AVAILABLE_TRACKERS = {
5
+ 'Pivotal Tracker' => 'pivotal-tracker',
6
+ 'Github' => 'github',
7
+ 'JIRA' => 'jira',
8
+ 'LinearApp' => 'linearapp'
9
+ }.freeze
10
+
11
+ TRACKERS_CLASSES = {
12
+ 'pivotal-tracker' => 'StoryBranch::Pivotal::Tracker',
13
+ 'github' => 'StoryBranch::Github::Tracker',
14
+ 'jira' => 'StoryBranch::Jira::Tracker',
15
+ 'linearapp' => 'StoryBranch::LinearApp::Tracker'
16
+ }.freeze
17
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StoryBranch
4
+ # Base class to represent an issue/ticket
5
+ class IssueBase
6
+ attr_reader :title, :id, :html_url
7
+
8
+ def initialize(tracker_issue, project = nil)
9
+ @project = project
10
+ @story = tracker_issue
11
+ end
12
+
13
+ def to_s
14
+ "#{@id} - #{@title}"
15
+ end
16
+
17
+ def dashed_title
18
+ StoryBranch::StringUtils.normalised_branch_name @title
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../issue_base'
4
+
5
+ module StoryBranch
6
+ module LinearApp
7
+ # LinearApp Issue representation
8
+ class Issue < StoryBranch::IssueBase
9
+ # NOTE: project here represents the team_id only
10
+ def initialize(tracker_issue, project)
11
+ super
12
+ @title = tracker_issue['title']
13
+ @id = "#{@project}-#{tracker_issue['number']}"
14
+ @html_url = tracker_issue['url']
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'issue'
4
+
5
+ module StoryBranch
6
+ module LinearApp
7
+ # LinearApp groups tickets in teams, so this is the team representation in
8
+ # story branch. It's equivalent to a project
9
+ class Team
10
+ def initialize(team_id, client)
11
+ @team_id = team_id
12
+ @client = client
13
+ end
14
+
15
+ def stories(_options = {})
16
+ response = @client.get(graphql_query: graphql_query)
17
+ stories_json = response.data['viewer']['assignedIssues']['nodes']
18
+ stories_json.map { |story| Issue.new(story, @team_id) }
19
+ rescue StoryBranch::Graphql::Error => e
20
+ raise "Error while querying for tickets:\n#{e.message}"
21
+ end
22
+
23
+ private
24
+
25
+ def graphql_query # rubocop:disable Metrics/MethodLength
26
+ %(
27
+ query Issue {
28
+ viewer {
29
+ assignedIssues (filter: { team: { name: { eq: "#{@team_id}"} } }) {
30
+ nodes {
31
+ id
32
+ title
33
+ description
34
+ number
35
+ url
36
+ }
37
+ }
38
+ }
39
+ }
40
+ )
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'story_branch/graphql'
4
+ require_relative '../tracker_base'
5
+ require_relative 'team'
6
+
7
+ module StoryBranch
8
+ module LinearApp
9
+ # Linear App API wrapper for story branch tracker
10
+ class Tracker < StoryBranch::TrackerBase
11
+ API_URL = 'https://api.linear.app/'
12
+
13
+ def initialize(project_id:, api_key:, **)
14
+ super
15
+
16
+ # NOTE: project should be the representation of linear app team
17
+ @team_id = project_id
18
+ @api_key = api_key
19
+ end
20
+
21
+ def valid?
22
+ !@api_key.nil? && !@team_id.nil?
23
+ end
24
+
25
+ # TODO: This should probably be renamed to something more meaningful
26
+ # in the sense that it should be workable stories/issues
27
+ # which depend on the tracker's workflow. PivotalTracker they need to
28
+ # be started and estimated, while for Github they just need to be open
29
+ def stories
30
+ project.stories
31
+ end
32
+
33
+ def get_story_by_id(story_id)
34
+ project.stories(id: story_id).first
35
+ end
36
+
37
+ def client
38
+ @client ||= StoryBranch::Graphql::Client.new(api_url: API_URL, api_key: @api_key)
39
+ end
40
+
41
+ private
42
+
43
+ def configure_api
44
+ client
45
+ end
46
+
47
+ def project
48
+ return @project if @project
49
+ raise 'team must be set' unless @team_id
50
+
51
+ @project = Team.new(@team_id, client)
52
+ end
53
+ end
54
+ end
55
+ end