octocheck 0.1.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.
@@ -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: []