story_branch 2.1.0 → 2.3.0
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 +4 -4
- data/.circleci/config.yml +4 -3
- data/.gitignore +0 -1
- data/Changelog.md +22 -0
- data/Gemfile.lock +162 -0
- data/README.md +115 -61
- data/lib/story_branch/commands/configure.rb +2 -6
- data/lib/story_branch/config_manager.rb +12 -3
- data/lib/story_branch/constants.rb +17 -0
- data/lib/story_branch/git_utils.rb +4 -4
- data/lib/story_branch/issue_base.rb +21 -0
- data/lib/story_branch/linear_app/issue.rb +18 -0
- data/lib/story_branch/linear_app/team.rb +44 -0
- data/lib/story_branch/linear_app/tracker.rb +56 -0
- data/lib/story_branch/main.rb +7 -22
- data/lib/story_branch/tracker_initializer.rb +27 -0
- data/lib/story_branch/version.rb +1 -1
- data/story_branch.gemspec +4 -1
- data/tools/prep_changelog.rb +3 -3
- metadata +66 -18
- data/lib/story_branch/git_wrapper.rb +0 -108
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c822a7c84f60daf75722fad9e100028aa8bec4e28b6f0a811135c511975c756
|
4
|
+
data.tar.gz: b44a6fe6aa0a18f9bae8ff0c240f99637fea1c2b519bdc645449b867529f253d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06c7c3802616972f40da61237b8f7f44bac809ec8b77f19ecddd700fef1b65c7551db9fe0cb31bc8e17935ad8b87d086828ce7fd398d50c02d7eac73f7ab9f70
|
7
|
+
data.tar.gz: 9c59ac43012d9bf73d680b5736897b2c6b7fea6d6c196f801c7df2718adb82aa81c719a28b1b9ba2b8658de2df512a89a920acc3cb402984fd8259c34a93efea
|
data/.circleci/config.yml
CHANGED
@@ -7,7 +7,7 @@ workflows:
|
|
7
7
|
- test:
|
8
8
|
matrix:
|
9
9
|
parameters:
|
10
|
-
ruby_version: ["ruby:2.6
|
10
|
+
ruby_version: ["ruby:2.6", "ruby:2.7", "ruby:3.0"]
|
11
11
|
|
12
12
|
filters:
|
13
13
|
tags:
|
@@ -29,7 +29,7 @@ jobs:
|
|
29
29
|
ruby_version:
|
30
30
|
type: string
|
31
31
|
docker:
|
32
|
-
- image:
|
32
|
+
- image: cimg/<< parameters.ruby_version >>
|
33
33
|
working_directory: ~/repo
|
34
34
|
|
35
35
|
steps:
|
@@ -45,6 +45,7 @@ jobs:
|
|
45
45
|
- run:
|
46
46
|
name: install dependencies
|
47
47
|
command: |
|
48
|
+
rm Gemfile.lock
|
48
49
|
gem install bundler
|
49
50
|
bundle install --jobs=4 --retry=3 --path vendor/bundle
|
50
51
|
|
@@ -76,7 +77,7 @@ jobs:
|
|
76
77
|
|
77
78
|
publish:
|
78
79
|
docker:
|
79
|
-
- image:
|
80
|
+
- image: cimg/ruby:3.0
|
80
81
|
working_directory: ~/repo
|
81
82
|
|
82
83
|
steps:
|
data/.gitignore
CHANGED
data/Changelog.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
# 2.3.0
|
2
|
+
|
3
|
+
Mon Aug 22 23:55:00 2022 +0800
|
4
|
+
|
5
|
+
- Moved Git::Wrapper to separate gem
|
6
|
+
- Try to read local file from both current path and git root's directory (#136)
|
7
|
+
|
8
|
+
# 2.2.1
|
9
|
+
|
10
|
+
Mon Aug 15 17:36:00 2022 +0800
|
11
|
+
|
12
|
+
- Fixed broken command story_branch open when using linear.app (#126)
|
13
|
+
- Fixed linear.app graphql query to filter team by key instead of name (#130)
|
14
|
+
|
15
|
+
# 2.2.0
|
16
|
+
|
17
|
+
Wed Aug 11 07:37:00 2022 +0800
|
18
|
+
|
19
|
+
- Add support for linear.app (#127)
|
20
|
+
- Adds dependency on story branch's graphql client
|
21
|
+
- Update README to match closer to current gem behavior
|
22
|
+
|
1
23
|
# 2.1.0
|
2
24
|
Wed Jul 20 18:30:00 2022 +0800
|
3
25
|
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
story_branch (2.3.0)
|
5
|
+
blanket_wrapper (~> 3.0, > 3.0)
|
6
|
+
damerau-levenshtein (~> 1.3, > 1.3)
|
7
|
+
httparty (> 0)
|
8
|
+
jira-ruby (> 1.7, < 3)
|
9
|
+
story_branch-git_wrapper (~> 0.0.3)
|
10
|
+
story_branch-graphql (~> 0.0.2)
|
11
|
+
thor (> 0.20, < 2)
|
12
|
+
tty-command (~> 0.8, > 0.8)
|
13
|
+
tty-config (~> 0.2, > 0.2)
|
14
|
+
tty-pager (~> 0.12, > 0.12)
|
15
|
+
tty-prompt (~> 0.18, > 0.18)
|
16
|
+
xdg (> 3.0, < 6)
|
17
|
+
|
18
|
+
GEM
|
19
|
+
remote: https://rubygems.org/
|
20
|
+
specs:
|
21
|
+
activesupport (7.0.3.1)
|
22
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
23
|
+
i18n (>= 1.6, < 2)
|
24
|
+
minitest (>= 5.1)
|
25
|
+
tzinfo (~> 2.0)
|
26
|
+
addressable (2.8.1)
|
27
|
+
public_suffix (>= 2.0.2, < 6.0)
|
28
|
+
ast (2.4.2)
|
29
|
+
atlassian-jwt (0.2.1)
|
30
|
+
jwt (~> 2.1)
|
31
|
+
blanket_wrapper (3.0.2)
|
32
|
+
httparty
|
33
|
+
recursive-open-struct
|
34
|
+
coderay (1.1.3)
|
35
|
+
concurrent-ruby (1.1.10)
|
36
|
+
damerau-levenshtein (1.3.3)
|
37
|
+
diff-lcs (1.5.0)
|
38
|
+
docile (1.4.0)
|
39
|
+
fakefs (1.8.0)
|
40
|
+
git (1.12.0)
|
41
|
+
addressable (~> 2.8)
|
42
|
+
rchardet (~> 1.8)
|
43
|
+
httparty (0.20.0)
|
44
|
+
mime-types (~> 3.0)
|
45
|
+
multi_xml (>= 0.5.2)
|
46
|
+
i18n (1.12.0)
|
47
|
+
concurrent-ruby (~> 1.0)
|
48
|
+
jira-ruby (2.2.0)
|
49
|
+
activesupport
|
50
|
+
atlassian-jwt
|
51
|
+
multipart-post
|
52
|
+
oauth (~> 0.5, >= 0.5.0)
|
53
|
+
json (2.6.2)
|
54
|
+
jwt (2.4.1)
|
55
|
+
method_source (1.0.0)
|
56
|
+
mime-types (3.4.1)
|
57
|
+
mime-types-data (~> 3.2015)
|
58
|
+
mime-types-data (3.2022.0105)
|
59
|
+
minitest (5.16.3)
|
60
|
+
multi_xml (0.6.0)
|
61
|
+
multipart-post (2.2.3)
|
62
|
+
oauth (0.5.10)
|
63
|
+
ostruct (0.5.5)
|
64
|
+
parallel (1.22.1)
|
65
|
+
parser (3.1.2.1)
|
66
|
+
ast (~> 2.4.1)
|
67
|
+
pastel (0.8.0)
|
68
|
+
tty-color (~> 0.5)
|
69
|
+
pry (0.14.1)
|
70
|
+
coderay (~> 1.1)
|
71
|
+
method_source (~> 1.0)
|
72
|
+
public_suffix (5.0.0)
|
73
|
+
rainbow (3.1.1)
|
74
|
+
rake (13.0.6)
|
75
|
+
rchardet (1.8.0)
|
76
|
+
recursive-open-struct (1.1.3)
|
77
|
+
regexp_parser (2.5.0)
|
78
|
+
rexml (3.2.5)
|
79
|
+
rspec (3.11.0)
|
80
|
+
rspec-core (~> 3.11.0)
|
81
|
+
rspec-expectations (~> 3.11.0)
|
82
|
+
rspec-mocks (~> 3.11.0)
|
83
|
+
rspec-core (3.11.0)
|
84
|
+
rspec-support (~> 3.11.0)
|
85
|
+
rspec-expectations (3.11.0)
|
86
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
87
|
+
rspec-support (~> 3.11.0)
|
88
|
+
rspec-mocks (3.11.1)
|
89
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
90
|
+
rspec-support (~> 3.11.0)
|
91
|
+
rspec-support (3.11.0)
|
92
|
+
rspec_junit_formatter (0.5.1)
|
93
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
94
|
+
rubocop (1.35.1)
|
95
|
+
json (~> 2.3)
|
96
|
+
parallel (~> 1.10)
|
97
|
+
parser (>= 3.1.2.1)
|
98
|
+
rainbow (>= 2.2.2, < 4.0)
|
99
|
+
regexp_parser (>= 1.8, < 3.0)
|
100
|
+
rexml (>= 3.2.5, < 4.0)
|
101
|
+
rubocop-ast (>= 1.20.1, < 2.0)
|
102
|
+
ruby-progressbar (~> 1.7)
|
103
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
104
|
+
rubocop-ast (1.21.0)
|
105
|
+
parser (>= 3.1.1.0)
|
106
|
+
ruby-progressbar (1.11.0)
|
107
|
+
simplecov (0.21.2)
|
108
|
+
docile (~> 1.1)
|
109
|
+
simplecov-html (~> 0.11)
|
110
|
+
simplecov_json_formatter (~> 0.1)
|
111
|
+
simplecov-html (0.12.3)
|
112
|
+
simplecov_json_formatter (0.1.4)
|
113
|
+
story_branch-git_wrapper (0.0.3)
|
114
|
+
story_branch-graphql (0.0.2)
|
115
|
+
httparty (> 0)
|
116
|
+
strings (0.2.1)
|
117
|
+
strings-ansi (~> 0.2)
|
118
|
+
unicode-display_width (>= 1.5, < 3.0)
|
119
|
+
unicode_utils (~> 1.4)
|
120
|
+
strings-ansi (0.2.0)
|
121
|
+
thor (1.2.1)
|
122
|
+
tty-color (0.6.0)
|
123
|
+
tty-command (0.10.1)
|
124
|
+
pastel (~> 0.8)
|
125
|
+
tty-config (0.6.0)
|
126
|
+
tty-cursor (0.7.1)
|
127
|
+
tty-pager (0.14.0)
|
128
|
+
strings (~> 0.2.0)
|
129
|
+
tty-screen (~> 0.8)
|
130
|
+
tty-prompt (0.23.1)
|
131
|
+
pastel (~> 0.8)
|
132
|
+
tty-reader (~> 0.8)
|
133
|
+
tty-reader (0.9.0)
|
134
|
+
tty-cursor (~> 0.7)
|
135
|
+
tty-screen (~> 0.8)
|
136
|
+
wisper (~> 2.0)
|
137
|
+
tty-screen (0.8.1)
|
138
|
+
tzinfo (2.0.5)
|
139
|
+
concurrent-ruby (~> 1.0)
|
140
|
+
unicode-display_width (2.2.0)
|
141
|
+
unicode_utils (1.4.0)
|
142
|
+
wisper (2.0.1)
|
143
|
+
xdg (4.5.0)
|
144
|
+
|
145
|
+
PLATFORMS
|
146
|
+
ruby
|
147
|
+
|
148
|
+
DEPENDENCIES
|
149
|
+
bundler (~> 2.1, > 2.1)
|
150
|
+
fakefs (> 0.14, < 2)
|
151
|
+
git (~> 1.5, > 1.5)
|
152
|
+
ostruct (~> 0.1, > 0.1)
|
153
|
+
pry (~> 0.11, > 0.11)
|
154
|
+
rake (>= 12.3.3, < 14)
|
155
|
+
rspec (~> 3, > 3)
|
156
|
+
rspec_junit_formatter (~> 0.4, > 0.4)
|
157
|
+
rubocop (~> 1.22)
|
158
|
+
simplecov (~> 0.16, > 0.16)
|
159
|
+
story_branch!
|
160
|
+
|
161
|
+
BUNDLED WITH
|
162
|
+
2.1.4
|
data/README.md
CHANGED
@@ -2,10 +2,32 @@
|
|
2
2
|
[](https://circleci.com/gh/story-branch/story_branch/tree/master)
|
3
3
|
[](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
|
-
Story branch is a CLI application that interacts with Pivotal Tracker, Github and
|
8
|
-
at the moment.
|
30
|
+
Story branch is a CLI application that interacts with Pivotal Tracker, Github, Jira and LinearApp.
|
9
31
|
|
10
32
|
For all the trackers it supports creating local branches from the tickets or
|
11
33
|
opening the ticket in your browser from the branch you're working on. In the future
|
@@ -46,25 +68,97 @@ Commands:
|
|
46
68
|
story_branch version # story_branch gem version
|
47
69
|
```
|
48
70
|
|
49
|
-
##
|
71
|
+
## Commentary
|
72
|
+
|
73
|
+
`story_branch configure`: Step by step configuration of a new tracker for your project
|
74
|
+
|
75
|
+
### Configuration
|
76
|
+
|
77
|
+
The configuration is split into two different files: a `.story_branch.yml` in the root folder
|
78
|
+
of the project where you're configuring the tool and a `.story_branch.yml` in user's home directory.
|
79
|
+
|
80
|
+
For the management of the home directory, story_branch relies on [XDG](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
|
81
|
+
specification, so if configured, it'll be installed under `~/.config` or whatever your machine
|
82
|
+
specifies.
|
83
|
+
|
84
|
+
The idea behind the two files is that the one in the root of the project should be committed to your
|
85
|
+
repository and defines basic tracker configuration settings to be shared across the contributors
|
86
|
+
to your repository. These configuration settings include the tracker type, project id in the tracker,
|
87
|
+
where you want the ticket number to be placed amongst others.
|
88
|
+
|
89
|
+
The file under your config directory is meant to be stored only locally as it will contain the api
|
90
|
+
keys needed for story branch to access your tracker. The story_branch file under your config directory
|
91
|
+
should not be published anywhere.
|
50
92
|
|
51
|
-
|
52
|
-
|
93
|
+
#### Configuring PivotalTracker
|
94
|
+
|
95
|
+
When running the command `story_branch configure` you'll be asked 3 things:
|
96
|
+
1. tracker - You should select Pivotal Tracker
|
97
|
+
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`
|
98
|
+
3. api key - this is your personal api key. You can get that from [your profile page](https://www.pivotaltracker.com/profile)
|
99
|
+
|
100
|
+
#### Configuring Github
|
101
|
+
|
102
|
+
When running the command `story_branch configure` you'll be asked 3 things:
|
103
|
+
1. tracker - You should select Github
|
104
|
+
2. project id - This is the github repository name in the format `<owner>/<repo_name>`. E.g. `story-branch/story_branch`.
|
105
|
+
3. api key - this is your personal api token. You can create one under your [developer profile tokens page](https://github.com/settings/tokens)
|
106
|
+
|
107
|
+
#### Configuring JIRA
|
108
|
+
|
109
|
+
The configuration for JIRA is slightly more complex as the endpoint changes according
|
110
|
+
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)
|
111
|
+
1. tracker - You should select JIRA
|
112
|
+
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>
|
113
|
+
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
|
114
|
+
4. API key that you should have gotten in the first description step
|
115
|
+
5. username used for login in the JIRA usually. If you use google email authentication, the username should be your email
|
116
|
+
|
117
|
+
#### Configuring LinearApp
|
118
|
+
|
119
|
+
When running the command `story_branch configure` you'll be asked 3 things:
|
120
|
+
1. tracker - You should select LinearApp
|
121
|
+
2. project id - This should be your team's id.
|
122
|
+
3. api key - this is your personal api token. You can create one under your [account API settings](https://linear.app/settings/api)
|
123
|
+
|
124
|
+
#### Available settings
|
125
|
+
|
126
|
+
##### Issue placement
|
127
|
+
|
128
|
+
On your local config you can add a line with `issue_placement: <Beginning|End>`.
|
129
|
+
Based on this configuration, when running `story_branch create`, the ticket id will be
|
130
|
+
used as prefix or suffix on the branch name.
|
131
|
+
|
132
|
+
E.g.
|
133
|
+
`issue_placement: Beginning`
|
53
134
|
|
54
|
-
|
135
|
+
`story_branch create` will create a branch in the format: `<issue_number>-<issue_title>`
|
55
136
|
|
56
|
-
|
57
|
-
This value will be stored in the local configuration file that will be committed
|
58
|
-
to the working repository
|
137
|
+
While
|
59
138
|
|
60
|
-
|
139
|
+
`issue_placement: End`
|
61
140
|
|
62
|
-
|
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
|
141
|
+
`story_branch create` will create a branch in the format: `<issue_title>-<issue_number>`
|
66
142
|
|
67
|
-
|
143
|
+
##### Branch username
|
144
|
+
|
145
|
+
In some cases your workflow requires you to have an identifier prefixing the branch name.
|
146
|
+
You can configure that by setting the configuration `branch_username` under your project's
|
147
|
+
name in the global `story_branch.yml` file (`defaults to: ~/.config/.story_branch.yml`)
|
148
|
+
|
149
|
+
E.g.
|
150
|
+
|
151
|
+
```
|
152
|
+
story-branch/story_branch:
|
153
|
+
api_key: my_fantastic_api_key
|
154
|
+
branch_username: rui
|
155
|
+
```
|
156
|
+
|
157
|
+
Doing so, when running `story_branch create`, it will create a branch in the format: `rui/<issue_number>-<issue_title>`
|
158
|
+
|
159
|
+
Naturally, the issue number will be placed based on the issue placement setting
|
160
|
+
|
161
|
+
##### Finish tag
|
68
162
|
|
69
163
|
On your local config you can add a line with `finish_tag: <Some random word>`.
|
70
164
|
This tag will be used in the commit message when running `story_branch finish`.
|
@@ -75,28 +169,11 @@ E.g.
|
|
75
169
|
`story_branch finish` will make a commit with the message
|
76
170
|
`[Resolves #12313] story title`
|
77
171
|
|
172
|
+
### Creating a new branch following the naming convention
|
78
173
|
|
79
|
-
|
80
|
-
|
81
|
-
|
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.
|
174
|
+
`story_branch create`: Creates a git branch with automatic reference to a tracker ticket.
|
175
|
+
The tickets/stories that will be fetched will depend on the project type. Once you choose the
|
176
|
+
ticket to work on, a new branch will be created based on the ticket title and id.
|
100
177
|
|
101
178
|
e.g. `my-story-name-1234567`
|
102
179
|
|
@@ -107,6 +184,8 @@ e.g: `[Finishes #1234567] My story name`
|
|
107
184
|
You must stage all changes (or stash them) first. Note the commit will not
|
108
185
|
be pushed. Note: You'll be able to bail out of the commit.
|
109
186
|
|
187
|
+
### PivotalTracker specific commands
|
188
|
+
|
110
189
|
`story_branch start`: Start a story in Pivotal Tracker from the terminal.
|
111
190
|
It'll get all un-started stories in your current project. You can
|
112
191
|
enter text and press TAB to search for a story name, or TAB to show
|
@@ -117,31 +196,6 @@ It'll get all started stories in your current project. You can
|
|
117
196
|
enter text and press TAB to search for a story name, or TAB to show
|
118
197
|
the full list.
|
119
198
|
|
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
199
|
## Migrating
|
146
200
|
|
147
201
|
### 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
|
|
@@ -73,12 +74,7 @@ module StoryBranch
|
|
73
74
|
def tracker
|
74
75
|
return @tracker if @tracker
|
75
76
|
|
76
|
-
|
77
|
-
'Pivotal Tracker' => 'pivotal-tracker',
|
78
|
-
'Github' => 'github',
|
79
|
-
'JIRA' => 'jira'
|
80
|
-
}
|
81
|
-
@tracker = prompt.select('Which tracker are you using?', trackers)
|
77
|
+
@tracker = prompt.select('Which tracker are you using?', StoryBranch::AVAILABLE_TRACKERS)
|
82
78
|
end
|
83
79
|
end
|
84
80
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'tty-config'
|
4
4
|
require 'tty-prompt'
|
5
5
|
require 'xdg'
|
6
|
+
require 'story_branch/git'
|
6
7
|
|
7
8
|
module StoryBranch
|
8
9
|
# Config manager is used to manage all possible configuration settings
|
@@ -141,7 +142,7 @@ module StoryBranch
|
|
141
142
|
end
|
142
143
|
|
143
144
|
def load_configs
|
144
|
-
@local =
|
145
|
+
@local = local_config
|
145
146
|
xdg_conf = XDG::Config.new
|
146
147
|
home_path = if conf_exist?(Dir.home)
|
147
148
|
Dir.home
|
@@ -151,6 +152,11 @@ module StoryBranch
|
|
151
152
|
@global = read_config(home_path)
|
152
153
|
end
|
153
154
|
|
155
|
+
def local_config
|
156
|
+
possible_local_paths = [Dir.pwd, StoryBranch::Git::Wrapper.command('rev-parse --show-toplevel')].uniq
|
157
|
+
read_config(possible_local_paths)
|
158
|
+
end
|
159
|
+
|
154
160
|
def read_config(path)
|
155
161
|
config = init_config(path)
|
156
162
|
config.read if config.persisted?
|
@@ -162,10 +168,13 @@ module StoryBranch
|
|
162
168
|
config.persisted?
|
163
169
|
end
|
164
170
|
|
165
|
-
def init_config(
|
171
|
+
def init_config(paths)
|
172
|
+
paths = Array(paths)
|
166
173
|
config = ::TTY::Config.new
|
167
174
|
config.filename = CONFIG_FILENAME
|
168
|
-
|
175
|
+
paths.each do |path|
|
176
|
+
config.append_path path
|
177
|
+
end
|
169
178
|
config
|
170
179
|
end
|
171
180
|
end
|
@@ -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
|
@@ -1,14 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'damerau-levenshtein'
|
4
|
-
|
4
|
+
require 'story_branch/git/wrapper'
|
5
5
|
|
6
6
|
module StoryBranch
|
7
7
|
# Class used to interact with git. It relies on git gem as the wrapper
|
8
8
|
# and levenshtein algo to determine branch name proximity
|
9
9
|
class GitUtils
|
10
10
|
def self.similar_branch?(name)
|
11
|
-
|
11
|
+
Git::Wrapper.branch_names.each do |n|
|
12
12
|
return true if DamerauLevenshtein.distance(n, name) < 3
|
13
13
|
|
14
14
|
branch_name_match = n.match(/(.*)(-[1-9]+[0-9]*$)/)
|
@@ -21,11 +21,11 @@ module StoryBranch
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def self.branch_to_story_string(regex_matcher = /.*-(\d+$)/)
|
24
|
-
|
24
|
+
Git::Wrapper.current_branch.match(regex_matcher)
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.status?(state)
|
28
|
-
status =
|
28
|
+
status = Git::Wrapper.status
|
29
29
|
return false unless status
|
30
30
|
|
31
31
|
!status[state].empty?
|
@@ -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: { key: { eq: "#{@team_id}"} } }) {
|
30
|
+
nodes {
|
31
|
+
id
|
32
|
+
title
|
33
|
+
description
|
34
|
+
number
|
35
|
+
url
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
).squeeze(' ')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,56 @@
|
|
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
|
+
@issue_regex = Regexp.new("#{@team_id}-(\\d+)")
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid?
|
23
|
+
!@api_key.nil? && !@team_id.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
# TODO: This should probably be renamed to something more meaningful
|
27
|
+
# in the sense that it should be workable stories/issues
|
28
|
+
# which depend on the tracker's workflow. PivotalTracker they need to
|
29
|
+
# be started and estimated, while for Github they just need to be open
|
30
|
+
def stories
|
31
|
+
project.stories
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_story_by_id(story_id)
|
35
|
+
project.stories(id: story_id).first
|
36
|
+
end
|
37
|
+
|
38
|
+
def client
|
39
|
+
@client ||= StoryBranch::Graphql::Client.new(api_url: API_URL, api_key: @api_key)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def configure_api
|
45
|
+
client
|
46
|
+
end
|
47
|
+
|
48
|
+
def project
|
49
|
+
return @project if @project
|
50
|
+
raise 'team must be set' unless @team_id
|
51
|
+
|
52
|
+
@project = Team.new(@team_id, client)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/story_branch/main.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require_relative './github/tracker'
|
5
|
-
require_relative './jira/tracker'
|
3
|
+
require 'story_branch/git/wrapper'
|
6
4
|
require_relative './git_utils'
|
7
|
-
require_relative './git_wrapper'
|
8
5
|
require_relative './config_manager'
|
9
6
|
require_relative './url_opener'
|
7
|
+
require_relative 'tracker_initializer'
|
8
|
+
|
10
9
|
require 'tty-prompt'
|
11
10
|
|
12
11
|
module StoryBranch
|
@@ -20,7 +19,7 @@ module StoryBranch
|
|
20
19
|
def initialize
|
21
20
|
@config = ConfigManager.new
|
22
21
|
abort(@config.errors.join("\n")) unless @config.valid?
|
23
|
-
@tracker = initialize_tracker
|
22
|
+
@tracker = StoryBranch::TrackerInitializer.initialize_tracker(config: @config)
|
24
23
|
abort('Invalid tracker configuration setting.') unless @tracker.valid?
|
25
24
|
end
|
26
25
|
|
@@ -45,7 +44,7 @@ module StoryBranch
|
|
45
44
|
commit_message = build_finish_message
|
46
45
|
proceed = prompt.yes?("Commit with standard message? #{commit_message}")
|
47
46
|
if proceed
|
48
|
-
|
47
|
+
Git::Wrapper.commit commit_message
|
49
48
|
else
|
50
49
|
prompt.say 'Aborted'
|
51
50
|
end
|
@@ -165,7 +164,7 @@ module StoryBranch
|
|
165
164
|
feature_branch_name_with_story_id = build_branch_name(branch_name, story.id)
|
166
165
|
|
167
166
|
prompt.say("Creating: #{feature_branch_name_with_story_id} with #{current_branch} as parent")
|
168
|
-
|
167
|
+
Git::Wrapper.create_branch feature_branch_name_with_story_id
|
169
168
|
end
|
170
169
|
|
171
170
|
def valid_branch_name(story)
|
@@ -207,21 +206,7 @@ module StoryBranch
|
|
207
206
|
end
|
208
207
|
|
209
208
|
def current_branch
|
210
|
-
@current_branch ||=
|
211
|
-
end
|
212
|
-
|
213
|
-
def initialize_tracker
|
214
|
-
# TODO: Ideally this would be mapped out somewhere so we don't need to
|
215
|
-
# evaluate anything from the config here
|
216
|
-
tracker_type = @config.tracker_type
|
217
|
-
case tracker_type
|
218
|
-
when 'github'
|
219
|
-
StoryBranch::Github::Tracker.new(**@config.tracker_params)
|
220
|
-
when 'pivotal-tracker'
|
221
|
-
StoryBranch::Pivotal::Tracker.new(**@config.tracker_params)
|
222
|
-
when 'jira'
|
223
|
-
StoryBranch::Jira::Tracker.new(**@config.tracker_params)
|
224
|
-
end
|
209
|
+
@current_branch ||= Git::Wrapper.current_branch
|
225
210
|
end
|
226
211
|
end
|
227
212
|
# rubocop:enable Metrics/ClassLength
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './constants'
|
4
|
+
require_relative './pivotal/tracker'
|
5
|
+
require_relative './github/tracker'
|
6
|
+
require_relative './jira/tracker'
|
7
|
+
require_relative './linear_app/tracker'
|
8
|
+
|
9
|
+
module StoryBranch
|
10
|
+
# helper class to find out which tracker should be initialized based on the
|
11
|
+
# configuration values
|
12
|
+
class TrackerInitializer
|
13
|
+
def self.initialize_tracker(config:)
|
14
|
+
tracker_class = find_tracker_class(config.tracker_type)
|
15
|
+
raise 'Invalid tracker configuration' unless tracker_class
|
16
|
+
|
17
|
+
tracker_class.new(**config.tracker_params)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find_tracker_class(tracker_type)
|
21
|
+
tracker_str = StoryBranch::TRACKERS_CLASSES[tracker_type]
|
22
|
+
return nil unless tracker_str
|
23
|
+
|
24
|
+
Kernel.const_get(tracker_str)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/story_branch/version.rb
CHANGED
data/story_branch.gemspec
CHANGED
@@ -55,7 +55,10 @@ Gem::Specification.new do |spec|
|
|
55
55
|
|
56
56
|
spec.add_runtime_dependency 'blanket_wrapper', '~> 3.0', '> 3.0'
|
57
57
|
spec.add_runtime_dependency 'damerau-levenshtein', '~> 1.3', '> 1.3'
|
58
|
+
spec.add_runtime_dependency 'httparty', '>0'
|
58
59
|
spec.add_runtime_dependency 'jira-ruby', '> 1.7', '< 3'
|
60
|
+
spec.add_runtime_dependency 'story_branch-graphql', '~> 0.0.2'
|
61
|
+
spec.add_runtime_dependency 'story_branch-git_wrapper', '~> 0.0.3'
|
59
62
|
spec.add_runtime_dependency 'thor', '> 0.20', '< 2'
|
60
63
|
spec.add_runtime_dependency 'tty-command', '~> 0.8', '> 0.8'
|
61
64
|
spec.add_runtime_dependency 'tty-config', '~> 0.2', '> 0.2'
|
@@ -69,9 +72,9 @@ Gem::Specification.new do |spec|
|
|
69
72
|
spec.add_development_dependency 'ostruct', '~> 0.1', '> 0.1'
|
70
73
|
spec.add_development_dependency 'pry', '~> 0.11', '> 0.11'
|
71
74
|
spec.add_development_dependency 'rake', '>= 12.3.3', '< 14'
|
72
|
-
spec.add_development_dependency 'rubocop', '~> 1.22'
|
73
75
|
spec.add_development_dependency 'rspec', '~> 3', '> 3'
|
74
76
|
spec.add_development_dependency 'rspec_junit_formatter', '~> 0.4', '> 0.4'
|
77
|
+
spec.add_development_dependency 'rubocop', '~> 1.22'
|
75
78
|
spec.add_development_dependency 'simplecov', '~> 0.16', '> 0.16'
|
76
79
|
end
|
77
80
|
# rubocop:enable Metrics/BlockLength
|
data/tools/prep_changelog.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'story_branch/git/wrapper'
|
4
4
|
|
5
5
|
def grab_and_print_log(from, to)
|
6
|
-
all_log = StoryBranch::
|
6
|
+
all_log = StoryBranch::Git::Wrapper.command("log #{from}..#{to}")
|
7
7
|
|
8
8
|
matches = all_log.scan(/CHANGELOG\n(.*?)--- 8< ---/m).flatten
|
9
9
|
matches.map!(&:strip)
|
@@ -19,7 +19,7 @@ end
|
|
19
19
|
# rubocop:disable Metrics/MethodLength
|
20
20
|
# rubocop:disable Metrics/AbcSize
|
21
21
|
def print_all_logs
|
22
|
-
all_tags = StoryBranch::
|
22
|
+
all_tags = StoryBranch::Git::Wrapper.command_lines('tag --list')
|
23
23
|
cleanup_tags = all_tags.map do |t|
|
24
24
|
{ cleanup_tag: t.delete('v'), tag: t }
|
25
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: story_branch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rui Baltazar
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: exe
|
14
14
|
cert_chain: []
|
15
|
-
date: 2022-
|
15
|
+
date: 2022-08-22 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: blanket_wrapper
|
@@ -54,6 +54,20 @@ dependencies:
|
|
54
54
|
- - ">"
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: '1.3'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: httparty
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :runtime
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
57
71
|
- !ruby/object:Gem::Dependency
|
58
72
|
name: jira-ruby
|
59
73
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,6 +88,34 @@ dependencies:
|
|
74
88
|
- - "<"
|
75
89
|
- !ruby/object:Gem::Version
|
76
90
|
version: '3'
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: story_branch-graphql
|
93
|
+
requirement: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 0.0.2
|
98
|
+
type: :runtime
|
99
|
+
prerelease: false
|
100
|
+
version_requirements: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 0.0.2
|
105
|
+
- !ruby/object:Gem::Dependency
|
106
|
+
name: story_branch-git_wrapper
|
107
|
+
requirement: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 0.0.3
|
112
|
+
type: :runtime
|
113
|
+
prerelease: false
|
114
|
+
version_requirements: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: 0.0.3
|
77
119
|
- !ruby/object:Gem::Dependency
|
78
120
|
name: thor
|
79
121
|
requirement: !ruby/object:Gem::Requirement
|
@@ -314,20 +356,6 @@ dependencies:
|
|
314
356
|
- - "<"
|
315
357
|
- !ruby/object:Gem::Version
|
316
358
|
version: '14'
|
317
|
-
- !ruby/object:Gem::Dependency
|
318
|
-
name: rubocop
|
319
|
-
requirement: !ruby/object:Gem::Requirement
|
320
|
-
requirements:
|
321
|
-
- - "~>"
|
322
|
-
- !ruby/object:Gem::Version
|
323
|
-
version: '1.22'
|
324
|
-
type: :development
|
325
|
-
prerelease: false
|
326
|
-
version_requirements: !ruby/object:Gem::Requirement
|
327
|
-
requirements:
|
328
|
-
- - "~>"
|
329
|
-
- !ruby/object:Gem::Version
|
330
|
-
version: '1.22'
|
331
359
|
- !ruby/object:Gem::Dependency
|
332
360
|
name: rspec
|
333
361
|
requirement: !ruby/object:Gem::Requirement
|
@@ -368,6 +396,20 @@ dependencies:
|
|
368
396
|
- - ">"
|
369
397
|
- !ruby/object:Gem::Version
|
370
398
|
version: '0.4'
|
399
|
+
- !ruby/object:Gem::Dependency
|
400
|
+
name: rubocop
|
401
|
+
requirement: !ruby/object:Gem::Requirement
|
402
|
+
requirements:
|
403
|
+
- - "~>"
|
404
|
+
- !ruby/object:Gem::Version
|
405
|
+
version: '1.22'
|
406
|
+
type: :development
|
407
|
+
prerelease: false
|
408
|
+
version_requirements: !ruby/object:Gem::Requirement
|
409
|
+
requirements:
|
410
|
+
- - "~>"
|
411
|
+
- !ruby/object:Gem::Version
|
412
|
+
version: '1.22'
|
371
413
|
- !ruby/object:Gem::Dependency
|
372
414
|
name: simplecov
|
373
415
|
requirement: !ruby/object:Gem::Requirement
|
@@ -420,6 +462,7 @@ files:
|
|
420
462
|
- ".story_branch.yml"
|
421
463
|
- Changelog.md
|
422
464
|
- Gemfile
|
465
|
+
- Gemfile.lock
|
423
466
|
- LICENSE.txt
|
424
467
|
- README.md
|
425
468
|
- Rakefile
|
@@ -441,16 +484,20 @@ files:
|
|
441
484
|
- lib/story_branch/commands/start.rb
|
442
485
|
- lib/story_branch/commands/unstart.rb
|
443
486
|
- lib/story_branch/config_manager.rb
|
487
|
+
- lib/story_branch/constants.rb
|
444
488
|
- lib/story_branch/git_utils.rb
|
445
|
-
- lib/story_branch/git_wrapper.rb
|
446
489
|
- lib/story_branch/github/issue.rb
|
447
490
|
- lib/story_branch/github/label.rb
|
448
491
|
- lib/story_branch/github/milestone.rb
|
449
492
|
- lib/story_branch/github/project.rb
|
450
493
|
- lib/story_branch/github/tracker.rb
|
494
|
+
- lib/story_branch/issue_base.rb
|
451
495
|
- lib/story_branch/jira/issue.rb
|
452
496
|
- lib/story_branch/jira/project.rb
|
453
497
|
- lib/story_branch/jira/tracker.rb
|
498
|
+
- lib/story_branch/linear_app/issue.rb
|
499
|
+
- lib/story_branch/linear_app/team.rb
|
500
|
+
- lib/story_branch/linear_app/tracker.rb
|
454
501
|
- lib/story_branch/main.rb
|
455
502
|
- lib/story_branch/pivotal/project.rb
|
456
503
|
- lib/story_branch/pivotal/story.rb
|
@@ -466,6 +513,7 @@ files:
|
|
466
513
|
- lib/story_branch/templates/start/.gitkeep
|
467
514
|
- lib/story_branch/templates/unstart/.gitkeep
|
468
515
|
- lib/story_branch/tracker_base.rb
|
516
|
+
- lib/story_branch/tracker_initializer.rb
|
469
517
|
- lib/story_branch/url_opener.rb
|
470
518
|
- lib/story_branch/version.rb
|
471
519
|
- story_branch.gemspec
|
@@ -496,7 +544,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
496
544
|
- !ruby/object:Gem::Version
|
497
545
|
version: '0'
|
498
546
|
requirements: []
|
499
|
-
rubygems_version: 3.2
|
547
|
+
rubygems_version: 3.1.2
|
500
548
|
signing_key:
|
501
549
|
specification_version: 4
|
502
550
|
summary: Create git branches based on your preferred tracker tickets
|
@@ -1,108 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# NOTE: Consider extracting this to a separate gem
|
4
|
-
module StoryBranch
|
5
|
-
# GitWrapper to help running git commands with direct system calls
|
6
|
-
# Essentially it provides a couple of commands to interact with git
|
7
|
-
# - StoryBranch::GitWrapper.command('<cmd>', [<opts>])
|
8
|
-
# Returns the output as is
|
9
|
-
#
|
10
|
-
# - StoryBranch::GitWrapper.command_lines('<cmd>', [<opts>])
|
11
|
-
# Returns the output split into an array of lines, stripped and chomped
|
12
|
-
#
|
13
|
-
# - StoryBranch::GitWrapper.branch_names
|
14
|
-
# Returns the list of available branch names, locally and configured remotes
|
15
|
-
class GitWrapper
|
16
|
-
STATI_MATCHERS = {
|
17
|
-
modified_rx: /^ M (.*)/,
|
18
|
-
untracked_rx: /^\?\? (.*)/,
|
19
|
-
staged_rx: /^M (.*)/,
|
20
|
-
added_rx: /^A (.*)/
|
21
|
-
}.freeze
|
22
|
-
|
23
|
-
def self.command(cmd, opts = [])
|
24
|
-
gw = new
|
25
|
-
gw.call(cmd, opts)
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.command_lines(cmd, opts = [])
|
29
|
-
result = command(cmd, opts)
|
30
|
-
lines = result.split("\n")
|
31
|
-
lines.each(&:strip!)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.branch_names
|
35
|
-
# NOTE: Regex matcher for cases as:
|
36
|
-
# remotes/origin/allow.... <- remote branch (remove 'remotes/origin')
|
37
|
-
# * allow.... <- * indicates current branch (remove '* ')
|
38
|
-
# allow <- local branch (do nothing)
|
39
|
-
regex = %r{(^remotes/.*/|\s|[*])}
|
40
|
-
all_branches.map do |line|
|
41
|
-
line = line.sub(regex, '')
|
42
|
-
line
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.current_branch
|
47
|
-
current_branch_line = all_branches.detect do |line|
|
48
|
-
line.match(/\*/)
|
49
|
-
end
|
50
|
-
current_branch_line.tr('*', ' ').strip
|
51
|
-
end
|
52
|
-
|
53
|
-
def self.all_branches
|
54
|
-
command_lines('branch', '-a')
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.create_branch(name)
|
58
|
-
command('checkout', ['-b', name])
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.status
|
62
|
-
g_status = command_lines('status', '-s')
|
63
|
-
return nil if g_status.empty?
|
64
|
-
|
65
|
-
{
|
66
|
-
modified: status_collect(g_status, STATI_MATCHERS[:modified_rx]),
|
67
|
-
untracked: status_collect(g_status, STATI_MATCHERS[:untracked_rx]),
|
68
|
-
added: status_collect(g_status, STATI_MATCHERS[:added_rx]),
|
69
|
-
staged: status_collect(g_status, STATI_MATCHERS[:staged_rx])
|
70
|
-
}
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.status_collect(status, regex)
|
74
|
-
chosen_stati = status.select { |e| e.match(regex) }
|
75
|
-
chosen_stati.map { |e| e.match(regex)[1] }
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.commit(message)
|
79
|
-
command('commit', ['-m', message])
|
80
|
-
end
|
81
|
-
|
82
|
-
def initialize
|
83
|
-
@system_git = 'git'
|
84
|
-
end
|
85
|
-
|
86
|
-
def call(cmd, opts = [])
|
87
|
-
opts = prepare_opts(opts)
|
88
|
-
git_cmd = "#{@system_git} #{cmd} #{opts}"
|
89
|
-
`#{git_cmd}`.chomp.strip
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
# NOTE: Taken from ruby git gem
|
95
|
-
def escape(str = '')
|
96
|
-
str = str.to_s
|
97
|
-
return "'#{str.gsub('\'', '\'"\'"\'')}'" if RUBY_PLATFORM !~ /mingw|mswin/
|
98
|
-
|
99
|
-
# Keeping the old escape format for windows users
|
100
|
-
escaped = str.gsub('\'', '\'\\\'\'')
|
101
|
-
%("#{escaped}")
|
102
|
-
end
|
103
|
-
|
104
|
-
def prepare_opts(opts = [])
|
105
|
-
[opts].flatten.map { |s| escape(s) }.join(' ')
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|