bimble 0.0.1 → 1.0.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.
Files changed (35) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +3 -1
  3. data/CHANGELOG.md +9 -0
  4. data/README.md +10 -2
  5. data/Rakefile +4 -0
  6. data/bimble.gemspec +5 -2
  7. data/bin/bimble +11 -0
  8. data/bin/{generate_oauth_token.rb → generate_github_oauth_token} +0 -0
  9. data/lib/bimble.rb +16 -3
  10. data/lib/bimble/bundler.rb +9 -0
  11. data/lib/bimble/factory.rb +12 -0
  12. data/lib/bimble/git_strategy/clone.rb +40 -0
  13. data/lib/bimble/git_strategy/github_api.rb +57 -0
  14. data/lib/bimble/helpers/github.rb +99 -0
  15. data/lib/bimble/helpers/strings.rb +19 -0
  16. data/lib/bimble/helpers/updater.rb +14 -0
  17. data/lib/bimble/version.rb +1 -1
  18. data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_create_a_new_blob.yml +73 -0
  19. data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_create_a_new_branch_for_a_commit.yml +73 -0
  20. data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_create_a_new_commit_from_a_tree.yml +215 -0
  21. 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
  22. data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_fetch_the_default_branch_for_a_repo.yml +72 -0
  23. data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_get_a_blob_sha_for_a_file_on_a_branch.yml +72 -0
  24. 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
  25. 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
  26. data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_get_latest_commit_SHA_on_a_branch.yml +73 -0
  27. data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_get_the_content_of_the_Gemfile_blob.yml +70 -0
  28. data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_open_a_pull_request_back_to_the_default_branch.yml +76 -0
  29. data/spec/cassettes/Bimble_GitStrategy_GithubApi/should_be_able_to_update_Gemfile_lock_and_open_PR_all_in_one_go.yml +567 -0
  30. data/spec/cassettes/github_api_strategy/should_get_all_appropriate_files.yml +342 -0
  31. data/spec/git_strategy_spec.rb +26 -0
  32. data/spec/github_api_spec.rb +70 -0
  33. data/spec/spec_helper.rb +15 -6
  34. metadata +88 -8
  35. 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
- MjU4MGVhZmIwNjFkYTMzM2IxNTdhNTFjMzg4NzMwMTExZTAyYjJlNA==
4
+ ODNlYmJiNGVjMzAwZjk2NTkxNzkzNDYzODI4Zjc1YjExMjY5MWIwZQ==
5
5
  data.tar.gz: !binary |-
6
- YTY3OGUzMTJjZGFkMTljOTIyMmExZDZjODJkMzM3YjU4NTE0NzJiNQ==
6
+ NzU0ZjAzNjhjMjE4MjZkNWQ4YzlhNzVhYWI4YWRmMDc0OTZiOWQ1Yw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OWU0MGJmNWFiYTljY2RlMmQ2MzExNDUwNzJjNzkzYzUyNzMxNjdkNmVlMjFm
10
- YzQ2NGJmYWNmZGNjZjM5ODU2NGQwM2VmZDdmZmQ0NjM4YTBiYTczYmEzNjMy
11
- NjlhYzA1NmZiZTdhNTBmNDE2NzYyNGU3N2JmNDI3NGI4OThkNDQ=
9
+ Mzg0MjA1YWY1OTQ4NTE0NjY3NThmMmQ1ZTEzMWZjMTI0MjQwMzQwODUzOTcz
10
+ YzkxZjJlZWI0N2FkN2M3YTBhN2UxNjc4OTk4ZmVhMDQzYWI0ODY3YjgwN2Nh
11
+ YmM3MTE1NmVlYmRmZThiMTIyODkwNWRhZTJmMTUxOGIwODJiOTM=
12
12
  data.tar.gz: !binary |-
13
- YzA2MWI3ZWMzODc4NmU4M2I0MWZjZTA3NzAxZjE0MTA5ZTJiY2MzZmZkN2Ni
14
- ZDIwNWZhNDE1OTc1NWUxYjA3MDgwNzBhNGRjNjE5NmEyNmE1Y2Q1NDIwZTlh
15
- YjcwNmM4MjU1ZjU1YjQ1Y2JhNzgwMTI0ZmJiMGExMjI1MTRjMGY=
13
+ ODZhY2FiOTgyNmFkNGNlYTE3M2E3YTQ3NWIxMjY1OTczMzQyNjQ4NWVjMDI2
14
+ MThiMWUwNDAyNjM2MTFhZDVkNzYwYmNmY2JjNjJlZmM2MjhhNDBlYzlkNjdj
15
+ NjNmYWQwNTg2OTk3OWJkZjMwMzQ2ZTAwZGQzNDUzZTQ5NzgzOGU=
data/.travis.yml CHANGED
@@ -15,4 +15,6 @@ deploy:
15
15
  gem: bimble
16
16
  on:
17
17
  tags: true
18
- repo: theodi/bimble
18
+ repo: theodi/bimble
19
+ env:
20
+ - GITHUB_OAUTH_TOKEN=abc123
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ Use github API to get and commit files instead of a full clone
6
+
7
+ ## 0.0.1
8
+
9
+ First gemmed version. Uses a local clone.
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.rb git@github.com:{user}/{repo}.git
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 `./generate_oauth_token.rb` and follow the instructions. You'll need
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
@@ -1,3 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
2
 
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
3
7
  task :default => :spec
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
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dotenv'
4
+ require 'bimble'
5
+
6
+ Dotenv.load
7
+
8
+ bimble = Bimble.create(:github_api,
9
+ git_url: ARGV[0],
10
+ github_oauth_token: ENV['GITHUB_OAUTH_TOKEN'])
11
+ puts bimble.update
data/lib/bimble.rb CHANGED
@@ -1,5 +1,18 @@
1
- require "bimble/version"
2
-
3
1
  module Bimble
4
- # Your code goes here...
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,9 @@
1
+ module Bimble
2
+
3
+ def self.bundle_update
4
+ if File.exists?("Gemfile")
5
+ `bundle update`
6
+ end
7
+ end
8
+
9
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Bimble
2
- VERSION = "0.0.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -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