compare_linker 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +44 -0
- data/LICENSE.txt +22 -0
- data/README.md +15 -0
- data/Rakefile +7 -0
- data/compare_linker.gemspec +27 -0
- data/guides/jenkins_setup_guide.md +85 -0
- data/lib/compare_linker.rb +69 -0
- data/lib/compare_linker/formatter/markdown.rb +30 -0
- data/lib/compare_linker/formatter/text.rb +30 -0
- data/lib/compare_linker/github_link_finder.rb +33 -0
- data/lib/compare_linker/github_tag_finder.rb +18 -0
- data/lib/compare_linker/lockfile_comparator.rb +37 -0
- data/lib/compare_linker/lockfile_fetcher.rb +24 -0
- data/lib/compare_linker/version.rb +3 -0
- data/lib/compare_linker/webhook_payload.rb +22 -0
- data/payload.rb +10 -0
- data/runner.rb +32 -0
- data/spec/fixtures/rails.json +1 -0
- data/spec/fixtures/web_translate_it.json +1 -0
- data/spec/lib/compare_linker/github_link_finder_spec.rb +32 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/load_fixture.rb +5 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: af95f0a2fa32ca45c3466eaea99a42a60f459ee8
|
4
|
+
data.tar.gz: c326f2ce50e6ee13d95fb6902fd5485c670388cc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f2658bdebc63b821bfe21fe64ac000ebcbef6ae64bf9259f694bb50dda824bcc866e2d9f12e7c308ea62b13132d3b5e49e77ae36458751471db8bb7159c41dc8
|
7
|
+
data.tar.gz: 7141938c57780fee24b2e814cdc01b4fabcb21f23060969c14a9564c88d88fe95a4d5310d0c8c5ef55e688895ce4c04f19251bb105dd645ae46abb7bc52f67b4
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
compare_linker (1.1.1)
|
5
|
+
httpclient
|
6
|
+
octokit
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
addressable (2.3.7)
|
12
|
+
diff-lcs (1.2.5)
|
13
|
+
faraday (0.9.1)
|
14
|
+
multipart-post (>= 1.2, < 3)
|
15
|
+
httpclient (2.6.0.1)
|
16
|
+
multipart-post (2.0.0)
|
17
|
+
octokit (3.8.0)
|
18
|
+
sawyer (~> 0.6.0, >= 0.5.3)
|
19
|
+
rake (10.4.2)
|
20
|
+
rspec (3.2.0)
|
21
|
+
rspec-core (~> 3.2.0)
|
22
|
+
rspec-expectations (~> 3.2.0)
|
23
|
+
rspec-mocks (~> 3.2.0)
|
24
|
+
rspec-core (3.2.1)
|
25
|
+
rspec-support (~> 3.2.0)
|
26
|
+
rspec-expectations (3.2.0)
|
27
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
28
|
+
rspec-support (~> 3.2.0)
|
29
|
+
rspec-mocks (3.2.1)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.2.0)
|
32
|
+
rspec-support (3.2.2)
|
33
|
+
sawyer (0.6.0)
|
34
|
+
addressable (~> 2.3.5)
|
35
|
+
faraday (~> 0.8, < 0.10)
|
36
|
+
|
37
|
+
PLATFORMS
|
38
|
+
ruby
|
39
|
+
|
40
|
+
DEPENDENCIES
|
41
|
+
bundler (~> 1.3)
|
42
|
+
compare_linker!
|
43
|
+
rake
|
44
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Kensuke Nagae
|
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,15 @@
|
|
1
|
+
Compare Linker
|
2
|
+
==============
|
3
|
+
|
4
|
+
Create GitHub's compare view URLs for pull request from diff of `Gemfile.lock` (and post comment to pull request).
|
5
|
+
|
6
|
+
![screen shot 2014-01-27 at 2 25 14 am](https://f.cloud.github.com/assets/10515/2004469/de374152-86ae-11e3-84a0-19e2ef40b959.png)
|
7
|
+
|
8
|
+
[GitHub Compare View](https://github.com/blog/612-introducing-github-compare-view) rocks.But [diff of Gemfile.lock](https://github.com/kyanny/compare_linker_demo/pull/14/files) sucks. So I made Compare Linker.
|
9
|
+
|
10
|
+
Rack app for listening GitHub Webhook
|
11
|
+
-------------------------------------
|
12
|
+
|
13
|
+
There's rack application for Compare Linker with GitHub's Webhook.
|
14
|
+
|
15
|
+
https://github.com/kyanny/compare_linker_rack_app
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'compare_linker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "compare_linker"
|
8
|
+
spec.version = CompareLinker::VERSION
|
9
|
+
spec.authors = ["Kensuke Nagae"]
|
10
|
+
spec.email = ["kyanny@gmail.com"]
|
11
|
+
spec.description = %q{Create GitHub's compare view URLs for pull request from diff of Gemfile.lock}
|
12
|
+
spec.summary = %q{Create GitHub's compare view URLs for pull request}
|
13
|
+
spec.homepage = "https://github.com/masutaka/compare_linker"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "octokit"
|
22
|
+
spec.add_dependency "httpclient"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
CompareLinker Jenkins Setup Guide
|
2
|
+
=================================
|
3
|
+
|
4
|
+
This guide describes how to setup Jenkins job for CompareLinker.
|
5
|
+
|
6
|
+
Before setup, you have to install and run your Jenkins CI server.
|
7
|
+
And you have to install Ruby 1.9 or higher with `bundler` gem in your Jenkins server, too.
|
8
|
+
|
9
|
+
1. Install "Parameterized Trigger Plugin"
|
10
|
+
-----------------------------------------
|
11
|
+
|
12
|
+
https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin
|
13
|
+
|
14
|
+
1. Create new job
|
15
|
+
-----------------
|
16
|
+
|
17
|
+
Create new "Build a free-style software project" job.
|
18
|
+
|
19
|
+
3. Check "This build is parameterized" and parameters
|
20
|
+
-----------------------------------------------------
|
21
|
+
|
22
|
+
You need to add two string parameters:
|
23
|
+
|
24
|
+
1. `payload` (default value is `none`)
|
25
|
+
2. `OCTOKIT_ACCESS_TOKEN` (default value is your GitHub access token)
|
26
|
+
|
27
|
+
If you don't have GitHub access token, you can get it from https://github.com/settings/tokens/new.
|
28
|
+
|
29
|
+
![screen shot 2014-01-19 at 12 07 29 am](https://f.cloud.github.com/assets/10515/1947496/cb857bac-8058-11e3-9e02-598942018d7a.png)
|
30
|
+
|
31
|
+
4. Setup "Source Code Management" section
|
32
|
+
-----------------------------------------
|
33
|
+
|
34
|
+
Choose "Git". Repository URL is https://github.com/kyanny/compare_linker.git.
|
35
|
+
|
36
|
+
![screen shot 2014-01-19 at 12 07 33 am](https://f.cloud.github.com/assets/10515/1947518/6ebf3cb8-8059-11e3-936a-566797ed8c01.png)
|
37
|
+
|
38
|
+
5. Setup "Build Triggers" section
|
39
|
+
---------------------------------
|
40
|
+
|
41
|
+
Check "Trigger builds remotely".
|
42
|
+
|
43
|
+
If you want to enable authentication to start build job, fill in "Authentication Token" field.
|
44
|
+
|
45
|
+
![screen shot 2014-01-19 at 12 07 38 am](https://f.cloud.github.com/assets/10515/1947537/834b0da0-805a-11e3-8e90-a6a22ca1f2ae.png)
|
46
|
+
|
47
|
+
6. Setup "Build" section
|
48
|
+
------------------------
|
49
|
+
|
50
|
+
Choose "Execute Shell". Command is below.
|
51
|
+
|
52
|
+
```
|
53
|
+
#!/bin/bash
|
54
|
+
|
55
|
+
bundle install --path vendor/bundle
|
56
|
+
bundle exec ruby runner.rb
|
57
|
+
```
|
58
|
+
|
59
|
+
7. Add GitHub Webhook to your repository
|
60
|
+
----------------------------------------
|
61
|
+
|
62
|
+
CompareLinker rack app listens GitHub's pull request webhook.
|
63
|
+
Webhook URL is like `http://example.com/jenkins/[job_name]/buildWithParameters?token=[jenkins_auth_token]`.
|
64
|
+
|
65
|
+
You can add webhook to your repository by `curl(1)`:
|
66
|
+
|
67
|
+
```
|
68
|
+
$ curl -H 'Authorization: token [your_github_access_token]' \
|
69
|
+
-d '{"name": "web", "active": true, "events": ["pull_request"], "config": {"url": "your_jenkins_webhook_url"}}' \
|
70
|
+
https://api.github.com/repos/[repo_owner_account]/[repo_name]/hooks
|
71
|
+
```
|
72
|
+
|
73
|
+
Or by http://www.hurl.it/:
|
74
|
+
|
75
|
+
![screen shot 2014-01-19 at 1 25 12 am](https://f.cloud.github.com/assets/10515/1947590/6da9392e-805d-11e3-8304-ab8648c7a7e0.png)
|
76
|
+
|
77
|
+
If your jenkins requires authentication, you need basic auth to access jenkins.
|
78
|
+
You can embed basic auth credential to URL like "http://user@pass:host" style.
|
79
|
+
|
80
|
+
8. Open new pull request
|
81
|
+
------------------------
|
82
|
+
|
83
|
+
That's all! When your repository gets new open pull request, you will see new comment like that:
|
84
|
+
|
85
|
+
![screen shot](http://gyazo.com/22001fae8ba6ccba602cc6fa9886b05d.png)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "octokit"
|
2
|
+
require_relative "compare_linker/formatter/text"
|
3
|
+
require_relative "compare_linker/formatter/markdown"
|
4
|
+
require_relative "compare_linker/github_link_finder"
|
5
|
+
require_relative "compare_linker/github_tag_finder"
|
6
|
+
require_relative "compare_linker/lockfile_comparator"
|
7
|
+
require_relative "compare_linker/lockfile_fetcher"
|
8
|
+
|
9
|
+
class CompareLinker
|
10
|
+
attr_reader :repo_full_name, :pr_number, :compare_links
|
11
|
+
attr_accessor :formatter, :octokit
|
12
|
+
|
13
|
+
def initialize(repo_full_name, pr_number)
|
14
|
+
@repo_full_name = repo_full_name
|
15
|
+
@pr_number = pr_number
|
16
|
+
@octokit ||= Octokit::Client.new(access_token: ENV["OCTOKIT_ACCESS_TOKEN"])
|
17
|
+
@formatter = Formatter::Text.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def make_compare_links
|
21
|
+
if octokit.pull_request_files(repo_full_name, pr_number).find { |resource| resource.filename == "Gemfile.lock" }
|
22
|
+
pull_request = octokit.pull_request(repo_full_name, pr_number)
|
23
|
+
|
24
|
+
fetcher = LockfileFetcher.new(octokit)
|
25
|
+
old_lockfile = fetcher.fetch(repo_full_name, pull_request.base.sha)
|
26
|
+
new_lockfile = fetcher.fetch(repo_full_name, pull_request.head.sha)
|
27
|
+
|
28
|
+
comparator = LockfileComparator.new
|
29
|
+
comparator.compare(old_lockfile, new_lockfile)
|
30
|
+
@compare_links = comparator.updated_gems.map { |gem_name, gem_info|
|
31
|
+
if gem_info[:owner].nil?
|
32
|
+
finder = GithubLinkFinder.new(octokit)
|
33
|
+
finder.find(gem_name)
|
34
|
+
if finder.repo_owner.nil?
|
35
|
+
gem_info[:homepage_uri] = finder.homepage_uri
|
36
|
+
formatter.format(gem_info)
|
37
|
+
else
|
38
|
+
gem_info[:repo_owner] = finder.repo_owner
|
39
|
+
gem_info[:repo_name] = finder.repo_name
|
40
|
+
|
41
|
+
tag_finder = GithubTagFinder.new(octokit)
|
42
|
+
old_tag = tag_finder.find(finder.repo_full_name, gem_info[:old_ver])
|
43
|
+
new_tag = tag_finder.find(finder.repo_full_name, gem_info[:new_ver])
|
44
|
+
|
45
|
+
if old_tag && new_tag
|
46
|
+
gem_info[:old_tag] = old_tag.name
|
47
|
+
gem_info[:new_tag] = new_tag.name
|
48
|
+
formatter.format(gem_info)
|
49
|
+
else
|
50
|
+
formatter.format(gem_info)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
else
|
54
|
+
formatter.format(gem_info)
|
55
|
+
end
|
56
|
+
}
|
57
|
+
@compare_links
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_comment(repo_full_name, pr_number, compare_links)
|
62
|
+
res = octokit.add_comment(
|
63
|
+
repo_full_name,
|
64
|
+
pr_number,
|
65
|
+
compare_links
|
66
|
+
)
|
67
|
+
"https://github.com/#{repo_full_name}/pull/#{pr_number}#issuecomment-#{res.id}"
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
|
3
|
+
class CompareLinker
|
4
|
+
class Formatter
|
5
|
+
class Markdown
|
6
|
+
def format(gem_info)
|
7
|
+
g = OpenStruct.new(gem_info)
|
8
|
+
|
9
|
+
text = case
|
10
|
+
when g.owner && g.old_rev && g.new_rev
|
11
|
+
"* #{g.gem_name}: https://github.com/#{g.owner}/#{g.gem_name}/compare/#{g.old_rev}...#{g.new_rev}"
|
12
|
+
when g.homepage_uri
|
13
|
+
"* [#{g.gem_name}](#{g.homepage_uri}): #{g.old_ver} => #{g.new_ver}"
|
14
|
+
when g.old_tag && g.new_tag
|
15
|
+
"* #{g.gem_name}: https://github.com/#{g.repo_owner}/#{g.repo_name}/compare/#{g.old_tag}...#{g.new_tag}"
|
16
|
+
when g.repo_owner && g.repo_name
|
17
|
+
"* [#{g.gem_name}](https://github.com/#{g.repo_owner}/#{g.repo_name}): #{g.old_ver} => #{g.new_ver}"
|
18
|
+
else
|
19
|
+
"* #{g.gem_name}: (link not found) #{g.old_ver} => #{g.new_ver}"
|
20
|
+
end
|
21
|
+
|
22
|
+
if (g.old_tag && g.new_tag && g.new_tag.to_f < g.old_tag.to_f) || g.new_ver.to_f < g.old_ver.to_f
|
23
|
+
text += " (downgrade)"
|
24
|
+
end
|
25
|
+
|
26
|
+
text
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
|
3
|
+
class CompareLinker
|
4
|
+
class Formatter
|
5
|
+
class Text
|
6
|
+
def format(gem_info)
|
7
|
+
g = OpenStruct.new(gem_info)
|
8
|
+
|
9
|
+
text = case
|
10
|
+
when g.owner && g.old_rev && g.new_rev
|
11
|
+
"#{g.gem_name}: https://github.com/#{g.owner}/#{g.gem_name}/compare/#{g.old_rev}...#{g.new_rev}"
|
12
|
+
when g.homepage_uri
|
13
|
+
"#{g.gem_name} (#{g.homepage_uri}): #{g.old_ver} => #{g.new_ver}"
|
14
|
+
when g.old_tag && g.new_tag
|
15
|
+
"#{g.gem_name}: https://github.com/#{g.repo_owner}/#{g.repo_name}/compare/#{g.old_tag}...#{g.new_tag}"
|
16
|
+
when g.repo_owner && g.repo_name
|
17
|
+
"#{g.gem_name}: https://github.com/#{g.repo_owner}/#{g.repo_name} #{g.old_ver} => #{g.new_ver}"
|
18
|
+
else
|
19
|
+
"#{g.gem_name} (link not found): #{g.old_ver} => #{g.new_ver}"
|
20
|
+
end
|
21
|
+
|
22
|
+
if (g.old_tag && g.new_tag && g.new_tag.to_f < g.old_tag.to_f) || g.new_ver.to_f < g.old_ver.to_f
|
23
|
+
text += " (downgrade)"
|
24
|
+
end
|
25
|
+
|
26
|
+
text
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "json"
|
2
|
+
require "httpclient"
|
3
|
+
|
4
|
+
class CompareLinker
|
5
|
+
class GithubLinkFinder
|
6
|
+
attr_reader :octokit, :repo_owner, :repo_name, :homepage_uri
|
7
|
+
|
8
|
+
def initialize(octokit)
|
9
|
+
@octokit = octokit
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(gem_name)
|
13
|
+
gem_info = JSON.parse(
|
14
|
+
HTTPClient.get("https://rubygems.org/api/v1/gems/#{gem_name}.json").body
|
15
|
+
)
|
16
|
+
|
17
|
+
github_url = [
|
18
|
+
gem_info["homepage_uri"],
|
19
|
+
gem_info["source_code_uri"]
|
20
|
+
].find { |uri| uri.to_s.match(/github\.com\//) }
|
21
|
+
|
22
|
+
if github_url.nil?
|
23
|
+
@homepage_uri = gem_info["homepage_uri"]
|
24
|
+
else
|
25
|
+
_, @repo_owner, @repo_name = github_url.match(%r!github\.com/([^/]+)/([^/]+)!).to_a
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def repo_full_name
|
30
|
+
"#{@repo_owner}/#{repo_name}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CompareLinker
|
2
|
+
class GithubTagFinder
|
3
|
+
attr_reader :octokit
|
4
|
+
|
5
|
+
def initialize(octokit)
|
6
|
+
@octokit = octokit
|
7
|
+
end
|
8
|
+
|
9
|
+
def find(repo_full_name, gem_version)
|
10
|
+
tags = octokit.tags(repo_full_name)
|
11
|
+
if tags
|
12
|
+
tags.find { |tag|
|
13
|
+
tag.name == gem_version || tag.name == "v#{gem_version}"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class CompareLinker
|
2
|
+
class LockfileComparator
|
3
|
+
attr_accessor :updated_gems
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@updated_gems = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def compare(old_lockfile, new_lockfile)
|
10
|
+
old_lockfile.specs.each do |old_spec|
|
11
|
+
new_lockfile.specs.each do |new_spec|
|
12
|
+
if old_spec.name == new_spec.name
|
13
|
+
old_rev = old_spec.source.options["revision"]
|
14
|
+
new_rev = new_spec.source.options["revision"]
|
15
|
+
if old_rev && new_rev && (old_rev != new_rev)
|
16
|
+
_, owner, gem_name = old_spec.source.uri.match(/github\.com\/([^\/]+)\/([^.]+)/).to_a
|
17
|
+
updated_gems[old_spec.name] = {
|
18
|
+
owner: owner,
|
19
|
+
gem_name: gem_name,
|
20
|
+
old_rev: old_rev,
|
21
|
+
new_rev: new_rev,
|
22
|
+
}
|
23
|
+
elsif old_spec.version != new_spec.version
|
24
|
+
updated_gems[old_spec.name] = {
|
25
|
+
owner: nil,
|
26
|
+
gem_name: old_spec.name,
|
27
|
+
old_ver: old_spec.version.to_s,
|
28
|
+
new_ver: new_spec.version.to_s,
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
updated_gems
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "bundler"
|
2
|
+
|
3
|
+
class CompareLinker
|
4
|
+
class LockfileFetcher
|
5
|
+
attr_reader :octokit
|
6
|
+
|
7
|
+
def initialize(octokit)
|
8
|
+
@octokit = octokit
|
9
|
+
end
|
10
|
+
|
11
|
+
def fetch(repo_full_name, ref)
|
12
|
+
lockfile_content = octokit.contents(
|
13
|
+
repo_full_name, { ref: ref }
|
14
|
+
).find { |content|
|
15
|
+
content.name == "Gemfile.lock"
|
16
|
+
}
|
17
|
+
Bundler::LockfileParser.new(
|
18
|
+
Base64.decode64(
|
19
|
+
octokit.blob(repo_full_name, lockfile_content.sha).content
|
20
|
+
)
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
class CompareLinker
|
4
|
+
class WebhookPayload
|
5
|
+
def initialize(payload)
|
6
|
+
@payload = payload
|
7
|
+
@json = JSON.parse(@payload)
|
8
|
+
end
|
9
|
+
|
10
|
+
def action
|
11
|
+
@json["action"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def repo_full_name
|
15
|
+
@json["repository"]["full_name"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def pr_number
|
19
|
+
@json["number"]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/payload.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative "lib/compare_linker"
|
2
|
+
require_relative "lib/compare_linker/webhook_payload"
|
3
|
+
|
4
|
+
payload = CompareLinker::WebhookPayload.new(ENV["payload"])
|
5
|
+
exit if payload.action != "opened"
|
6
|
+
|
7
|
+
compare_linker = CompareLinker.new(payload.repo_full_name, payload.pr_number)
|
8
|
+
compare_linker.formatter = CompareLinker::Formatter::Markdown.new
|
9
|
+
compare_links = compare_linker.make_compare_links.join("\n")
|
10
|
+
puts compare_linker.add_comment(payload.repo_full_name, payload.pr_number, compare_links)
|
data/runner.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative "lib/compare_linker"
|
2
|
+
require "optparse"
|
3
|
+
|
4
|
+
options = {}
|
5
|
+
opt = OptionParser.new
|
6
|
+
opt.on("-f VAL", "--format VAL") { |val|
|
7
|
+
case val
|
8
|
+
when /t(ext)?/i
|
9
|
+
options[:formatter] = CompareLinker::Formatter::Text.new
|
10
|
+
when /m(arkdown|d)?/i
|
11
|
+
options[:formatter] = CompareLinker::Formatter::Markdown.new
|
12
|
+
end
|
13
|
+
}
|
14
|
+
opt.on("--post-comment") { options[:post_comment] = true }
|
15
|
+
opt.parse!
|
16
|
+
|
17
|
+
repo_full_name, pr_number = *ARGV
|
18
|
+
if repo_full_name.nil? || pr_number.nil?
|
19
|
+
puts <<USAGE
|
20
|
+
Usage: ruby #{$0} [repo_full_name] [pr_number]
|
21
|
+
ruby #{$0} [repo_full_name] [pr_number] OCTOKIT_ACCESS_TOKEN=[your github access token]
|
22
|
+
USAGE
|
23
|
+
exit!
|
24
|
+
end
|
25
|
+
|
26
|
+
compare_linker = CompareLinker.new(repo_full_name, pr_number.to_i)
|
27
|
+
compare_linker.formatter = options[:formatter] if options[:formatter]
|
28
|
+
puts compare_linker.make_compare_links
|
29
|
+
if options[:post_comment]
|
30
|
+
compare_linker.formatter = CompareLinker::Formatter::Markdown.new
|
31
|
+
puts compare_linker.add_comment(repo_full_name, pr_number, compare_linker.compare_links)
|
32
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"name":"rails","downloads":31913037,"version":"4.0.2","version_downloads":485385,"platform":"ruby","authors":"David Heinemeier Hansson","info":"Ruby on Rails is a full-stack web framework optimized for programmer happiness and sustainable productivity. It encourages beautiful code by favoring convention over configuration.","licenses":["MIT"],"project_uri":"http://rubygems.org/gems/rails","gem_uri":"http://rubygems.org/gems/rails-4.0.2.gem","homepage_uri":"http://www.rubyonrails.org","wiki_uri":"http://wiki.rubyonrails.org","documentation_uri":"http://api.rubyonrails.org","mailing_list_uri":"http://groups.google.com/group/rubyonrails-talk","source_code_uri":"http://github.com/rails/rails","bug_tracker_uri":"http://github.com/rails/rails/issues","dependencies":{"development":[],"runtime":[{"name":"actionmailer","requirements":"= 4.0.2"},{"name":"actionpack","requirements":"= 4.0.2"},{"name":"activerecord","requirements":"= 4.0.2"},{"name":"activesupport","requirements":"= 4.0.2"},{"name":"bundler","requirements":"< 2.0, >= 1.3.0"},{"name":"railties","requirements":"= 4.0.2"},{"name":"sprockets-rails","requirements":"~> 2.0.0"}]}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"name":"web_translate_it","downloads":143572,"version":"2.2.1","version_downloads":321,"platform":"ruby","authors":"Edouard Briere","info":"A gem to push and pull language files to WebTranslateIt.com.","licenses":["MIT"],"project_uri":"http://rubygems.org/gems/web_translate_it","gem_uri":"http://rubygems.org/gems/web_translate_it-2.2.1.gem","homepage_uri":"https://webtranslateit.com","wiki_uri":"","documentation_uri":"","mailing_list_uri":"","source_code_uri":"http://github.com/atelierconvivialite/webtranslateit/","bug_tracker_uri":"http://github.com/atelierconvivialite/webtranslateit/issues","dependencies":{"development":[{"name":"guard-rspec","requirements":">= 0"},{"name":"rspec","requirements":">= 2.6.0"}],"runtime":[{"name":"multi_json","requirements":">= 0"},{"name":"multipart-post","requirements":"~> 2.0"},{"name":"trollop","requirements":"~> 2.0"}]}}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe CompareLinker::GithubLinkFinder do
|
4
|
+
let(:octokit) { double.as_null_object }
|
5
|
+
|
6
|
+
subject { described_class.new(octokit) }
|
7
|
+
|
8
|
+
|
9
|
+
describe "#find" do
|
10
|
+
before do
|
11
|
+
allow(HTTPClient).to receive_message_chain(:get, :body).and_return load_fixture("rails.json")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "extracts repo_owner and repo_name" do
|
15
|
+
subject.find("rails")
|
16
|
+
expect(subject.repo_owner).to eq "rails"
|
17
|
+
expect(subject.repo_name).to eq "rails"
|
18
|
+
end
|
19
|
+
|
20
|
+
context "if github url includes trailing slash" do
|
21
|
+
before do
|
22
|
+
allow(HTTPClient).to receive_message_chain(:get, :body).and_return load_fixture("web_translate_it.json")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "extracts repo_owner and repo_name without trailing slash" do
|
26
|
+
subject.find("web_translate_it")
|
27
|
+
expect(subject.repo_owner).to eq "atelierconvivialite"
|
28
|
+
expect(subject.repo_name).to eq "webtranslateit"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: compare_linker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kensuke Nagae
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: octokit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: httpclient
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Create GitHub's compare view URLs for pull request from diff of Gemfile.lock
|
84
|
+
email:
|
85
|
+
- kyanny@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- ".travis.yml"
|
93
|
+
- Gemfile
|
94
|
+
- Gemfile.lock
|
95
|
+
- LICENSE.txt
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- compare_linker.gemspec
|
99
|
+
- guides/jenkins_setup_guide.md
|
100
|
+
- lib/compare_linker.rb
|
101
|
+
- lib/compare_linker/formatter/markdown.rb
|
102
|
+
- lib/compare_linker/formatter/text.rb
|
103
|
+
- lib/compare_linker/github_link_finder.rb
|
104
|
+
- lib/compare_linker/github_tag_finder.rb
|
105
|
+
- lib/compare_linker/lockfile_comparator.rb
|
106
|
+
- lib/compare_linker/lockfile_fetcher.rb
|
107
|
+
- lib/compare_linker/version.rb
|
108
|
+
- lib/compare_linker/webhook_payload.rb
|
109
|
+
- payload.rb
|
110
|
+
- runner.rb
|
111
|
+
- spec/fixtures/rails.json
|
112
|
+
- spec/fixtures/web_translate_it.json
|
113
|
+
- spec/lib/compare_linker/github_link_finder_spec.rb
|
114
|
+
- spec/spec_helper.rb
|
115
|
+
- spec/support/load_fixture.rb
|
116
|
+
homepage: https://github.com/masutaka/compare_linker
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.4.5
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: Create GitHub's compare view URLs for pull request
|
140
|
+
test_files:
|
141
|
+
- spec/fixtures/rails.json
|
142
|
+
- spec/fixtures/web_translate_it.json
|
143
|
+
- spec/lib/compare_linker/github_link_finder_spec.rb
|
144
|
+
- spec/spec_helper.rb
|
145
|
+
- spec/support/load_fixture.rb
|