circleci-cli 1.0.0 → 3.0.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/.all-contributorsrc +56 -0
- data/.circleci/config.yml +2 -2
- data/.github/workflows/test.yml +22 -0
- data/.rubocop.yml +9 -1
- data/.ruby-version +1 -0
- data/CHANGELOG.md +140 -0
- data/Gemfile.lock +93 -62
- data/README.md +74 -14
- data/Rakefile +8 -0
- data/circleci-cli.gemspec +6 -5
- data/lib/circleci/cli.rb +115 -24
- data/lib/circleci/cli/command/base_command.rb +6 -13
- data/lib/circleci/cli/command/build_command.rb +18 -2
- data/lib/circleci/cli/command/builds_command.rb +9 -9
- data/lib/circleci/cli/command/projects_command.rb +1 -1
- data/lib/circleci/cli/command/retry_command.rb +18 -2
- data/lib/circleci/cli/command/watch_command.rb +46 -43
- data/lib/circleci/cli/command/watch_command/build_repository.rb +44 -0
- data/lib/circleci/cli/command/watch_command/build_watcher.rb +85 -0
- data/lib/circleci/cli/networking/pusher_client.rb +15 -21
- data/lib/circleci/cli/printer.rb +25 -1
- data/lib/circleci/cli/printer/build_printer.rb +18 -6
- data/lib/circleci/cli/printer/project_printer.rb +2 -1
- data/lib/circleci/cli/printer/step_printer.rb +26 -16
- data/lib/circleci/cli/response/account.rb +6 -4
- data/lib/circleci/cli/response/action.rb +1 -0
- data/lib/circleci/cli/response/build.rb +35 -28
- data/lib/circleci/cli/response/step.rb +1 -2
- data/lib/circleci/cli/version.rb +1 -1
- data/movie/rec.gif +0 -0
- metadata +45 -27
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# circleci-cli
|
2
|
-
|
2
|
+
[](#contributors-)
|
3
3
|
[](https://badge.fury.io/rb/circleci-cli)
|
4
4
|
[](https://circleci.com/gh/unhappychoice/circleci-cli)
|
5
5
|
[](https://codeclimate.com/github/unhappychoice/circleci-cli)
|
@@ -12,8 +12,6 @@ circleci-cli is a CLI tool for [Circle CI](https://circleci.com).
|
|
12
12
|
|
13
13
|

|
14
14
|
|
15
|
-
Notice: This gem is renamed from `circler` to `circleci-cli` on 2019/09/22
|
16
|
-
|
17
15
|
## Installation
|
18
16
|
|
19
17
|
```sh
|
@@ -29,19 +27,59 @@ export CIRCLE_CI_TOKEN=your-circle-ci-token
|
|
29
27
|
## Usage
|
30
28
|
```
|
31
29
|
Commands:
|
32
|
-
circleci-cli browse
|
33
|
-
circleci-cli build
|
34
|
-
circleci-cli builds
|
35
|
-
circleci-cli
|
36
|
-
circleci-cli
|
37
|
-
circleci-cli
|
38
|
-
circleci-cli
|
39
|
-
circleci-cli
|
30
|
+
circleci-cli browse # Open CircleCI website
|
31
|
+
circleci-cli build # Show the build result
|
32
|
+
circleci-cli builds # List builds
|
33
|
+
circleci-cli cancel # Cancel a build
|
34
|
+
circleci-cli help [COMMAND] # Describe available commands or one specific command
|
35
|
+
circleci-cli projects # List projects
|
36
|
+
circleci-cli retry # Retry a build
|
37
|
+
circleci-cli version # Show gem version
|
38
|
+
circleci-cli watch # Watch builds in real time
|
40
39
|
|
41
40
|
Options:
|
42
|
-
-p user_name/project
|
43
|
-
|
44
|
-
|
41
|
+
-p user_name/project # Specify repository
|
42
|
+
# Default to the Git remote of current directory
|
43
|
+
|
44
|
+
-b branch # Specify branch name
|
45
|
+
# Default to the current Git branch
|
46
|
+
|
47
|
+
-a, --all, --no-all # Ignore the branch option and stop being filtered by the branch
|
48
|
+
# Default to false
|
49
|
+
|
50
|
+
-n build_number # Specify build number.
|
51
|
+
-l last # Get or retry last failed build.
|
52
|
+
-v verbose # Show all the logs if applied to watch command.
|
53
|
+
|
54
|
+
--pretty=true/false, --no-pretty # Make outputs pretty or not
|
55
|
+
# Default to true
|
56
|
+
```
|
57
|
+
|
58
|
+
### Examples
|
59
|
+
|
60
|
+
#### Watch your project
|
61
|
+
```
|
62
|
+
$ circleci-cli watch
|
63
|
+
```
|
64
|
+
|
65
|
+
#### Watch your project and show all of the build log
|
66
|
+
```
|
67
|
+
$ circleci-cli watch -v
|
68
|
+
```
|
69
|
+
|
70
|
+
#### Show last failed build
|
71
|
+
```
|
72
|
+
$ circleci-cli build --last
|
73
|
+
```
|
74
|
+
|
75
|
+
#### Retry last failed build
|
76
|
+
```
|
77
|
+
$ circleci-cli retry --last
|
78
|
+
```
|
79
|
+
|
80
|
+
#### Open CircleCI webpage for current project
|
81
|
+
```
|
82
|
+
$ circleci-cli browse
|
45
83
|
```
|
46
84
|
|
47
85
|
## Contributing
|
@@ -51,3 +89,25 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/unhapp
|
|
51
89
|
## License
|
52
90
|
|
53
91
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
92
|
+
|
93
|
+
## Contributors ✨
|
94
|
+
|
95
|
+
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
96
|
+
|
97
|
+
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
98
|
+
<!-- prettier-ignore-start -->
|
99
|
+
<!-- markdownlint-disable -->
|
100
|
+
<table>
|
101
|
+
<tr>
|
102
|
+
<td align="center"><a href="http://blog.unhappychoice.com"><img src="https://avatars3.githubusercontent.com/u/5608948?v=4" width="100px;" alt=""/><br /><sub><b>Yuji Ueki</b></sub></a><br /><a href="https://github.com/unhappychoice/circleci-cli/commits?author=unhappychoice" title="Code">💻</a></td>
|
103
|
+
<td align="center"><a href="https://mattbrictson.com/"><img src="https://avatars0.githubusercontent.com/u/189693?v=4" width="100px;" alt=""/><br /><sub><b>Matt Brictson</b></sub></a><br /><a href="https://github.com/unhappychoice/circleci-cli/commits?author=mattbrictson" title="Code">💻</a> <a href="https://github.com/unhappychoice/circleci-cli/commits?author=mattbrictson" title="Tests">⚠️</a></td>
|
104
|
+
<td align="center"><a href="http://fzf.me"><img src="https://avatars0.githubusercontent.com/u/1462357?v=4" width="100px;" alt=""/><br /><sub><b>Fletcher Fowler</b></sub></a><br /><a href="https://github.com/unhappychoice/circleci-cli/issues?q=author%3Afzf" title="Bug reports">🐛</a> <a href="#ideas-fzf" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/unhappychoice/circleci-cli/commits?author=fzf" title="Code">💻</a></td>
|
105
|
+
<td align="center"><a href="https://datadoghq.com"><img src="https://avatars3.githubusercontent.com/u/583503?v=4" width="100px;" alt=""/><br /><sub><b>Marco Costa</b></sub></a><br /><a href="#ideas-marcotc" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/unhappychoice/circleci-cli/commits?author=marcotc" title="Code">💻</a></td>
|
106
|
+
</tr>
|
107
|
+
</table>
|
108
|
+
|
109
|
+
<!-- markdownlint-enable -->
|
110
|
+
<!-- prettier-ignore-end -->
|
111
|
+
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
112
|
+
|
113
|
+
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
data/Rakefile
CHANGED
@@ -2,7 +2,15 @@
|
|
2
2
|
|
3
3
|
require 'bundler/gem_tasks'
|
4
4
|
require 'rspec/core/rake_task'
|
5
|
+
require 'github_changelog_generator/task'
|
5
6
|
|
6
7
|
RSpec::Core::RakeTask.new(:spec)
|
7
8
|
|
8
9
|
task default: :spec
|
10
|
+
|
11
|
+
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
12
|
+
config.user = 'unhappychoice'
|
13
|
+
config.project = 'circleci-cli'
|
14
|
+
config.since_tag = '0.1.0'
|
15
|
+
# config.future_release = '2.2.0'
|
16
|
+
end
|
data/circleci-cli.gemspec
CHANGED
@@ -6,20 +6,20 @@ require 'circleci/cli/version'
|
|
6
6
|
|
7
7
|
def production_dependency(spec)
|
8
8
|
spec.add_dependency 'circleci', '~> 2.0.2'
|
9
|
-
spec.add_dependency '
|
10
|
-
spec.add_dependency 'faraday', '>= 0.14', '< 0.16'
|
9
|
+
spec.add_dependency 'faraday', '>= 0.14', '< 1.1'
|
11
10
|
spec.add_dependency 'highline', '>= 1.7.8', '< 2.1.0'
|
12
|
-
spec.add_dependency 'launchy', '
|
11
|
+
spec.add_dependency 'launchy', '>= 2.4.3', '< 2.6.0'
|
13
12
|
spec.add_dependency 'pusher-client', '~> 0.6.2'
|
14
|
-
spec.add_dependency 'rugged', '>= 0.26', '<
|
13
|
+
spec.add_dependency 'rugged', '>= 0.26', '< 1.1'
|
15
14
|
spec.add_dependency 'terminal-notifier', '~> 2.0.0'
|
16
15
|
spec.add_dependency 'terminal-table', '~> 1.8.0'
|
17
|
-
spec.add_dependency 'thor', '
|
16
|
+
spec.add_dependency 'thor', '>= 0.20', '< 1.1'
|
18
17
|
end
|
19
18
|
|
20
19
|
def development_dependency(spec)
|
21
20
|
spec.add_development_dependency 'bundler'
|
22
21
|
spec.add_development_dependency 'codecov'
|
22
|
+
spec.add_development_dependency 'github_changelog_generator'
|
23
23
|
spec.add_development_dependency 'guard'
|
24
24
|
spec.add_development_dependency 'guard-rspec'
|
25
25
|
spec.add_development_dependency 'guard-rubocop'
|
@@ -38,6 +38,7 @@ end
|
|
38
38
|
Gem::Specification.new do |spec|
|
39
39
|
spec.name = 'circleci-cli'
|
40
40
|
spec.version = CircleCI::CLI::VERSION
|
41
|
+
spec.required_ruby_version = '>= 2.5'
|
41
42
|
spec.authors = ['unhappychoice']
|
42
43
|
spec.email = ['unhappychoice@gmail.com']
|
43
44
|
|
data/lib/circleci/cli.rb
CHANGED
@@ -5,7 +5,6 @@ require 'faraday'
|
|
5
5
|
require 'launchy'
|
6
6
|
require 'terminal-table'
|
7
7
|
require 'highline/import'
|
8
|
-
require 'colorize'
|
9
8
|
require 'rugged'
|
10
9
|
require 'circleci'
|
11
10
|
require 'terminal-notifier'
|
@@ -18,57 +17,149 @@ require 'circleci/cli/networking'
|
|
18
17
|
|
19
18
|
module CircleCI
|
20
19
|
module CLI
|
21
|
-
class Runner < Thor
|
22
|
-
|
23
|
-
|
20
|
+
class Runner < Thor # rubocop:disable Metrics/ClassLength
|
21
|
+
package_name 'circleci-cli'
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def project
|
25
|
+
repository = Rugged::Repository.new('.')
|
26
|
+
origin = repository.remotes.find { |r| r.name == 'origin' }
|
27
|
+
regexp = %r{(?:git@|https://)github.com(?::|/)([\w_-]+/[.\w_-]+?)(?:\.git)*$}
|
28
|
+
return Regexp.last_match(1) if origin.url =~ regexp
|
29
|
+
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def branch_name
|
34
|
+
repository = Rugged::Repository.new('.')
|
35
|
+
head = repository.head
|
36
|
+
|
37
|
+
return nil unless head.branch?
|
38
|
+
|
39
|
+
head.name.sub(%r{\Arefs/heads/}, '')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'projects', 'List projects'
|
44
|
+
method_option :pretty, type: :boolean, default: true, desc: 'Make output pretty'
|
24
45
|
def projects
|
25
46
|
Command::ProjectsCommand.run(options)
|
26
47
|
end
|
27
48
|
|
28
|
-
desc 'builds', '
|
29
|
-
method_option :project,
|
30
|
-
|
31
|
-
|
49
|
+
desc 'builds', 'List builds'
|
50
|
+
method_option :project,
|
51
|
+
aliases: 'p',
|
52
|
+
type: :string,
|
53
|
+
banner: 'user/project',
|
54
|
+
default: project,
|
55
|
+
desc: 'A project you want to get.'
|
56
|
+
method_option :branch,
|
57
|
+
aliases: 'b',
|
58
|
+
type: :string,
|
59
|
+
banner: 'some-branch',
|
60
|
+
default: branch_name,
|
61
|
+
desc: 'A branch name you want to filter with.'
|
62
|
+
method_option :all,
|
63
|
+
aliases: 'a',
|
64
|
+
type: :boolean,
|
65
|
+
default: false,
|
66
|
+
desc: 'Target all the branches. This option overwrites branch option.'
|
67
|
+
method_option :pretty, type: :boolean, banner: 'true/false', default: true, desc: 'Make output pretty.'
|
32
68
|
def builds
|
33
69
|
Command::BuildsCommand.run(options)
|
34
70
|
end
|
35
71
|
|
36
|
-
desc 'build', '
|
37
|
-
method_option :project,
|
38
|
-
|
72
|
+
desc 'build', 'Show the build result'
|
73
|
+
method_option :project,
|
74
|
+
aliases: 'p',
|
75
|
+
type: :string,
|
76
|
+
banner: 'user/project',
|
77
|
+
default: project,
|
78
|
+
desc: 'A project you want to get.'
|
79
|
+
method_option :build, aliases: 'n', type: :numeric, banner: 'build-number', desc: 'Build number you want to get.'
|
80
|
+
method_option :last, aliases: 'l', type: :boolean, default: false, desc: 'Get last failed build.'
|
81
|
+
method_option :pretty, type: :boolean, banner: 'true/false', default: true, desc: 'Make output pretty.'
|
39
82
|
def build
|
40
83
|
Command::BuildCommand.run(options)
|
41
84
|
end
|
42
85
|
|
43
|
-
desc 'browse', '
|
44
|
-
method_option :project,
|
45
|
-
|
86
|
+
desc 'browse', 'Open CircleCI website'
|
87
|
+
method_option :project,
|
88
|
+
aliases: 'p',
|
89
|
+
type: :string,
|
90
|
+
banner: 'user/project',
|
91
|
+
default: project,
|
92
|
+
desc: 'A project you want to get.'
|
93
|
+
method_option :build,
|
94
|
+
aliases: 'n',
|
95
|
+
type: :numeric,
|
96
|
+
banner: 'build-number',
|
97
|
+
desc: 'Build number you want to browse.'
|
46
98
|
def browse
|
47
99
|
Command::BrowseCommand.run(options)
|
48
100
|
end
|
49
101
|
|
50
|
-
desc 'retry', '
|
51
|
-
method_option :project,
|
52
|
-
|
102
|
+
desc 'retry', 'Retry a build'
|
103
|
+
method_option :project,
|
104
|
+
aliases: 'p',
|
105
|
+
type: :string,
|
106
|
+
banner: 'user/project',
|
107
|
+
default: project,
|
108
|
+
desc: 'A project you want to get.'
|
109
|
+
method_option :build,
|
110
|
+
aliases: 'n',
|
111
|
+
type: :numeric,
|
112
|
+
banner: 'build-number',
|
113
|
+
desc: 'Build number you want to retry.'
|
114
|
+
method_option :last, aliases: 'l', type: :boolean, desc: 'Retry last failed build.'
|
53
115
|
def retry
|
54
116
|
Command::RetryCommand.run(options)
|
55
117
|
end
|
56
118
|
|
57
|
-
desc 'cancel', '
|
58
|
-
method_option :project,
|
59
|
-
|
119
|
+
desc 'cancel', 'Cancel a build'
|
120
|
+
method_option :project,
|
121
|
+
aliases: 'p',
|
122
|
+
type: :string,
|
123
|
+
default: project,
|
124
|
+
desc: 'A project you want to get.'
|
125
|
+
method_option :build,
|
126
|
+
aliases: 'n',
|
127
|
+
type: :numeric,
|
128
|
+
banner: 'build-number',
|
129
|
+
desc: 'Build number you want to cancel.'
|
60
130
|
def cancel
|
61
131
|
Command::CancelCommand.run(options)
|
62
132
|
end
|
63
133
|
|
64
|
-
desc 'watch', '
|
65
|
-
method_option :project,
|
66
|
-
|
134
|
+
desc 'watch', 'Watch builds in real time'
|
135
|
+
method_option :project,
|
136
|
+
aliases: 'p',
|
137
|
+
type: :string,
|
138
|
+
banner: 'user/project',
|
139
|
+
default: project,
|
140
|
+
desc: 'A project you want to get.'
|
141
|
+
method_option :branch,
|
142
|
+
aliases: 'b',
|
143
|
+
type: :string,
|
144
|
+
banner: 'some-branch',
|
145
|
+
default: branch_name,
|
146
|
+
desc: 'A branch name you want to filter with.'
|
147
|
+
method_option :all,
|
148
|
+
aliases: 'a',
|
149
|
+
type: :boolean,
|
150
|
+
default: false,
|
151
|
+
desc: 'Target all the branches. This option overwrites branch option.'
|
152
|
+
method_option :user, aliases: 'u', type: :string, banner: 'user'
|
153
|
+
method_option :verbose,
|
154
|
+
aliases: 'v',
|
155
|
+
type: :boolean,
|
156
|
+
default: false,
|
157
|
+
desc: 'Show all the build logs including successful build steps.'
|
67
158
|
def watch
|
68
159
|
Command::WatchCommand.run(options)
|
69
160
|
end
|
70
161
|
|
71
|
-
desc 'version', '
|
162
|
+
desc 'version', 'Show gem version'
|
72
163
|
def version
|
73
164
|
say CircleCI::CLI::VERSION
|
74
165
|
end
|
@@ -14,30 +14,23 @@ module CircleCI
|
|
14
14
|
def project_name(options)
|
15
15
|
if options.project
|
16
16
|
options.project
|
17
|
-
elsif reponame
|
18
|
-
reponame
|
19
17
|
else
|
20
18
|
say Printer::ProjectPrinter.new(Response::Project.all).to_s
|
21
19
|
ask('Input user-name/project-name :')
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
nil
|
23
|
+
def branch_name(options)
|
24
|
+
if options.all
|
25
|
+
nil
|
26
|
+
else
|
27
|
+
options.branch
|
28
|
+
end
|
32
29
|
end
|
33
30
|
|
34
31
|
def build_number(options)
|
35
32
|
options.build || ask('Input build number')
|
36
33
|
end
|
37
|
-
|
38
|
-
def should_be_pretty(options)
|
39
|
-
options['format'] != 'simple'
|
40
|
-
end
|
41
34
|
end
|
42
35
|
end
|
43
36
|
end
|
@@ -8,9 +8,25 @@ module CircleCI
|
|
8
8
|
def run(options)
|
9
9
|
setup_token
|
10
10
|
username, reponame = project_name(options).split('/')
|
11
|
+
build =
|
12
|
+
if options.last
|
13
|
+
get_last_build(username, reponame)
|
14
|
+
else
|
15
|
+
get_build(username, reponame, options)
|
16
|
+
end
|
17
|
+
say Printer::StepPrinter.new(build.steps, pretty: options.pretty).to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def get_build(username, reponame, options)
|
11
23
|
number = build_number(options)
|
12
|
-
|
13
|
-
|
24
|
+
Response::Build.get(username, reponame, number)
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_last_build(username, reponame)
|
28
|
+
builds = Response::Build.failed(username, reponame)
|
29
|
+
Response::Build.get(username, reponame, builds.map(&:build_number).max)
|
14
30
|
end
|
15
31
|
end
|
16
32
|
end
|
@@ -7,16 +7,16 @@ module CircleCI
|
|
7
7
|
class << self
|
8
8
|
def run(options)
|
9
9
|
setup_token
|
10
|
-
|
10
|
+
project_name = project_name(options)
|
11
|
+
username, reponame = project_name.split('/')
|
12
|
+
branch = branch_name(options)
|
13
|
+
builds = if branch
|
14
|
+
Response::Build.branch(username, reponame, branch)
|
15
|
+
else
|
16
|
+
Response::Build.all(username, reponame)
|
17
|
+
end
|
11
18
|
|
12
|
-
builds
|
13
|
-
if options.branch
|
14
|
-
Response::Build.branch(username, reponame, options.branch)
|
15
|
-
else
|
16
|
-
Response::Build.all(username, reponame)
|
17
|
-
end
|
18
|
-
|
19
|
-
say Printer::BuildPrinter.new(builds, pretty: should_be_pretty(options)).to_s
|
19
|
+
say Printer::BuildPrinter.new(builds, project_name, pretty: options.pretty).to_s
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -7,7 +7,7 @@ module CircleCI
|
|
7
7
|
class << self
|
8
8
|
def run(options)
|
9
9
|
setup_token
|
10
|
-
say Printer::ProjectPrinter.new(Response::Project.all, pretty:
|
10
|
+
say Printer::ProjectPrinter.new(Response::Project.all, pretty: options.pretty).to_s
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -8,14 +8,30 @@ module CircleCI
|
|
8
8
|
def run(options)
|
9
9
|
setup_token
|
10
10
|
username, reponame = project_name(options).split('/')
|
11
|
-
number =
|
11
|
+
number = build_number_for(username, reponame, options)
|
12
|
+
|
12
13
|
build = Response::Build.retry(username, reponame, number)
|
13
|
-
|
14
|
+
|
15
|
+
if build&.username
|
14
16
|
say "build #{username}/#{reponame} #{build.build_number} is triggered"
|
15
17
|
else
|
16
18
|
say "failed to trigger #{username}/#{reponame} #{number}"
|
17
19
|
end
|
18
20
|
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def build_number_for(username, reponame, options)
|
25
|
+
if options.last
|
26
|
+
get_last_build_number(username, reponame)
|
27
|
+
else
|
28
|
+
build_number(options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_last_build_number(username, reponame)
|
33
|
+
Response::Build.failed(username, reponame).map(&:build_number).max
|
34
|
+
end
|
19
35
|
end
|
20
36
|
end
|
21
37
|
end
|