circleci-cli 1.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # circleci-cli
2
-
2
+ [![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors-)
3
3
  [![Gem Version](https://badge.fury.io/rb/circleci-cli.svg)](https://badge.fury.io/rb/circleci-cli)
4
4
  [![Circle CI](https://circleci.com/gh/unhappychoice/circleci-cli.svg?style=shield)](https://circleci.com/gh/unhappychoice/circleci-cli)
5
5
  [![Code Climate](https://codeclimate.com/github/unhappychoice/circleci-cli/badges/gpa.svg)](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
  ![sample.gif](https://github.com/unhappychoice/circler/raw/master/movie/rec.gif)
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 # open circle ci website
33
- circleci-cli build # show build description
34
- circleci-cli builds # list builds
35
- circleci-cli help [COMMAND] # describe available commands or one specific command
36
- circleci-cli projects # list projects
37
- circleci-cli retry # retry a build
38
- circleci-cli version # show gem version
39
- circleci-cli watch # watch a build in real time
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 # specify repository
43
- -b branch # specify branch name
44
- -n build_number # specify build number
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
@@ -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 'colorize', '~> 0.8.1'
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', '~> 2.4.3'
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', '< 0.29'
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', '~> 0.20.0'
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
 
@@ -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
- desc 'projects', 'list projects'
23
- method_option :format, aliases: 'f', type: :string, banner: 'pretty/simple'
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', 'list builds'
29
- method_option :project, aliases: 'p', type: :string, banner: 'user/project'
30
- method_option :branch, aliases: 'b', type: :string, banner: 'some-branch'
31
- method_option :format, aliases: 'f', type: :string, banner: 'pretty/simple'
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', 'show build description'
37
- method_option :project, aliases: 'p', type: :string, banner: 'user/project'
38
- method_option :build, aliases: 'n', type: :numeric, banner: 'build-number'
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', 'open circle ci website'
44
- method_option :project, aliases: 'p', type: :string, banner: 'user/project'
45
- method_option :build, aliases: 'n', type: :numeric, banner: 'build-number'
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', 'retry a build'
51
- method_option :project, aliases: 'p', type: :string, banner: 'user/project'
52
- method_option :build, aliases: 'n', type: :numeric, banner: 'build-number'
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', 'cancel a build'
58
- method_option :project, aliases: 'p', type: :string, banner: 'user/project'
59
- method_option :build, aliases: 'n', type: :numeric, banner: 'build-number'
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', 'watch a build in real time'
65
- method_option :project, aliases: 'p', type: :string, banner: 'user/project'
66
- method_option :build, aliases: 'n', type: :numeric, banner: 'build-number'
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', 'show gem 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 reponame
26
- repository = Rugged::Repository.new('.')
27
- origin = repository.remotes.find { |r| r.name == 'origin' }
28
- regexp = %r{git@github.com(?::|/)([\w_-]+/[\w_-]+)(?:\.git)*}
29
- return Regexp.last_match(1) if origin.url =~ regexp
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
- build = Response::Build.get(username, reponame, number)
13
- say Printer::StepPrinter.new(build.steps).to_s
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
- username, reponame = project_name(options).split('/')
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: should_be_pretty(options)).to_s
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 = build_number(options)
11
+ number = build_number_for(username, reponame, options)
12
+
12
13
  build = Response::Build.retry(username, reponame, number)
13
- if build.username
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