bimble 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.travis.yml +3 -1
- data/CHANGELOG.md +9 -0
- data/README.md +10 -2
- data/Rakefile +4 -0
- data/bimble.gemspec +5 -2
- data/bin/bimble +11 -0
- data/bin/{generate_oauth_token.rb → generate_github_oauth_token} +0 -0
- data/lib/bimble.rb +16 -3
- data/lib/bimble/bundler.rb +9 -0
- data/lib/bimble/factory.rb +12 -0
- data/lib/bimble/git_strategy/clone.rb +40 -0
- data/lib/bimble/git_strategy/github_api.rb +57 -0
- data/lib/bimble/helpers/github.rb +99 -0
- data/lib/bimble/helpers/strings.rb +19 -0
- data/lib/bimble/helpers/updater.rb +14 -0
- data/lib/bimble/version.rb +1 -1
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_create_a_new_blob.yml +73 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_create_a_new_branch_for_a_commit.yml +73 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_create_a_new_commit_from_a_tree.yml +215 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_create_a_tree_with_the_new_blob_in_it_given_a_filename.yml +211 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_fetch_the_default_branch_for_a_repo.yml +72 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_get_a_blob_sha_for_a_file_on_a_branch.yml +72 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_get_a_blob_sha_for_files_matching_a_regex_on_a_branch.yml +72 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_get_a_blob_sha_for_files_matching_a_regexp_on_a_branch.yml +72 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_get_latest_commit_SHA_on_a_branch.yml +73 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_get_the_content_of_the_Gemfile_blob.yml +70 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_open_a_pull_request_back_to_the_default_branch.yml +76 -0
- data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_update_Gemfile_lock_and_open_PR_all_in_one_go.yml +567 -0
- data/spec/cassettes/github_api_strategy/should_get_all_appropriate_files.yml +342 -0
- data/spec/git_strategy_spec.rb +26 -0
- data/spec/github_api_spec.rb +70 -0
- data/spec/spec_helper.rb +15 -6
- metadata +88 -8
- data/bin/bimble.rb +0 -52
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODNlYmJiNGVjMzAwZjk2NTkxNzkzNDYzODI4Zjc1YjExMjY5MWIwZQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzU0ZjAzNjhjMjE4MjZkNWQ4YzlhNzVhYWI4YWRmMDc0OTZiOWQ1Yw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Mzg0MjA1YWY1OTQ4NTE0NjY3NThmMmQ1ZTEzMWZjMTI0MjQwMzQwODUzOTcz
|
10
|
+
YzkxZjJlZWI0N2FkN2M3YTBhN2UxNjc4OTk4ZmVhMDQzYWI0ODY3YjgwN2Nh
|
11
|
+
YmM3MTE1NmVlYmRmZThiMTIyODkwNWRhZTJmMTUxOGIwODJiOTM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ODZhY2FiOTgyNmFkNGNlYTE3M2E3YTQ3NWIxMjY1OTczMzQyNjQ4NWVjMDI2
|
14
|
+
MThiMWUwNDAyNjM2MTFhZDVkNzYwYmNmY2JjNjJlZmM2MjhhNDBlYzlkNjdj
|
15
|
+
NjNmYWQwNTg2OTk3OWJkZjMwMzQ2ZTAwZGQzNDUzZTQ5NzgzOGU=
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
[![Build Status](http://img.shields.io/travis/theodi/bimble.svg)](https://travis-ci.org/theodi/bimble)
|
2
|
+
[![Dependency Status](http://img.shields.io/gemnasium/theodi/bimble.svg)](https://gemnasium.com/theodi/bimble)
|
3
|
+
[![Coverage Status](http://img.shields.io/coveralls/theodi/bimble.svg)](https://coveralls.io/r/theodi/bimble)
|
4
|
+
[![Code Climate](http://img.shields.io/codeclimate/github/theodi/bimble.svg)](https://codeclimate.com/github/theodi/bimble)
|
5
|
+
[![Gem Version](http://img.shields.io/gem/v/bimble.svg)](https://rubygems.org/gems/bimble)
|
6
|
+
[![License](http://img.shields.io/:license-mit-blue.svg)](http://theodi.mit-license.org)
|
7
|
+
[![Badges](http://img.shields.io/:badges-7/7-ff6799.svg)](https://github.com/pikesley/badger)
|
8
|
+
|
1
9
|
# Bimble
|
2
10
|
|
3
11
|
A gem and executable to check out a repo, run bundle update, then commit and open a PR.
|
@@ -31,7 +39,7 @@ You need to be able to clone via SSH from the user the script will run as.
|
|
31
39
|
Then:
|
32
40
|
|
33
41
|
```
|
34
|
-
bimble
|
42
|
+
bimble git@github.com:{user}/{repo}.git
|
35
43
|
```
|
36
44
|
|
37
45
|
Once the bundle is updated, `Gemfile.lock` **only** will be committed on a new
|
@@ -49,7 +57,7 @@ The following environment variables should be set in a `.env` file in order to u
|
|
49
57
|
|
50
58
|
GITHUB_OAUTH_TOKEN='your-oauth-token-for-your-app'
|
51
59
|
|
52
|
-
To generate this token, run
|
60
|
+
To generate this token, run `generate_github_oauth_token` and follow the instructions. You'll need
|
53
61
|
to be on a machine with a web browser.
|
54
62
|
|
55
63
|
## Contributing
|
data/Rakefile
CHANGED
data/bimble.gemspec
CHANGED
@@ -22,11 +22,14 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency 'dotenv'
|
23
23
|
spec.add_dependency 'github_api'
|
24
24
|
spec.add_dependency 'launchy'
|
25
|
+
spec.add_dependency 'memoist'
|
25
26
|
|
26
27
|
spec.add_development_dependency "bundler", "~> 1.3"
|
27
28
|
spec.add_development_dependency "rake"
|
28
29
|
spec.add_development_dependency "rspec"
|
29
|
-
spec.add_development_dependency "travis"
|
30
30
|
spec.add_development_dependency "coveralls"
|
31
|
-
|
31
|
+
spec.add_development_dependency "vcr"
|
32
|
+
spec.add_development_dependency "webmock"
|
33
|
+
spec.add_development_dependency "pry"
|
34
|
+
|
32
35
|
end
|
data/bin/bimble
ADDED
File without changes
|
data/lib/bimble.rb
CHANGED
@@ -1,5 +1,18 @@
|
|
1
|
-
require "bimble/version"
|
2
|
-
|
3
1
|
module Bimble
|
4
|
-
|
2
|
+
|
3
|
+
module Helpers
|
4
|
+
end
|
5
|
+
|
6
|
+
module GitStrategy
|
7
|
+
end
|
8
|
+
|
5
9
|
end
|
10
|
+
|
11
|
+
require "bimble/version"
|
12
|
+
require "bimble/helpers/github"
|
13
|
+
require "bimble/helpers/strings"
|
14
|
+
require "bimble/helpers/updater"
|
15
|
+
require "bimble/git_strategy/clone"
|
16
|
+
require "bimble/git_strategy/github_api"
|
17
|
+
require "bimble/factory"
|
18
|
+
require "bimble/bundler"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Bimble
|
2
|
+
|
3
|
+
def self.create(strategy, options)
|
4
|
+
case strategy
|
5
|
+
when :clone
|
6
|
+
Bimble::GitStrategy::Clone.new(options[:git_url], options[:github_oauth_token])
|
7
|
+
when :github_api
|
8
|
+
Bimble::GitStrategy::GithubApi.new(options[:git_url], options[:github_oauth_token])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'git'
|
2
|
+
|
3
|
+
class Bimble::GitStrategy::Clone
|
4
|
+
|
5
|
+
include Bimble::Helpers::Strings
|
6
|
+
include Bimble::Helpers::Github
|
7
|
+
include Bimble::Helpers::Updater
|
8
|
+
|
9
|
+
def initialize(git_url, oauth_token)
|
10
|
+
@git_url = git_url
|
11
|
+
@oauth_token = oauth_token
|
12
|
+
end
|
13
|
+
|
14
|
+
def in_working_copy
|
15
|
+
Dir.mktmpdir do |tmpdir|
|
16
|
+
@repository = Git.clone(@git_url, tmpdir)
|
17
|
+
@default_branch = @repository.branch
|
18
|
+
Dir.chdir(tmpdir) do
|
19
|
+
yield
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def lockfile_changed?
|
25
|
+
@repository.status.changed.keys.include? "Gemfile.lock"
|
26
|
+
end
|
27
|
+
|
28
|
+
def commit_to_new_branch
|
29
|
+
@repository.branch(branch_name).create
|
30
|
+
@repository.checkout(branch_name)
|
31
|
+
@repository.add("Gemfile.lock")
|
32
|
+
@repository.commit(commit_message)
|
33
|
+
@repository.push("origin", branch_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_branch
|
37
|
+
@default_branch
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Bimble::GitStrategy::GithubApi
|
2
|
+
|
3
|
+
include Bimble::Helpers::Strings
|
4
|
+
include Bimble::Helpers::Github
|
5
|
+
include Bimble::Helpers::Updater
|
6
|
+
|
7
|
+
def initialize(git_url, oauth_token)
|
8
|
+
@git_url = git_url
|
9
|
+
@oauth_token = oauth_token
|
10
|
+
end
|
11
|
+
|
12
|
+
def in_working_copy
|
13
|
+
Dir.mktmpdir do |tmpdir|
|
14
|
+
# Get files
|
15
|
+
files = get_files("Gemfile.*").merge(get_files(".*gemspec"))
|
16
|
+
Dir.chdir(tmpdir) do
|
17
|
+
# Write files
|
18
|
+
files.each_pair do |name, content|
|
19
|
+
File.open(name, 'w') {|f| f.write(content) }
|
20
|
+
end
|
21
|
+
# Store md5 of lockfile
|
22
|
+
@original_md5 = Digest::MD5.hexdigest(File.read("Gemfile.lock"))
|
23
|
+
# Do the business
|
24
|
+
yield
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_files(name)
|
30
|
+
blobs = blob_shas(default_branch, name)
|
31
|
+
Hash[blobs.map{|x| [x[0], blob_content(x[1])]}]
|
32
|
+
end
|
33
|
+
|
34
|
+
def lock_md5
|
35
|
+
Digest::MD5.hexdigest(File.read("Gemfile.lock"))
|
36
|
+
end
|
37
|
+
|
38
|
+
def lockfile_changed?
|
39
|
+
lock_md5 != @original_md5
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_file(name)
|
43
|
+
get_files(name)[name]
|
44
|
+
end
|
45
|
+
|
46
|
+
def commit_to_new_branch
|
47
|
+
commit_file("Gemfile.lock", File.read("Gemfile.lock"))
|
48
|
+
end
|
49
|
+
|
50
|
+
def commit_file(name, content)
|
51
|
+
blob_sha = create_blob(content)
|
52
|
+
tree_sha = add_blob_to_tree(blob_sha, name)
|
53
|
+
commit_sha = commit(tree_sha)
|
54
|
+
create_branch(branch_name, commit_sha)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'github_api'
|
3
|
+
require 'memoist'
|
4
|
+
|
5
|
+
module Bimble::Helpers::Github
|
6
|
+
|
7
|
+
extend Memoist
|
8
|
+
|
9
|
+
GITHUB_REPO_REGEX = /github.com[:\/]([^\/]*)\/([^\.]*)/
|
10
|
+
|
11
|
+
def github
|
12
|
+
Github.new oauth_token: @oauth_token
|
13
|
+
end
|
14
|
+
memoize :github
|
15
|
+
|
16
|
+
def user
|
17
|
+
match = @git_url.match GITHUB_REPO_REGEX
|
18
|
+
match ? match[1] : nil
|
19
|
+
end
|
20
|
+
memoize :user
|
21
|
+
|
22
|
+
def repo
|
23
|
+
match = @git_url.match GITHUB_REPO_REGEX
|
24
|
+
match ? match[2] : nil
|
25
|
+
end
|
26
|
+
memoize :repo
|
27
|
+
|
28
|
+
def default_branch
|
29
|
+
repository = github.repos.get user, repo
|
30
|
+
repository.default_branch
|
31
|
+
end
|
32
|
+
memoize :default_branch
|
33
|
+
|
34
|
+
def latest_commit(branch_name)
|
35
|
+
branch_data = github.repos.branch user, repo, branch_name
|
36
|
+
branch_data['commit']['sha']
|
37
|
+
end
|
38
|
+
memoize :latest_commit
|
39
|
+
|
40
|
+
def tree(branch)
|
41
|
+
github.git_data.trees.get user, repo, branch
|
42
|
+
end
|
43
|
+
memoize :tree
|
44
|
+
|
45
|
+
def blob_shas(branch, path)
|
46
|
+
tree = tree branch
|
47
|
+
Hash[tree['tree'].select{|x| x['path'] =~ /^#{path}$/ && x['type'] == 'blob'}.map{|x| [x.path, x.sha]}]
|
48
|
+
end
|
49
|
+
memoize :blob_shas
|
50
|
+
|
51
|
+
def blob_content(sha)
|
52
|
+
blob = github.git_data.blobs.get user, repo, sha
|
53
|
+
if blob['encoding'] == 'base64'
|
54
|
+
Base64.decode64(blob['content'])
|
55
|
+
else
|
56
|
+
blob['content']
|
57
|
+
end
|
58
|
+
end
|
59
|
+
memoize :blob_content
|
60
|
+
|
61
|
+
|
62
|
+
def create_blob(content)
|
63
|
+
blob = github.git_data.blobs.create user, repo, "content" => content, "encoding" => "utf-8"
|
64
|
+
blob['sha']
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_blob_to_tree(sha, filename)
|
68
|
+
tree = tree default_branch
|
69
|
+
new_tree = github.git_data.trees.create user, repo, "base_tree" => tree['sha'], "tree" => [
|
70
|
+
"path" => filename,
|
71
|
+
"mode" => "100644",
|
72
|
+
"type" => "blob",
|
73
|
+
"sha" => sha
|
74
|
+
]
|
75
|
+
new_tree['sha']
|
76
|
+
end
|
77
|
+
|
78
|
+
def commit(sha)
|
79
|
+
parent = latest_commit(default_branch)
|
80
|
+
commit = github.git_data.commits.create user, repo, "message" => commit_message,
|
81
|
+
"parents" => [parent],
|
82
|
+
"tree" => sha
|
83
|
+
commit['sha']
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_branch(name, sha)
|
87
|
+
branch = github.git_data.references.create user, repo, "ref" => "refs/heads/#{name}", "sha" => sha
|
88
|
+
branch['ref']
|
89
|
+
end
|
90
|
+
|
91
|
+
def open_pr(head, base)
|
92
|
+
github.pull_requests.create user, repo,
|
93
|
+
"title" => pull_request_title,
|
94
|
+
"body" => pull_request_body,
|
95
|
+
"head" => head,
|
96
|
+
"base" => base
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Bimble::Helpers::Strings
|
2
|
+
|
3
|
+
def branch_name
|
4
|
+
"update-dependencies-#{Date.today.to_s}"
|
5
|
+
end
|
6
|
+
|
7
|
+
def commit_message
|
8
|
+
"automatically updated dependencies"
|
9
|
+
end
|
10
|
+
|
11
|
+
def pull_request_title
|
12
|
+
"Updated dependencies"
|
13
|
+
end
|
14
|
+
|
15
|
+
def pull_request_body
|
16
|
+
"Automatically updated by Bimble"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Bimble::Helpers::Updater
|
2
|
+
|
3
|
+
def update
|
4
|
+
in_working_copy do
|
5
|
+
Bimble.bundle_update
|
6
|
+
if lockfile_changed?
|
7
|
+
commit_to_new_branch
|
8
|
+
@pr = open_pr(branch_name, default_branch) if @oauth_token
|
9
|
+
end
|
10
|
+
end
|
11
|
+
@pr ? @pr['html_url'] : nil
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/lib/bimble/version.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://api.github.com/repos/Floppy/bimble-test/git/blobs?access_token=<GITHUB_OAUTH_TOKEN>
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: "{\"content\":\"new blob content\",\"encoding\":\"utf-8\"}"
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1
|
12
|
+
Accept-Charset:
|
13
|
+
- utf-8
|
14
|
+
User-Agent:
|
15
|
+
- Github Ruby Gem 0.11.3
|
16
|
+
Content-Type:
|
17
|
+
- application/json
|
18
|
+
Authorization:
|
19
|
+
- Token token="<GITHUB_OAUTH_TOKEN>"
|
20
|
+
Accept-Encoding:
|
21
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
22
|
+
response:
|
23
|
+
status:
|
24
|
+
code: 201
|
25
|
+
message: Created
|
26
|
+
headers:
|
27
|
+
Server:
|
28
|
+
- GitHub.com
|
29
|
+
Date:
|
30
|
+
- Tue, 11 Mar 2014 14:20:58 GMT
|
31
|
+
Content-Type:
|
32
|
+
- application/json; charset=utf-8
|
33
|
+
Status:
|
34
|
+
- 201 Created
|
35
|
+
X-Ratelimit-Limit:
|
36
|
+
- '5000'
|
37
|
+
X-Ratelimit-Remaining:
|
38
|
+
- '4563'
|
39
|
+
X-Ratelimit-Reset:
|
40
|
+
- '1394548554'
|
41
|
+
Cache-Control:
|
42
|
+
- private, max-age=60, s-maxage=60
|
43
|
+
Etag:
|
44
|
+
- "\"f1f8f95824fcfe41a55cf713ac0c9b16\""
|
45
|
+
X-Oauth-Scopes:
|
46
|
+
- repo
|
47
|
+
X-Accepted-Oauth-Scopes:
|
48
|
+
- ''
|
49
|
+
Location:
|
50
|
+
- https://api.github.com/repos/Floppy/bimble-test/git/blobs/28b552e7359c5c3bbe947749aab70d18e3ea554b
|
51
|
+
Vary:
|
52
|
+
- Accept, Authorization, Cookie, X-GitHub-OTP
|
53
|
+
X-Github-Media-Type:
|
54
|
+
- github.v3; format=json
|
55
|
+
X-Content-Type-Options:
|
56
|
+
- nosniff
|
57
|
+
Content-Length:
|
58
|
+
- '157'
|
59
|
+
Access-Control-Allow-Credentials:
|
60
|
+
- 'true'
|
61
|
+
Access-Control-Expose-Headers:
|
62
|
+
- ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset,
|
63
|
+
X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
|
64
|
+
Access-Control-Allow-Origin:
|
65
|
+
- "*"
|
66
|
+
X-Github-Request-Id:
|
67
|
+
- 519F8646:7B0C:1ADBBE8:531F1BCA
|
68
|
+
body:
|
69
|
+
encoding: UTF-8
|
70
|
+
string: "{\"sha\":\"28b552e7359c5c3bbe947749aab70d18e3ea554b\",\"url\":\"https://api.github.com/repos/Floppy/bimble-test/git/blobs/28b552e7359c5c3bbe947749aab70d18e3ea554b\"}"
|
71
|
+
http_version:
|
72
|
+
recorded_at: Tue, 11 Mar 2014 14:20:59 GMT
|
73
|
+
recorded_with: VCR 2.8.0
|