circleci-cli 0.6.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +21 -19
- data/bin/circle +2 -2
- data/bin/console +1 -1
- data/{circler.gemspec → circleci-cli.gemspec} +3 -3
- data/exe/{circle → circleci-cli} +2 -2
- data/lib/circleci/cli.rb +77 -0
- data/lib/circleci/cli/command.rb +16 -0
- data/lib/circleci/cli/command/base_command.rb +45 -0
- data/lib/circleci/cli/command/browse_command.rb +24 -0
- data/lib/circleci/cli/command/build_command.rb +19 -0
- data/lib/circleci/cli/command/builds_command.rb +25 -0
- data/lib/circleci/cli/command/cancel_command.rb +23 -0
- data/lib/circleci/cli/command/projects_command.rb +16 -0
- data/lib/circleci/cli/command/retry_command.rb +23 -0
- data/lib/circleci/cli/command/watch_command.rb +77 -0
- data/lib/circleci/cli/networking.rb +9 -0
- data/lib/circleci/cli/networking/pusher_client.rb +62 -0
- data/lib/circleci/cli/printer.rb +11 -0
- data/lib/circleci/cli/printer/build_printer.rb +63 -0
- data/lib/circleci/cli/printer/project_printer.rb +37 -0
- data/lib/circleci/cli/printer/step_printer.rb +57 -0
- data/lib/circleci/cli/response.rb +13 -0
- data/lib/circleci/cli/response/account.rb +21 -0
- data/lib/circleci/cli/response/action.rb +39 -0
- data/lib/circleci/cli/response/build.rb +104 -0
- data/lib/circleci/cli/response/project.rb +21 -0
- data/lib/circleci/cli/response/step.rb +22 -0
- data/lib/circleci/cli/version.rb +7 -0
- data/lib/circleci_cli.rb +7 -0
- metadata +29 -25
- data/lib/circler.rb +0 -6
- data/lib/circler/cli.rb +0 -88
- data/lib/circler/command/base_command.rb +0 -41
- data/lib/circler/command/browse_command.rb +0 -20
- data/lib/circler/command/build_command.rb +0 -15
- data/lib/circler/command/builds_command.rb +0 -21
- data/lib/circler/command/cancel_command.rb +0 -19
- data/lib/circler/command/projects_command.rb +0 -12
- data/lib/circler/command/retry_command.rb +0 -19
- data/lib/circler/command/watch_command.rb +0 -73
- data/lib/circler/networking/pusher_client.rb +0 -56
- data/lib/circler/printer/build_printer.rb +0 -59
- data/lib/circler/printer/project_printer.rb +0 -33
- data/lib/circler/printer/step_printer.rb +0 -53
- data/lib/circler/response/account.rb +0 -17
- data/lib/circler/response/action.rb +0 -35
- data/lib/circler/response/build.rb +0 -100
- data/lib/circler/response/project.rb +0 -17
- data/lib/circler/response/step.rb +0 -18
- data/lib/circler/version.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5210a33cd66ffb1d7cdf4294653d0a8b0098ad7755689ead6ff50419377937ca
|
4
|
+
data.tar.gz: 16e6f04777f3046d6e0c67d3919d39713236da8a2cf9393497cf62b5310a271b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6166152b480e9accfbbb5321496a14b5fa92ea5277c629d4ce96ebbd4b5bfd520a803afebe713fcba873f2945e23f75743e24671155f018f157f7e373a50860f
|
7
|
+
data.tar.gz: ec1d2459890466344fc641fad40b0e1375d997ce3979d6babf5259d4227124cd6c0c4976dbcdb7007ea3cfad656bc1218508f76a12edadceecf06b553902840e
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,21 +1,23 @@
|
|
1
|
-
#
|
1
|
+
# circleci-cli
|
2
2
|
|
3
|
-
[![Gem Version](https://badge.fury.io/rb/
|
4
|
-
[![Circle CI](https://circleci.com/gh/unhappychoice/
|
5
|
-
[![Code Climate](https://codeclimate.com/github/unhappychoice/
|
6
|
-
[![codecov](https://codecov.io/gh/unhappychoice/
|
7
|
-
[![Libraries.io dependency status for GitHub repo](https://img.shields.io/librariesio/github/unhappychoice/
|
8
|
-
![](http://ruby-gem-downloads-badge.herokuapp.com/
|
9
|
-
![GitHub](https://img.shields.io/github/license/unhappychoice/
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/circleci-cli.svg)](https://badge.fury.io/rb/circleci-cli)
|
4
|
+
[![Circle CI](https://circleci.com/gh/unhappychoice/circleci-cli.svg?style=shield)](https://circleci.com/gh/unhappychoice/circleci-cli)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/unhappychoice/circleci-cli/badges/gpa.svg)](https://codeclimate.com/github/unhappychoice/circleci-cli)
|
6
|
+
[![codecov](https://codecov.io/gh/unhappychoice/circleci-cli/branch/master/graph/badge.svg)](https://codecov.io/gh/unhappychoice/circleci-cli)
|
7
|
+
[![Libraries.io dependency status for GitHub repo](https://img.shields.io/librariesio/github/unhappychoice/circleci-cli.svg)](https://libraries.io/github/unhappychoice/circleci-cli)
|
8
|
+
![](http://ruby-gem-downloads-badge.herokuapp.com/circleci-cli?type=total)
|
9
|
+
![GitHub](https://img.shields.io/github/license/unhappychoice/circleci-cli.svg)
|
10
10
|
|
11
|
-
|
11
|
+
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
|
+
|
15
17
|
## Installation
|
16
18
|
|
17
19
|
```sh
|
18
|
-
$ gem install
|
20
|
+
$ gem install circleci-cli
|
19
21
|
```
|
20
22
|
|
21
23
|
set the `CIRCLE_CI_TOKEN` environment variable. (optional)
|
@@ -27,14 +29,14 @@ export CIRCLE_CI_TOKEN=your-circle-ci-token
|
|
27
29
|
## Usage
|
28
30
|
```
|
29
31
|
Commands:
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
38
40
|
|
39
41
|
Options:
|
40
42
|
-p user_name/project # specify repository
|
@@ -44,7 +46,7 @@ Options:
|
|
44
46
|
|
45
47
|
## Contributing
|
46
48
|
|
47
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/unhappychoice/
|
49
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/unhappychoice/circleci-cli.
|
48
50
|
|
49
51
|
## License
|
50
52
|
|
data/bin/circle
CHANGED
data/bin/console
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require '
|
5
|
+
require 'circleci/cli/version'
|
6
6
|
|
7
7
|
def production_dependency(spec)
|
8
8
|
spec.add_dependency 'circleci', '~> 2.0.2'
|
@@ -37,13 +37,13 @@ end
|
|
37
37
|
|
38
38
|
Gem::Specification.new do |spec|
|
39
39
|
spec.name = 'circleci-cli'
|
40
|
-
spec.version =
|
40
|
+
spec.version = CircleCI::CLI::VERSION
|
41
41
|
spec.authors = ['unhappychoice']
|
42
42
|
spec.email = ['unhappychoice@gmail.com']
|
43
43
|
|
44
44
|
spec.summary = 'CLI tool for CircleCI'
|
45
45
|
spec.description = 'A command line tool for CircleCI'
|
46
|
-
spec.homepage = 'https://github.com/unhappychoice/
|
46
|
+
spec.homepage = 'https://github.com/unhappychoice/circleci-cli'
|
47
47
|
spec.license = 'MIT'
|
48
48
|
spec.files = project_files
|
49
49
|
spec.bindir = 'exe'
|
data/exe/{circle → circleci-cli}
RENAMED
data/lib/circleci/cli.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'faraday'
|
5
|
+
require 'launchy'
|
6
|
+
require 'terminal-table'
|
7
|
+
require 'highline/import'
|
8
|
+
require 'colorize'
|
9
|
+
require 'rugged'
|
10
|
+
require 'circleci'
|
11
|
+
require 'terminal-notifier'
|
12
|
+
|
13
|
+
require 'circleci/cli/version'
|
14
|
+
require 'circleci/cli/command'
|
15
|
+
require 'circleci/cli/response'
|
16
|
+
require 'circleci/cli/printer'
|
17
|
+
require 'circleci/cli/networking'
|
18
|
+
|
19
|
+
module CircleCI
|
20
|
+
module CLI
|
21
|
+
class Runner < Thor
|
22
|
+
desc 'projects', 'list projects'
|
23
|
+
method_option :format, aliases: 'f', type: :string, banner: 'pretty/simple'
|
24
|
+
def projects
|
25
|
+
Command::ProjectsCommand.run(options)
|
26
|
+
end
|
27
|
+
|
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'
|
32
|
+
def builds
|
33
|
+
Command::BuildsCommand.run(options)
|
34
|
+
end
|
35
|
+
|
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'
|
39
|
+
def build
|
40
|
+
Command::BuildCommand.run(options)
|
41
|
+
end
|
42
|
+
|
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'
|
46
|
+
def browse
|
47
|
+
Command::BrowseCommand.run(options)
|
48
|
+
end
|
49
|
+
|
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'
|
53
|
+
def retry
|
54
|
+
Command::RetryCommand.run(options)
|
55
|
+
end
|
56
|
+
|
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'
|
60
|
+
def cancel
|
61
|
+
Command::CancelCommand.run(options)
|
62
|
+
end
|
63
|
+
|
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'
|
67
|
+
def watch
|
68
|
+
Command::WatchCommand.run(options)
|
69
|
+
end
|
70
|
+
|
71
|
+
desc 'version', 'show gem version'
|
72
|
+
def version
|
73
|
+
say CircleCI::CLI::VERSION
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'circleci/cli/command/base_command'
|
4
|
+
require 'circleci/cli/command/projects_command'
|
5
|
+
require 'circleci/cli/command/builds_command'
|
6
|
+
require 'circleci/cli/command/build_command'
|
7
|
+
require 'circleci/cli/command/browse_command'
|
8
|
+
require 'circleci/cli/command/watch_command'
|
9
|
+
require 'circleci/cli/command/retry_command'
|
10
|
+
require 'circleci/cli/command/cancel_command'
|
11
|
+
|
12
|
+
module CircleCI
|
13
|
+
module CLI
|
14
|
+
module Command; end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CircleCI
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class BaseCommand
|
7
|
+
class << self
|
8
|
+
def setup_token
|
9
|
+
CircleCi.configure do |config|
|
10
|
+
config.token = ENV['CIRCLE_CI_TOKEN'] || ask('Circle CI token ? :')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def project_name(options)
|
15
|
+
if options.project
|
16
|
+
options.project
|
17
|
+
elsif reponame
|
18
|
+
reponame
|
19
|
+
else
|
20
|
+
say Printer::ProjectPrinter.new(Response::Project.all).to_s
|
21
|
+
ask('Input user-name/project-name :')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
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
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_number(options)
|
35
|
+
options.build || ask('Input build number')
|
36
|
+
end
|
37
|
+
|
38
|
+
def should_be_pretty(options)
|
39
|
+
options['format'] != 'simple'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CircleCI
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class BrowseCommand < BaseCommand
|
7
|
+
class << self
|
8
|
+
def run(options)
|
9
|
+
setup_token
|
10
|
+
project = project_name(options)
|
11
|
+
number = options.build
|
12
|
+
Launchy.open url(project, number)
|
13
|
+
end
|
14
|
+
|
15
|
+
def url(project, number)
|
16
|
+
return "https://circleci.com/gh/#{project}" unless number
|
17
|
+
|
18
|
+
"https://circleci.com/gh/#{project}/#{number}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CircleCI
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class BuildCommand < BaseCommand
|
7
|
+
class << self
|
8
|
+
def run(options)
|
9
|
+
setup_token
|
10
|
+
username, reponame = project_name(options).split('/')
|
11
|
+
number = build_number(options)
|
12
|
+
build = Response::Build.get(username, reponame, number)
|
13
|
+
say Printer::StepPrinter.new(build.steps).to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CircleCI
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class BuildsCommand < BaseCommand
|
7
|
+
class << self
|
8
|
+
def run(options)
|
9
|
+
setup_token
|
10
|
+
username, reponame = project_name(options).split('/')
|
11
|
+
|
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
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CircleCI
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class CancelCommand < BaseCommand
|
7
|
+
class << self
|
8
|
+
def run(options)
|
9
|
+
setup_token
|
10
|
+
username, reponame = project_name(options).split('/')
|
11
|
+
number = build_number(options)
|
12
|
+
build = Response::Build.cancel(username, reponame, number)
|
13
|
+
if build.username
|
14
|
+
say "build #{build.project_name} #{build.build_number} is canceled."
|
15
|
+
else
|
16
|
+
say "failed to cancel #{username}/#{reponame} #{number}."
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CircleCI
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class ProjectsCommand < BaseCommand
|
7
|
+
class << self
|
8
|
+
def run(options)
|
9
|
+
setup_token
|
10
|
+
say Printer::ProjectPrinter.new(Response::Project.all, pretty: should_be_pretty(options)).to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CircleCI
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class RetryCommand < BaseCommand
|
7
|
+
class << self
|
8
|
+
def run(options)
|
9
|
+
setup_token
|
10
|
+
username, reponame = project_name(options).split('/')
|
11
|
+
number = build_number(options)
|
12
|
+
build = Response::Build.retry(username, reponame, number)
|
13
|
+
if build.username
|
14
|
+
say "build #{username}/#{reponame} #{build.build_number} is triggered"
|
15
|
+
else
|
16
|
+
say "failed to trigger #{username}/#{reponame} #{number}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CircleCI
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class WatchCommand < BaseCommand
|
7
|
+
class << self
|
8
|
+
def run(options)
|
9
|
+
setup_token
|
10
|
+
setup_client
|
11
|
+
|
12
|
+
build = get_build(options)
|
13
|
+
|
14
|
+
if build&.running?
|
15
|
+
start_watch(build)
|
16
|
+
wait_until_finish
|
17
|
+
finalize(build, build.channel_name)
|
18
|
+
else
|
19
|
+
say 'The build is not running'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def setup_client
|
26
|
+
@client = Networking::CircleCIPusherClient.new
|
27
|
+
@client.connect
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_build(options)
|
31
|
+
username, reponame = project_name(options).split('/')
|
32
|
+
number = build_number options
|
33
|
+
Response::Build.get(username, reponame, number)
|
34
|
+
end
|
35
|
+
|
36
|
+
def start_watch(build)
|
37
|
+
@running = true
|
38
|
+
text = "Start watching #{build.project_name} ##{build.build_number}"
|
39
|
+
print_bordered text
|
40
|
+
TerminalNotifier.notify text
|
41
|
+
|
42
|
+
bind_event_handling build.channel_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def bind_event_handling(channel)
|
46
|
+
@client.bind_event_json(channel, 'newAction') do |json|
|
47
|
+
print_bordered json['log']['name'].green
|
48
|
+
end
|
49
|
+
|
50
|
+
@client.bind_event_json(channel, 'appendAction') do |json|
|
51
|
+
say json['out']['message']
|
52
|
+
end
|
53
|
+
|
54
|
+
@client.bind_event_json(channel, 'updateAction') do |json|
|
55
|
+
@running = json['log']['name'] != 'Disable SSH'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def wait_until_finish
|
60
|
+
sleep(1) while @running
|
61
|
+
end
|
62
|
+
|
63
|
+
def finalize(build, channel)
|
64
|
+
@client.unsubscribe(channel)
|
65
|
+
text = "Finish watching #{build.project_name} ##{build.build_number}"
|
66
|
+
print_bordered text.blue
|
67
|
+
TerminalNotifier.notify text
|
68
|
+
end
|
69
|
+
|
70
|
+
def print_bordered(text)
|
71
|
+
say Terminal::Table.new(rows: [[text]], style: { width: 120 }).to_s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|