upstreamwatchr 0.0.42

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e1ec7dfa70e08c99094546080e6180ea953a033e
4
+ data.tar.gz: 8acfdf0d9507374a9cd4258b1855ba7659c312a8
5
+ SHA512:
6
+ metadata.gz: 8fd2ea5f6c64dcc7069e51e85cd0ca3f0869d4a249281f301c7d472d85abd37981cfd41aa123be80e9801b81bb187538d61d2ce8b6b755cb8b59c1da8686dd88
7
+ data.tar.gz: 368f85a18be9087b18e205ba12e885849d1c43c39ca38e24a945243a9488514a5c16a56c82f5e83a1d5df1c1e4feb1dc0ad108b091c220b93e3c886e67b3f2eb
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # UpstreamWatchr
2
+ makes it easy to keep track of changes in the upstream repositories of your forks by comparing two git remotes and creating an issue on your fork if it is out of sync.
3
+
4
+
5
+ Currently only GitLab is supported (api wise). This means that it will fail (horribly) if you are using something else for your repos. It also has some requirements on your projects, such as that its needs a hyperlink in your projects `description` to find the upstream repository. Also your project should allow upstreamwatchr's user to read the code and create issues. If your project is not setup this way, UpstreamWatchr will fail, again, horribly.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'upstreamwatchr'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install upstreamwatchr
20
+
21
+ ## Usage
22
+
23
+ Set `ENV['GITLAB_API_ENDPOINT']` and `ENV['GITLAB_API_PRIVATE_TOKEN']` and use the "binary":
24
+ ```
25
+ # Check a single project
26
+ GITLAB_API_ENDPOINT=https://git.acme.com/ GITLAB_API_PRIVATE_TOKEN=abcdefg123456 upstreamwatchr git@githost.acme.com:/path/repo.git
27
+ ```
28
+ ```
29
+ # Check all available projects
30
+ GITLAB_API_ENDPOINT=https://git.acme.com/ GITLAB_API_PRIVATE_TOKEN=abcdefg123456 upstreamwatchr"
31
+ ```
@@ -0,0 +1,43 @@
1
+ #! ruby
2
+ require 'rainbow/ext/string'
3
+
4
+ lib = File.expand_path('../../lib', __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require 'upstreamwatchr'
7
+
8
+ unless ENV['GITLAB_API_ENDPOINT'] && ENV['GITLAB_API_PRIVATE_TOKEN']
9
+ puts "Usage:
10
+ GITLAB_API_ENDPOINT=https://git.acme.com/ GITLAB_API_PRIVATE_TOKEN=abcdefg123456 upstreamwatchr git@githost.acme.com:/path/repo.git
11
+ or to check all available projects:
12
+ GITLAB_API_ENDPOINT=https://git.acme.com/ GITLAB_API_PRIVATE_TOKEN=abcdefg123456 upstreamwatchr"
13
+ exit 1
14
+ end
15
+
16
+ if not ARGV[0]
17
+ puts "Debug: Not called with a specific project. Checking all I can haz access to!" if ENV['DEBUG']
18
+ projects = Gitlab.projects(:per_page => 10000)
19
+ my_uid = Gitlab.user.id
20
+ projects.select! {|p| ((not p.owner) || p.owner.id != my_uid)}
21
+ projects.each do |project|
22
+ begin
23
+ watch = UpstreamWatchr::GitLabWatchr.new(project.ssh_url_to_repo)
24
+ info = "Info: #{project.name} (#{project.ssh_url_to_repo}): #{watch.comparator.to_s}"
25
+ if watch.comparator.has_changes?
26
+ puts info.color(:red)
27
+ watch.grumble_in_issue
28
+ else
29
+ puts info.color(:green)
30
+ end
31
+ rescue => e
32
+ STDERR.puts "Warn: Failed to check #{project.name} (#{project.ssh_url_to_repo}!"
33
+ require 'pry'; binding.pry if ENV['DEBUG']
34
+ STDERR.puts e
35
+ end
36
+ end
37
+ else
38
+ watch = UpstreamWatchr::GitLabWatchr.new(ARGV[0])
39
+ puts "Debug: #{project.comparator.to_s}" if ENV['DEBUG']
40
+ if watch.comparator.has_changes?
41
+ watch.grumble_in_issue
42
+ end
43
+ end
@@ -0,0 +1,8 @@
1
+ require "UpstreamWatchr/gitremotes"
2
+ require "UpstreamWatchr/gitlabcheck"
3
+ #require "UpstreamWatchr/version"
4
+
5
+
6
+ module UpstreamWatchr
7
+ # Your code goes here...
8
+ end
@@ -0,0 +1,96 @@
1
+ require 'gitlab'
2
+
3
+ module UpstreamWatchr
4
+ class GitLabWatchr
5
+ attr_reader :origin_url, :origin_project, :comparator
6
+
7
+ def initialize(origin_url, branch = 'master')
8
+ @origin_url = origin_url
9
+ @branch = branch
10
+ @comparator = GitRemotes.new(@origin_url, upstream_url)
11
+ end
12
+
13
+ def origin_project
14
+ @origin_project ||= Gitlab.projects(:per_page => 10000).find {|p| p.ssh_url_to_repo == @origin_url || p.http_url_to_repo == @origin_url || p.web_url == @origin_url }
15
+ end
16
+
17
+ def upstream_url
18
+ @upstream_url ||= origin_project.description.match(/^Upstream: (\S*)$/)[1]
19
+ end
20
+
21
+ def create_fork
22
+ puts "Forking #{origin_project.name}..."
23
+ Gitlab.create_fork(@origin_project.id)
24
+ rescue Gitlab::Error::Conflict
25
+ puts "Fork of #{origin_project.name} already exists."
26
+ end
27
+
28
+ def fork
29
+ @fork ||= (Gitlab.projects(:per_page => 10000).find {|p| p.forked_from_project && p.forked_from_project.id == @origin_project.id } || create_fork)
30
+ end
31
+
32
+ def create_merge_request
33
+ @comparator.push_to_my_fork(fork.ssh_url_to_repo)
34
+
35
+ puts "Creating merge request on #{origin_project.name}..."
36
+ Gitlab.create_merge_request(fork.id,
37
+ 'UpstreamWatcher detected new upstream changes!',
38
+ :source_branch => @branch,
39
+ :target_branch => @branch,
40
+ :target_project_id => origin_project.id
41
+ )
42
+ rescue Gitlab::Error::Conflict
43
+ puts "Merge request seems to be already there. Good. Previous MR updated with even more upstream changes!"
44
+ end
45
+
46
+ def issue_title
47
+ "UpstreamWatchr: #{@comparator.upstream_ahead} change(s) to fetch from your upstream project!"
48
+ end
49
+
50
+ def issue_description
51
+ "UpstreamWatchr noted that your branch '#{@branch}' is #{@comparator.upstream_ahead} commits behind `#{upstream_url}`'s #{@branch}.
52
+
53
+ Whenenver you feel confident pulling the upstream changes onto your branch, you can use these git commands:
54
+
55
+ ```
56
+ git checkout #{@branch}
57
+ git pull #{upstream_url} #{@branch}
58
+ git push origin #{@branch}
59
+ ```
60
+
61
+
62
+ Sincerly, UpstreamWatchr"
63
+ end
64
+
65
+ def issue
66
+ @issue ||= find_issue || create_issue
67
+ end
68
+
69
+ def find_issue
70
+ Gitlab.issues(@origin_project.id, :per_page => 1000).find {|i| i.state != 'closed' && i.author.id == Gitlab.user.id && i.title =~ /^UpstreamWatchr:/}
71
+ end
72
+
73
+ def create_issue
74
+ puts "Warn: Creating new issue '#{issue_title}'"
75
+ Gitlab.create_issue(@origin_project.id,
76
+ issue_title,
77
+ {:description => issue_description}
78
+ )
79
+ end
80
+
81
+ def update_issue
82
+ puts "Debug: Updating issue '#{issue_title}'" if ENV['DEBUG']
83
+ Gitlab.edit_issue(@origin_project.id, issue.id, :title => issue_title)
84
+ end
85
+
86
+ def grumble_in_issue
87
+ changes_in_title = issue.title.match(/(\d+)/)[1].to_i
88
+ puts "Debug: Issue states '#{changes_in_title} changes'" if ENV['DEBUG']
89
+ unless changes_in_title == @comparator.upstream_ahead
90
+ puts "Warn: Going to update issue to '#{issue_title}'"
91
+ update_issue
92
+ end
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,103 @@
1
+ require 'rugged'
2
+ require 'tmpdir'
3
+
4
+ module UpstreamWatchr
5
+ class GitRemotes
6
+
7
+ def initialize(origin, upstream, main_branch = 'master')
8
+ @origin = origin
9
+ @upstream = upstream
10
+ @main_branch = main_branch
11
+
12
+ begin
13
+ @repo = Rugged::Repository.clone_at(@origin, clone_path, {:bare => true, :credentials => ssh_agent})
14
+ puts "Debug: cloned #{@origin} to #{clone_path}" if ENV['DEBUG']
15
+ rescue Rugged::InvalidError
16
+ puts "Debug: didn't clone (#{@origin} to #{clone_path}), local repo already there." if ENV['DEBUG']
17
+ @repo = Rugged::Repository.new(clone_path)
18
+ @repo.remotes['origin'].fetch({:credentials => ssh_agent})
19
+ @repo.remotes['origin'].save
20
+ puts "Debug: fetched 'origin' from #{origin}" if ENV['DEBUG']
21
+ end
22
+
23
+ @repo.remotes.create('upstream', @upstream) unless @repo.remotes['upstream']
24
+ fail "Can not read from upstream. Something seems off with remote #{@upstream}" unless @repo.remotes['upstream'].check_connection(:fetch, {:credentials => ssh_agent})
25
+ @repo.remotes['upstream'].fetch({:credentials => ssh_agent})
26
+ @repo.remotes['upstream'].save
27
+ puts "Debug: fetched 'upstream' from #{@upstream}" if ENV['DEBUG']
28
+ end
29
+
30
+ def ssh_agent
31
+ lambda { |_, username, _| Rugged::Credentials::SshKeyFromAgent.new(username: username)}
32
+ end
33
+
34
+ def clone_path
35
+ File.join(Dir.tmpdir, @origin.split('/').last)
36
+ end
37
+
38
+ def push_to_my_fork(my_fork_url, branch = nil)
39
+ branch ||= @main_branch
40
+ @repo.remotes.create('my_fork', my_fork_url) unless @repo.remotes['my_fork']
41
+
42
+ @repo.reset("upstream/#{branch}", :soft)
43
+ @repo.remotes["my_fork"].push("refs/heads/#{branch}", {:credentials => ssh_agent})
44
+ end
45
+
46
+ def diff(branch = nil)
47
+ branch ||= @main_branch
48
+ origin_target = @repo.references["refs/remotes/origin/#{branch}"].target
49
+ puts "Debug: origin has its #{branch} at #{origin_target}" if ENV['DEBUG']
50
+ upstream_target = @repo.references["refs/remotes/upstream/#{branch}"].target
51
+ puts "Debug: upstream has its #{branch} at #{upstream_target}" if ENV['DEBUG']
52
+ @repo.diff(origin_target, upstream_target)
53
+ end
54
+
55
+ def ahead_behind(branch = nil)
56
+ branch ||= @main_branch
57
+ @repo.ahead_behind(@repo.references["refs/remotes/origin/#{branch}"].target, @repo.references["refs/remotes/upstream/#{branch}"].target)
58
+ end
59
+
60
+ def upstream_ahead
61
+ ahead_behind[1]
62
+ end
63
+
64
+ def upstream_behind
65
+ ahead_behind[0]
66
+ end
67
+
68
+ def trees(branch = nil)
69
+ branch ||= @main_branch
70
+ [@repo.references["refs/remotes/origin/#{branch}"].target.tree, @repo.references["refs/remotes/upstream/#{branch}"].target.tree]
71
+ end
72
+
73
+ def origin_tree_size(branch = nil)
74
+ branch ||= @main_branch
75
+ trees(branch)[0].count
76
+ end
77
+
78
+ def upstream_tree_size(branch = nil)
79
+ branch ||= @main_branch
80
+ trees(branch)[1].count
81
+ end
82
+
83
+ def tree_size_diff(branch = nil)
84
+ branch ||= @main_branch
85
+ upstream_tree_size(branch) - origin_tree_size(branch)
86
+ end
87
+
88
+ def has_changes?
89
+ ahead_behind != [0,0]
90
+ end
91
+
92
+ def to_s(branch = nil)
93
+ branch ||= @main_branch
94
+ a_b = ahead_behind(branch)
95
+ if a_b == [0,0]
96
+ "origin/#{branch} is up-to-date with 'upstream/#{branch}'"
97
+ else
98
+ "upstream/#{branch} is #{upstream_ahead} ahead and #{upstream_behind} behind 'origin/#{branch}'"
99
+ end
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,3 @@
1
+ module UpstreamWatchr
2
+ VERSION = "0.0.42"
3
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'upstreamwatchr/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "upstreamwatchr"
8
+ spec.version = UpstreamWatchr::VERSION
9
+ spec.authors = ["Marvin Frick"]
10
+ spec.email = ["marvin.frick@sinnerschrader.com"]
11
+ spec.summary = %q{watches "upstream" repositories for changes}
12
+ spec.description = %q{upstreamwatchr makes it easy to keep track of changes in the upstream repositories of your forks by comparing two git remotes and creating an issue on your fork if it is out of sync.}
13
+ spec.homepage = "https://github.com/MrMarvin/upstreamwatchr"
14
+ spec.license = "BSD"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
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
+ spec.add_development_dependency 'pry', '0.10.1'
21
+ spec.add_runtime_dependency 'rugged', '0.22.2'
22
+ spec.add_runtime_dependency 'gitlab', '3.4.0'
23
+ spec.add_runtime_dependency 'rainbow', '2.0.0'
24
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: upstreamwatchr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.42
5
+ platform: ruby
6
+ authors:
7
+ - Marvin Frick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.1
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: rugged
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.22.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.22.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: gitlab
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 3.4.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 3.4.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rainbow
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.0
69
+ description: upstreamwatchr makes it easy to keep track of changes in the upstream
70
+ repositories of your forks by comparing two git remotes and creating an issue on
71
+ your fork if it is out of sync.
72
+ email:
73
+ - marvin.frick@sinnerschrader.com
74
+ executables:
75
+ - upstreamwatchr
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - ".gitignore"
80
+ - Gemfile
81
+ - README.md
82
+ - bin/upstreamwatchr
83
+ - lib/UpstreamWatchr.rb
84
+ - lib/UpstreamWatchr/gitlabcheck.rb
85
+ - lib/UpstreamWatchr/gitremotes.rb
86
+ - lib/UpstreamWatchr/version.rb
87
+ - upstreamwatchr.gemspec
88
+ homepage: https://github.com/MrMarvin/upstreamwatchr
89
+ licenses:
90
+ - BSD
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.2.2
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: watches "upstream" repositories for changes
112
+ test_files: []