semaphore-status 0.0.1
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +60 -0
- data/Rakefile +1 -0
- data/bin/sst +122 -0
- data/lib/semaphore-status/version.rb +5 -0
- data/lib/semaphore-status.rb +129 -0
- data/semaphore-status.gemspec +22 -0
- metadata +71 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Aleksandar Diklic
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Semaphore-status
|
2
|
+
|
3
|
+
Command-line interface for checking projects status on Semaphore.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```
|
8
|
+
$ gem install semaphore-status
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
Running 'sst' in project repository that is on Semaphore, Semaphore-status will list only that project, otherwise sst will list you all projects you have on Semaphore.
|
14
|
+
To list all projects in any directorium, simply provide flag -a 'sst -a'.
|
15
|
+
|
16
|
+
To check only one project, you can provide project name like 'sst <project_name>'.
|
17
|
+
|
18
|
+
Semaphore-status have interactive mood, in which you can see live status of your build (refresh rate 5sec).
|
19
|
+
|
20
|
+
To change authentication token you run 'sst -t <your_token_>'.
|
21
|
+
|
22
|
+
Running 'sst' in interactive mode you will see live status of your build (updates every 5sec).
|
23
|
+
|
24
|
+
```
|
25
|
+
sst - Show build status for projects in which repo you are (otherwise shows all projects)
|
26
|
+
sst <project_name> - Show build status for project with name <project_name>
|
27
|
+
sst -a - Show all projects
|
28
|
+
sst -i - Interactive mode
|
29
|
+
sst -i <project_name> - Run Semaphore-status in interactive mode for project with name <project_name>
|
30
|
+
sst -t <your_token> - Sets authentication token
|
31
|
+
sst -h - Shows help
|
32
|
+
```
|
33
|
+
|
34
|
+
|
35
|
+
## Options:
|
36
|
+
|
37
|
+
```
|
38
|
+
-i - Interactive mode
|
39
|
+
-a - All projects
|
40
|
+
-t - Set authentication token
|
41
|
+
-h - Prints help
|
42
|
+
```
|
43
|
+
|
44
|
+
## Screenshots
|
45
|
+
|
46
|
+

|
47
|
+
|
48
|
+
## Contributing
|
49
|
+
|
50
|
+
1. Fork it
|
51
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
52
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
53
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
54
|
+
5. Create new Pull Request
|
55
|
+
|
56
|
+
|
57
|
+
## License
|
58
|
+
|
59
|
+
Semaphore-status is released under the MIT License.
|
60
|
+
Developed by [rastasheep](https://github.com/rastasheep).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/sst
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
TOKEN_PATH = "#{ENV['HOME']}/.semaphore_token"
|
5
|
+
REFRESH_INTERVAL = 5
|
6
|
+
|
7
|
+
help = <<-MSG
|
8
|
+
This utility shows current status of your projects on Semaphore.
|
9
|
+
|
10
|
+
Running 'sst' in project repository that is on Semaphore, Semaphore-status will list only that project, otherwise sst will list you all projects you have on Semaphore.
|
11
|
+
To list all projects in any directorium, simply provide flag -a 'sst -a'.
|
12
|
+
|
13
|
+
To check only one project, you can provide project name like 'sst <project_name>'.
|
14
|
+
|
15
|
+
Semaphore-status have interactive mood, in which you can see live status of your build (refresh rate 5sec).
|
16
|
+
|
17
|
+
To change authentication token you run 'sst -t <your_token_>'.
|
18
|
+
|
19
|
+
Running 'sst' in interactive mode you will see live status of your build (updates every 5sec).
|
20
|
+
|
21
|
+
Options:
|
22
|
+
|
23
|
+
-i (--interactive) Interactive mode
|
24
|
+
-a (--all) All projects
|
25
|
+
-t (--token) Set authentication token
|
26
|
+
-h (--help) Prints help
|
27
|
+
|
28
|
+
Usage:
|
29
|
+
|
30
|
+
sst
|
31
|
+
sst <project_name>
|
32
|
+
sst -a
|
33
|
+
sst -i
|
34
|
+
sst -i <project_name>
|
35
|
+
sst -t <your_token>
|
36
|
+
sst -h
|
37
|
+
MSG
|
38
|
+
|
39
|
+
if system('git rev-parse 2>/dev/null ')
|
40
|
+
git_repo_cmd = %q(git remote -v | head -n1 | awk '{print $2}' | sed 's/.*\///' | sed 's/\.git//')
|
41
|
+
query = `#{git_repo_cmd}`.chomp
|
42
|
+
else
|
43
|
+
query = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
if i = ARGV.index('-t') or i = ARGV.index('--token')
|
47
|
+
token = ARGV[i + 1]
|
48
|
+
|
49
|
+
file = File.open(TOKEN_PATH, "w")
|
50
|
+
file.write(token)
|
51
|
+
|
52
|
+
puts 'Token successfully saved.'
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
|
56
|
+
if ARGV.index('-h') or ARGV.index('--help')
|
57
|
+
puts help
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
|
61
|
+
require "semaphore-status"
|
62
|
+
|
63
|
+
def get_projects(query = nil, interactive = false)
|
64
|
+
puts "\e[H\e[2J" if interactive
|
65
|
+
if query
|
66
|
+
sst.tree(query)
|
67
|
+
else
|
68
|
+
sst.tree
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
unless ENV['SEMAPHORE_API_KEY']
|
73
|
+
|
74
|
+
if !File.exist?(TOKEN_PATH)
|
75
|
+
token = ''
|
76
|
+
puts 'Please enter authentication token for your Semaphore account:'
|
77
|
+
while token.lstrip.empty?
|
78
|
+
token = gets.chomp
|
79
|
+
end
|
80
|
+
|
81
|
+
file = File.open(TOKEN_PATH, "w")
|
82
|
+
file.write(token)
|
83
|
+
ENV['SEMAPHORE_API_KEY'] = token
|
84
|
+
|
85
|
+
puts 'Token successfully saved.'
|
86
|
+
|
87
|
+
get_projects(query)
|
88
|
+
exit
|
89
|
+
else
|
90
|
+
key = File.read(TOKEN_PATH).chomp
|
91
|
+
if key.empty?
|
92
|
+
puts 'Please provide new authentication token with: sst -t <your_token>.'
|
93
|
+
else
|
94
|
+
ENV['SEMAPHORE_API_KEY'] = key
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
if ARGV.index('-a') or ARGV.index('--all')
|
100
|
+
get_projects()
|
101
|
+
exit
|
102
|
+
end
|
103
|
+
|
104
|
+
if i = ARGV.index('-i') or i = ARGV.index('--interactive')
|
105
|
+
|
106
|
+
interrupted = false
|
107
|
+
trap("INT") { interrupted = true }
|
108
|
+
|
109
|
+
query = ARGV[i + 1] if ARGV[i + 1]
|
110
|
+
until interrupted do
|
111
|
+
puts 'Press Ctrl-C to exit semaphore-status.'
|
112
|
+
get_projects(query, true)
|
113
|
+
sleep 5
|
114
|
+
end
|
115
|
+
exit
|
116
|
+
end
|
117
|
+
|
118
|
+
if ARGV.empty?
|
119
|
+
get_projects(query)
|
120
|
+
else
|
121
|
+
get_projects(ARGV[0])
|
122
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'semaphore-status/version'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'json'
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
|
9
|
+
class SemaphoreClient
|
10
|
+
|
11
|
+
API_URL = 'https://semaphoreapp.com/api/v1/projects?auth_token='
|
12
|
+
|
13
|
+
def initialize(token)
|
14
|
+
response = open(API_URL+token).read
|
15
|
+
@json_response = JSON.parse(response)
|
16
|
+
end
|
17
|
+
|
18
|
+
def tree(query = nil)
|
19
|
+
if query
|
20
|
+
projects = search(query)
|
21
|
+
if projects.empty?
|
22
|
+
puts 'This git repository is not on Semaphore.'
|
23
|
+
self.tree
|
24
|
+
return
|
25
|
+
end
|
26
|
+
else
|
27
|
+
projects = @json_response
|
28
|
+
end
|
29
|
+
|
30
|
+
if @json_response.size == projects.size
|
31
|
+
puts 'Your projects on Semaphore:'
|
32
|
+
else
|
33
|
+
puts "Displaying #{projects.size} of #{@json_response.size} projects:"
|
34
|
+
end
|
35
|
+
|
36
|
+
projects.each_with_index do |project, index|
|
37
|
+
if index+1 == projects.size
|
38
|
+
print_project(project,'last')
|
39
|
+
else
|
40
|
+
print_project(project)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def search(query)
|
48
|
+
@json_response.select{|project| project['name'] == query}
|
49
|
+
end
|
50
|
+
|
51
|
+
def print_project(project, order = 'first')
|
52
|
+
if order == 'last'
|
53
|
+
puts "└── #{yellow project['name']}"
|
54
|
+
print_branches(project['branches'],'last')
|
55
|
+
else
|
56
|
+
puts "├── #{yellow project['name']}"
|
57
|
+
print_branches(project['branches'])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def print_branches(branches, order = 'first')
|
62
|
+
branches.each_with_index do |branch, index|
|
63
|
+
print '|' if order != 'last'
|
64
|
+
print ' '
|
65
|
+
if index == branches.length - 1
|
66
|
+
print_branch(branch, 'last')
|
67
|
+
else
|
68
|
+
print_branch(branch)
|
69
|
+
end
|
70
|
+
puts ""
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def print_branch(branch, order = 'first' )
|
75
|
+
if order == 'last'
|
76
|
+
print "└── "
|
77
|
+
else
|
78
|
+
print "├── "
|
79
|
+
end
|
80
|
+
print branch_info(branch)
|
81
|
+
end
|
82
|
+
|
83
|
+
def branch_info(branch)
|
84
|
+
finished_at = branch['finished_at']
|
85
|
+
info = branch['branch_name'].to_s + " :: " + branch['result'].to_s + " (" + branch['build_number'].to_s + ")\e[0m :: " + calculate_time(finished_at)
|
86
|
+
if branch['result'] == 'passed'
|
87
|
+
green(info)
|
88
|
+
elsif branch['result'] == 'failed'
|
89
|
+
red(info)
|
90
|
+
else
|
91
|
+
blue(info)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def colorize(text, color_code)
|
96
|
+
"#{color_code}#{text}\033[0m"
|
97
|
+
end
|
98
|
+
|
99
|
+
def red(text); colorize(text, "\e[0;31m"); end
|
100
|
+
def green(text); colorize(text, "\e[0;32m"); end
|
101
|
+
def blue(text); colorize(text, "\e[0;34m"); end
|
102
|
+
def yellow(text); colorize(text, "\e[0;33m"); end
|
103
|
+
|
104
|
+
def calculate_time(finished)
|
105
|
+
if finished
|
106
|
+
duration(Time.now - Time.parse(finished))
|
107
|
+
else
|
108
|
+
"Not built yet"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def duration(time)
|
113
|
+
secs = time.to_int
|
114
|
+
mins = secs / 60
|
115
|
+
hours = mins / 60
|
116
|
+
days = hours / 24
|
117
|
+
|
118
|
+
if days > 0
|
119
|
+
"#{days} days and #{hours % 24} hours ago"
|
120
|
+
elsif hours > 0
|
121
|
+
"#{hours} hours and #{mins % 60} minutes ago"
|
122
|
+
elsif mins > 0
|
123
|
+
"#{mins} minutes and #{secs % 60} seconds ago"
|
124
|
+
elsif secs >= 0
|
125
|
+
"#{secs} seconds ago"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'semaphore-status/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "semaphore-status"
|
8
|
+
gem.version = Semaphore::Status::VERSION
|
9
|
+
gem.authors = ["Aleksandar Diklic"]
|
10
|
+
gem.email = ["aleksandar@renderedtext.com"]
|
11
|
+
gem.description = %q{Command-line interface for checking projects status on Semaphore.}
|
12
|
+
gem.summary = %q{Semaphore status for command-line}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency "json"
|
21
|
+
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: semaphore-status
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Aleksandar Diklic
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Command-line interface for checking projects status on Semaphore.
|
31
|
+
email:
|
32
|
+
- aleksandar@renderedtext.com
|
33
|
+
executables:
|
34
|
+
- sst
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
files:
|
38
|
+
- .gitignore
|
39
|
+
- Gemfile
|
40
|
+
- LICENSE.txt
|
41
|
+
- README.md
|
42
|
+
- Rakefile
|
43
|
+
- bin/sst
|
44
|
+
- lib/semaphore-status.rb
|
45
|
+
- lib/semaphore-status/version.rb
|
46
|
+
- semaphore-status.gemspec
|
47
|
+
homepage: ''
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.8.23
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Semaphore status for command-line
|
71
|
+
test_files: []
|