octocheck 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bf3fdff5823507d50863f9222ac43ed5bde3a73c
4
+ data.tar.gz: bad327462b3bb0200876409fa706130c17e770ac
5
+ SHA512:
6
+ metadata.gz: 754f6f7db2d24c504ed08af9a967f880035cc0b8dab0087944e50b501c3da3229bd785f9a6722319af6822f3498dd9ad3d51c34d158cbd73fc5dc83f584ef89d
7
+ data.tar.gz: dd39442972c9e03b1780d6bd67be456d4d4471a7469161acdf6dea330896c1a745430860a02c7cfe04100a67febca800dc79031040555eacb74fe2e21ec8328a
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.gem
10
+ test/examples/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in octocheck.gemspec
6
+ gemspec
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ octocheck (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (10.5.0)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ bundler (~> 1.16)
16
+ octocheck!
17
+ rake (~> 10.0)
18
+
19
+ BUNDLED WITH
20
+ 1.16.4
@@ -0,0 +1,88 @@
1
+ # Octocheck
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/octocheck`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'octocheck'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install octocheck
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/octocheck.
36
+ See github status checks in your terminal.
37
+ (https://help.github.com/en/articles/about-status-checks)
38
+
39
+ octocheck --branch myBranchName --project my_repo_name
40
+
41
+ [Options]
42
+
43
+ -b, --branch: defaults to current repo's branch
44
+ -p, --project: defaults to repo directory name
45
+ -o, --org: the Github org that owns the repo (see CONFIGURATION below)
46
+ -r, --revision: defaults to latest revision on current branch
47
+ -t, --token: your github API token (see CONFIGURATION below)
48
+
49
+ [CONFIGURATION]:
50
+
51
+ You can specify your github org and token in a configuration file so
52
+ that you don't need to configure them each time.
53
+
54
+ Put a json formatted file at ~/.config/octocheck/config.json with the
55
+ following data:
56
+
57
+ {
58
+ "token": "< github token value >",
59
+ "org": "< github org name >"
60
+ }
61
+
62
+ [ORG]:
63
+
64
+ Unfortunately when accessing status checks for a repo, the repo's
65
+ organization must be specified. :( The organization can be found in
66
+ the repo's url:
67
+
68
+ https://github.com/ORGNAME/repo_name
69
+
70
+ [TOKEN]:
71
+
72
+ In order to read Github checks, you need to configure (or pass as an
73
+ argument) a token with rights to "repo" permissions:
74
+
75
+ 1. Visit https://github.com/settings/tokens/new
76
+ 2. Generate a new token
77
+ 3. Grant the `repo` permission (leave all others unchecked)
78
+ 4. Paste the token in the configuration file as specified in CONFIGURATION.
79
+
80
+ Unfortunately full `repo` access is needed in order to access Github
81
+ status checks. Hopefully they change that soon.
82
+
83
+ [OUTPUT]
84
+
85
+ Checks are listed in the order they are received. There is some basic
86
+ colorization applied based on the status names. When using Iterm2, the
87
+ status names are links to the check target. Other terminals have the
88
+ link appended to the output.
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "octocheck"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,154 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ lib_dir = File.expand_path(File.join(__dir__, '../lib'))
4
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
5
+
6
+ require "optparse"
7
+ require "json"
8
+ require "octocheck/cli"
9
+
10
+ HELP = <<~TXT
11
+ See github status checks in your terminal.
12
+ (https://help.github.com/en/articles/about-status-checks)
13
+
14
+ octocheck --branch myBranchName --project my_repo_name
15
+
16
+ [Options]
17
+
18
+ -b, --branch: defaults to current repo's branch
19
+ -p, --project: defaults to repo directory name
20
+ -o, --org: the Github org that owns the repo (see CONFIGURATION below)
21
+ -r, --revision: defaults to latest revision on current branch
22
+ -t, --token: your github API token (see CONFIGURATION below)
23
+
24
+ [CONFIGURATION]:
25
+
26
+ You can specify your github org and token in a configuration file so
27
+ that you don't need to configure them each time.
28
+
29
+ Put a json formatted file at ~/.config/octocheck/config.json with the
30
+ following data:
31
+
32
+ {
33
+ "token": "< github token value >",
34
+ "org": "< github org name >"
35
+ }
36
+
37
+ [ORG]:
38
+
39
+ Unfortunately when accessing status checks for a repo, the repo's
40
+ organization must be specified. :( The organization can be found in
41
+ the repo's url:
42
+
43
+ https://github.com/ORGNAME/repo_name
44
+
45
+ [TOKEN]:
46
+
47
+ In order to read Github checks, you need to configure (or pass as an
48
+ argument) a token with rights to "repo" permissions:
49
+
50
+ 1. Visit https://github.com/settings/tokens/new
51
+ 2. Generate a new token
52
+ 3. Grant the `repo` permission (leave all others unchecked)
53
+ 4. Paste the token in the configuration file as specified in CONFIGURATION.
54
+
55
+ Unfortunately full `repo` access is needed in order to access Github
56
+ status checks. Hopefully they change that soon.
57
+
58
+ [OUTPUT]
59
+
60
+ Checks are listed in the order they are received. There is some basic
61
+ colorization applied based on the status names. When using Iterm2, the
62
+ status names are links to the check target. Other terminals have the
63
+ link appended to the output.
64
+ TXT
65
+
66
+ options = {}
67
+ OptionParser.new do |opts|
68
+ opts.banner = "Usage: octocheck [options]"
69
+
70
+ opts.on("-b BRANCH", "--branch BRANCH", "git branch (defaults to current repo branch)") do |b|
71
+ options[:branch] = b
72
+ end
73
+
74
+ opts.on("-p REPONAME", "--reponame REPONAME", "The reponame (defaults to repo directory)") do |p|
75
+ options[:reponame] = p
76
+ end
77
+
78
+ opts.on("-o ORG", "--org ORG", "The github organization name") do |o|
79
+ options[:org] = o
80
+ end
81
+
82
+ opts.on("-t TOKEN", "--token TOKEN", "The github access token") do |t|
83
+ options[:token] = t
84
+ end
85
+
86
+ opts.on("-r REVISION", "--revision REVISION", "The git revision to look for (defaults to revision of latest test run)") do |r|
87
+ options[:revision] = r
88
+
89
+ if !r.match(/\h{40}/)
90
+ warn("#{r} is not a full/valid git revision")
91
+ exit(1)
92
+ end
93
+ end
94
+
95
+ opts.on("-h", "--help", "See help") do
96
+ puts HELP
97
+ exit(0)
98
+ end
99
+
100
+ end.parse!
101
+
102
+ if ARGV.any?
103
+ puts HELP
104
+ exit(1)
105
+ end
106
+
107
+ if !options[:branch]
108
+ options[:branch] = `git rev-parse --abbrev-ref @`.chomp
109
+ if $? != 0
110
+ warn "Could not identify branch. Please specify one"
111
+ exit(1)
112
+ end
113
+ end
114
+
115
+ root_dir = nil
116
+
117
+ if !options[:reponame]
118
+ root_dir ||=
119
+ File.basename(
120
+ `git rev-parse --show-toplevel`
121
+ .chomp
122
+ .tap { raise "detecting root dir failed" unless $?==0}
123
+ )
124
+
125
+ options[:reponame] = root_dir
126
+ end
127
+
128
+ config_file = File.expand_path("~/.config/octocheck/config.json")
129
+ config = File.exist?(config_file) && JSON.parse(File.read(config_file))
130
+
131
+ if !options[:org] && config
132
+ options[:org] = config["org"]
133
+ end
134
+
135
+ if !options[:org]
136
+ warn "Org not specified in command nor in config file. See --help for info."
137
+ exit(1)
138
+ end
139
+
140
+ if !options[:token] && config
141
+ options[:token] = config["token"]
142
+ end
143
+
144
+ if !options[:token]
145
+ warn "Token not specified in command nor in config file. See --help for info."
146
+ exit(1)
147
+ end
148
+
149
+ Octocheck::CLI.call(
150
+ token: options[:token],
151
+ branch: options[:branch],
152
+ repo: options[:reponame],
153
+ org: options[:org]
154
+ )
@@ -0,0 +1,5 @@
1
+ require "octocheck/version"
2
+
3
+ module Octocheck
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,81 @@
1
+ require "uri"
2
+ require "net/http"
3
+ require "json"
4
+
5
+ module Octocheck
6
+ class Api
7
+ attr_accessor :org, :branch, :repo, :token
8
+ def initialize(org:, branch:, repo:, token:)
9
+ @org = org
10
+ @branch = branch
11
+ @repo = repo
12
+ @token = token
13
+ end
14
+
15
+ def statuses
16
+ get("repos/#{org}/#{repo}/commits/#{branch}/statuses")
17
+ .map {|j|
18
+ {
19
+ name: j["context"],
20
+ state: j["state"].downcase,
21
+ url: j["target_url"]
22
+ }
23
+ }
24
+ .uniq {|j| j[:name]}
25
+ end
26
+
27
+ def check_runs
28
+ get("repos/#{org}/#{repo}/commits/#{branch}/check-runs")
29
+ .fetch("check_runs")
30
+ .map { |cr|
31
+ {
32
+ name: cr["name"],
33
+ state: cr["status"].downcase,
34
+ url: cr["details_url"],
35
+ details: check_run_details(cr["output"]["summary"])
36
+ }
37
+ }
38
+ end
39
+
40
+ private
41
+
42
+ def check_run_details(text)
43
+ text
44
+ .split("\n")
45
+ .map { |r|
46
+ structure = r.match(/\[(?<name>.+)\]\((?<url>.+\)) - (?<state>.*)$/)
47
+
48
+ if structure
49
+ {
50
+ name: structure[:name],
51
+ state: structure[:state].downcase,
52
+ url: structure[:url]
53
+ }
54
+ else
55
+ nil
56
+ end
57
+ }.compact
58
+ end
59
+
60
+ def get(path)
61
+ url = File.join("https://api.github.com", path)
62
+ uri = URI.parse(url)
63
+ http = Net::HTTP.new(uri.host, uri.port)
64
+ request = Net::HTTP::Get.new(uri.request_uri)
65
+ headers.each do |k, v|
66
+ request[k] = v
67
+ end
68
+ http.use_ssl = true
69
+ response = http.request(request)
70
+ raise "request failure:\n\n#{response.body}" unless response.code == "200"
71
+ JSON.parse(response.body)
72
+ end
73
+
74
+ def headers
75
+ {
76
+ "Authorization" => "Token #{token}",
77
+ "Accept" => "application/vnd.github.antiope-preview+json"
78
+ }
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,35 @@
1
+ require "octocheck/api"
2
+ require "octocheck/summary"
3
+ require "octocheck/formatters/iterm2"
4
+ require "octocheck/formatters/simple"
5
+
6
+ module Octocheck
7
+ class CLI
8
+ def self.call(org:, branch:, repo:, token:)
9
+ api = Api.new(
10
+ org: org,
11
+ branch: branch,
12
+ repo: repo,
13
+ token: token
14
+ )
15
+
16
+ summary = Summary.new(
17
+ api: api
18
+ )
19
+
20
+ using_iterm2 = (
21
+ ENV["TERM_PROGRAM"] == "iTerm.app" &&
22
+ ENV.fetch("TERM_PROGRAM_VERSION", "").match(/3.[23456789].[123456789]/)
23
+ )
24
+
25
+ formatter =
26
+ if using_iterm2
27
+ Formatters::Iterm2
28
+ else
29
+ Formatters::Simple
30
+ end
31
+
32
+ formatter.new($stdout).format(summary)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ module Octocheck
2
+ module Formatters
3
+ module Color
4
+ CODES = {
5
+ red: 31,
6
+ green: 32,
7
+ yellow: 33,
8
+ blue: 34,
9
+ pink: 35,
10
+ }.freeze
11
+
12
+ CODES.each do |color, code|
13
+ define_method(color) do |string|
14
+ colorize_code(string, code)
15
+ end
16
+ end
17
+
18
+ def colorize(string, color_name)
19
+ return string unless CODES.key?(color_name)
20
+ colorize_code(string, CODES[color_name])
21
+ end
22
+
23
+ private
24
+
25
+ # colorization
26
+ def colorize_code(string, color_code)
27
+ "\e[#{color_code}m#{string}\e[0m"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,58 @@
1
+ require "octocheck/formatters/color"
2
+
3
+ module Octocheck
4
+ module Formatters
5
+ class Iterm2
6
+ GREEN_REGEX = /success|pass|completed|done/
7
+ RED_REGEX = /fail|error/
8
+ BLUE_REGEX = /progress|running/
9
+
10
+ include Color
11
+ attr_reader :io
12
+ def initialize(io)
13
+ @io = io
14
+ end
15
+
16
+ def format(summary)
17
+ cols = []
18
+ summary.statuses.each do |status|
19
+ cols << [
20
+ linkify(status.fetch(:state), status.fetch(:url)),
21
+ status.fetch(:name)
22
+ ].join(" ")
23
+ end
24
+
25
+ summary.check_runs.each do |run|
26
+ cols << [
27
+ linkify(run.fetch(:state), run.fetch(:url)),
28
+ run.fetch(:name)
29
+ ].join(" ")
30
+
31
+ run.fetch(:details).each do |detail|
32
+ cols << [
33
+ linkify(detail.fetch(:state), detail.fetch(:url)),
34
+ detail.fetch(:name)
35
+ ].join(" ")
36
+ end
37
+ end
38
+
39
+ io.puts(cols.join("\n"))
40
+ end
41
+
42
+ def linkify(text, url)
43
+ colorized_text =
44
+ if text.match(GREEN_REGEX)
45
+ green(text)
46
+ elsif text.match(RED_REGEX)
47
+ red(text)
48
+ elsif text.match(BLUE_REGEX)
49
+ blue(text)
50
+ else
51
+ yellow(text)
52
+ end
53
+
54
+ "\e]8;;#{url}\a#{colorized_text}\e]8;;\a"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,58 @@
1
+ require "octocheck/formatters/color"
2
+
3
+ module Octocheck
4
+ module Formatters
5
+ class Simple
6
+ GREEN_REGEX = /success|pass|completed|done/
7
+ RED_REGEX = /fail|error/
8
+ BLUE_REGEX = /progress|running/
9
+
10
+ include Color
11
+ attr_reader :io
12
+ def initialize(io)
13
+ @io = io
14
+ end
15
+
16
+ def format(summary)
17
+ cols = []
18
+ summary.statuses.each do |status|
19
+ cols << [
20
+ colorize(status.fetch(:state)),
21
+ status.fetch(:name),
22
+ status.fetch(:url)
23
+ ].join(" ")
24
+ end
25
+
26
+ summary.check_runs.each do |run|
27
+ cols << [
28
+ colorize(run.fetch(:state)),
29
+ run.fetch(:name),
30
+ run.fetch(:url)
31
+ ].join(" ")
32
+
33
+ run.fetch(:details).each do |detail|
34
+ cols << [
35
+ colorize(detail.fetch(:state)),
36
+ detail.fetch(:name),
37
+ detail.fetch(:url)
38
+ ].join(" ")
39
+ end
40
+ end
41
+
42
+ io.puts(cols.join("\n"))
43
+ end
44
+
45
+ def colorize(text)
46
+ if text.match(GREEN_REGEX)
47
+ green(text)
48
+ elsif text.match(RED_REGEX)
49
+ red(text)
50
+ elsif text.match(BLUE_REGEX)
51
+ blue(text)
52
+ else
53
+ yellow(text)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,16 @@
1
+ module Octocheck
2
+ class Summary
3
+ attr_accessor :api
4
+ def initialize(api:)
5
+ @api = api
6
+ end
7
+
8
+ def check_runs
9
+ @check_runs ||= api.check_runs
10
+ end
11
+
12
+ def statuses
13
+ @statuses ||= api.statuses
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module Octocheck
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,25 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "octocheck/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "octocheck"
8
+ spec.version = Octocheck::VERSION
9
+ spec.authors = ["Pete Kinnecom"]
10
+ spec.email = ["git@k7u7.com"]
11
+
12
+ spec.summary = "See github checks in your terminal"
13
+ spec.homepage = "https://github.com/petekinnecom/octocheck"
14
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
15
+
16
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
17
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.16"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: octocheck
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Pete Kinnecom
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-03-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description:
42
+ email:
43
+ - git@k7u7.com
44
+ executables:
45
+ - octocheck
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - Gemfile.lock
52
+ - README.md
53
+ - Rakefile
54
+ - bin/console
55
+ - bin/setup
56
+ - exe/octocheck
57
+ - lib/octocheck.rb
58
+ - lib/octocheck/api.rb
59
+ - lib/octocheck/cli.rb
60
+ - lib/octocheck/formatters/color.rb
61
+ - lib/octocheck/formatters/iterm2.rb
62
+ - lib/octocheck/formatters/simple.rb
63
+ - lib/octocheck/summary.rb
64
+ - lib/octocheck/version.rb
65
+ - octocheck.gemspec
66
+ homepage: https://github.com/petekinnecom/octocheck
67
+ licenses: []
68
+ metadata:
69
+ allowed_push_host: https://rubygems.org
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.5.2
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: See github checks in your terminal
90
+ test_files: []