contribution-checker 0.0.1

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: 19182ad1d31baf01f0dc6d78e7d3ba7d3f992bcb
4
+ data.tar.gz: a8f6d7d814d0637a965c93b43a98fe12465fecbe
5
+ SHA512:
6
+ metadata.gz: ecbddc0756b18773bb5be5ef195f2b96251b30bddd1b8c20b1291749a057a29fa23b9079bc0be43e0123974f2c552caec18432af88681f46a2a17be7fdbf3aee
7
+ data.tar.gz: dcb17c150028c981d7939ecc53e9f8f1fc8c60512766387577f00aab4b53593b2f8f7486b668d33f5de3c6bb518348c67e8c3c8e99846c3ca237e9a60825b48a
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/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 James Dennes
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,31 @@
1
+ # GitHub Contribution Checker
2
+
3
+ People :heart: GitHub Contributions. However, it's not always simple to tell why a commit isn't [counted as a contribution][contributions]. This library lets you check whether a specific commit qualifies as a contribution.
4
+
5
+ ## Usage
6
+
7
+ ```ruby
8
+ checker = ContributionChecker::Checker.new \
9
+ :access_token => "<Your 40 char GitHub API token>",
10
+ :commit_url => "https://github.com/user/repo/commit/sha"
11
+ )
12
+
13
+ checker.check
14
+ => {
15
+ :counted_as_contribution => true,
16
+ :and_criteria => {
17
+ :commit_in_valid_branch => true,
18
+ :commit_in_last_year => true,
19
+ :repo_not_a_fork => true,
20
+ :commit_email_linked_to_user => true
21
+ },
22
+ :or_criteria => {
23
+ :user_has_starred_repo => false,
24
+ :user_can_push_to_repo => false,
25
+ :user_is_repo_org_member => true,
26
+ :user_has_fork_of_repo => false
27
+ }
28
+ }
29
+ ```
30
+
31
+ [contributions]: https://help.github.com/articles/why-are-my-contributions-not-showing-up-on-my-profile
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'contribution-checker/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "contribution-checker"
8
+ spec.version = ContributionChecker::VERSION
9
+ spec.authors = ["James Dennes"]
10
+ spec.email = ["jdennes@gmail.com"]
11
+ spec.summary = %q{Check whether a commit is counted as a contribution.}
12
+ spec.description = %q{Check whether a GitHub commit is counted as a \
13
+ contribution for a specific GitHub user.}
14
+ spec.homepage = ""
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "octokit", "~> 3.1"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake"
26
+ end
@@ -0,0 +1,206 @@
1
+ require "octokit"
2
+
3
+ # Check whether a GitHub commit is counted as a contribution for a specific
4
+ # GitHub user.
5
+ #
6
+ # @see https://help.github.com/articles/why-are-my-contributions-not-showing-up-on-my-profile
7
+ module ContributionChecker
8
+
9
+ # The Checker.
10
+ class Checker
11
+
12
+ # Initialise a new Checker instance with an API access token and commit URL.
13
+ #
14
+ # @param options [Hash] Options which should take the form:
15
+ # {
16
+ # :access_token => "<Your 40 char GitHub API token>",
17
+ # :commit_url => "https://github.com/user/repo/commit/sha"
18
+ # }
19
+ #
20
+ # @return [ContributionChecker::Checker] Contribution checker initialised
21
+ # for an authenticated user and a specific commit
22
+ def initialize(options = {})
23
+ options.each do |key, val|
24
+ instance_variable_set :"@#{key}", val
25
+ end
26
+ @client = Octokit::Client.new(:access_token => @access_token)
27
+ end
28
+
29
+ # Checks whether the commit is counted as a contribution for the
30
+ # authenticated user.
31
+ #
32
+ # @return [Hash] The return value takes the following form:
33
+ # {
34
+ # :counted_as_contribution => true,
35
+ # :and_criteria => {
36
+ # :commit_in_valid_branch => true,
37
+ # :commit_in_last_year => true,
38
+ # :repo_not_a_fork => true,
39
+ # :commit_email_linked_to_user => true
40
+ # },
41
+ # :or_criteria => {
42
+ # :user_has_starred_repo => false,
43
+ # :user_can_push_to_repo => false,
44
+ # :user_is_repo_org_member => true,
45
+ # :user_has_fork_of_repo => false
46
+ # }
47
+ # }
48
+ def check
49
+ parts = URI.parse(@commit_url).path.split("/")
50
+ @nwo = "#{parts[1]}/#{parts[2]}"
51
+ @sha = parts[4]
52
+ @user = @client.user
53
+ @repo = @client.repository @nwo
54
+ @commit = @client.commit @nwo, @sha
55
+
56
+ @commit_in_valid_branch = commit_in_valid_branch?
57
+ @commit_in_last_year = commit_in_last_year?
58
+ @repo_not_a_fork = !repository_is_fork?
59
+ @commit_email_linked_to_user = commit_email_linked_to_user?
60
+ @user_has_starred_repo = user_has_starred_repo?
61
+ @user_can_push_to_repo = user_can_push_to_repo?
62
+ @user_is_repo_org_member = user_is_repo_org_member?
63
+ @user_has_fork_of_repo = user_has_fork_of_repo?
64
+
65
+ {
66
+ :contribution => and_criteria_met? && or_criteria_met?,
67
+ :and_criteria => {
68
+ :commit_in_valid_branch => @commit_in_valid_branch,
69
+ :commit_in_last_year => @commit_in_last_year,
70
+ :repo_not_a_fork => @repo_not_a_fork,
71
+ :commit_email_linked_to_user => @commit_email_linked_to_user,
72
+ },
73
+ :or_criteria => {
74
+ :user_has_starred_repo => @user_has_starred_repo,
75
+ :user_can_push_to_repo => @user_can_push_to_repo,
76
+ :user_is_repo_org_member => @user_is_repo_org_member,
77
+ :user_has_fork_of_repo => @user_has_fork_of_repo,
78
+ }
79
+ }
80
+ end
81
+
82
+ # Checks whether the commit is in a valid branch. A valid branch is defined
83
+ # as either the default branch of the repository, or the gh-pages branch.
84
+ #
85
+ # @return [Boolean]
86
+ def commit_in_valid_branch?
87
+ # If two refs are entirely different commit histories, the API responds
88
+ # with a 404. Rescue Octokit::NotFound in this case.
89
+ begin
90
+ default_compare = @client.compare @repo[:full_name],
91
+ @repo[:default_branch], @commit[:sha]
92
+ rescue Octokit::NotFound
93
+ default_compare = nil
94
+ end
95
+
96
+ # The compare status should be "identical" or "behind" if the commit is in
97
+ # the default branch
98
+ unless default_compare &&
99
+ %w(identical behind).include?(default_compare[:status])
100
+
101
+ # If the commit is not in the default branch, check the gh-pages branch
102
+ begin
103
+ gh_pages_compare = @client.compare @repo[:full_name], "gh-pages",
104
+ @commit[:sha]
105
+ rescue Octokit::NotFound
106
+ gh_pages_compare = nil
107
+ end
108
+ return false if !gh_pages_compare
109
+ return false if !%w(identical behind).include? gh_pages_compare [:status]
110
+ end
111
+
112
+ true
113
+ end
114
+
115
+ # Checks whether the commit was authored in the last year.
116
+ #
117
+ # @return [Boolean]
118
+ def commit_in_last_year?
119
+ a_year_ago = Time.now - (365.25 * 86400)
120
+ commit_time = @commit[:commit][:author][:date]
121
+ (commit_time <=> a_year_ago) == 1
122
+ end
123
+
124
+ # Checks whether the repository is a fork.
125
+ #
126
+ # @return [Boolean]
127
+ def repository_is_fork?
128
+ @repo[:fork]
129
+ end
130
+
131
+ # Checks whether the commit email is linked to the authenticated user's
132
+ # GitHub account.
133
+ #
134
+ # @return [Boolean]
135
+ def commit_email_linked_to_user?
136
+ @emails = @client.emails
137
+ @emails.map { |e| e[:email] }.include? @commit[:commit][:author][:email]
138
+ end
139
+
140
+ # Checks whether the authenticated user has starred the repository in which
141
+ # the commit exists.
142
+ #
143
+ # @return [Boolean]
144
+ def user_has_starred_repo?
145
+ @client.starred?(@nwo)
146
+ end
147
+
148
+ # Checks whether the authenticated user is a member of the organization
149
+ # that owns the repository (if the repository is owned by an organization
150
+ # account).
151
+ #
152
+ # @return [Boolean]
153
+ def user_is_repo_org_member?
154
+ false if @repo[:owner] != "Organization"
155
+ @client.organization_member? @repo[:owner][:login], @user[:login]
156
+ end
157
+
158
+ # Checks whether the authenticated user has push access to the repository in
159
+ # which the commit exists.
160
+ #
161
+ # @return [Boolean]
162
+ def user_can_push_to_repo?
163
+ @repo[:permissions][:push]
164
+ end
165
+
166
+ # Checks whether the authenticated user has forked the repository in which
167
+ # the commit exists.
168
+ #
169
+ # @return [Boolean]
170
+ def user_has_fork_of_repo?
171
+ # The API doesn't provide a simple means of checking whether a user has
172
+ # forked a repository. Here we need to get the user's forks and check the
173
+ # `parent` field of each fork to see whether it matches @repo.
174
+ @client.auto_paginate = true
175
+ @user_repos = @client.repos
176
+ @user_forks = @user_repos.select { |r| r[:fork] }
177
+ @user_forks.each do |f|
178
+ r = @client.repository f[:full_name]
179
+ return true if r[:parent][:full_name] == @repo[:full_name]
180
+ end
181
+ false
182
+ end
183
+
184
+ # Checks whether the "and" criteria for counting a commit as a contribution
185
+ # are correctly met.
186
+ #
187
+ # @return [Boolean]
188
+ def and_criteria_met?
189
+ @commit_in_valid_branch &&
190
+ @commit_in_last_year &&
191
+ @repo_not_a_fork &&
192
+ @commit_email_linked_to_user
193
+ end
194
+
195
+ # Checks whether the "or" criteria for counting a commit as a contribution
196
+ # are correctly met.
197
+ #
198
+ # @return [Boolean]
199
+ def or_criteria_met?
200
+ @user_has_starred_repo ||
201
+ @user_can_push_to_repo ||
202
+ @user_is_repo_org_member ||
203
+ @user_has_fork_of_repo
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,3 @@
1
+ module ContributionChecker
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,2 @@
1
+ require "contribution-checker/version"
2
+ require "contribution-checker/checker"
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: contribution-checker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - James Dennes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-07 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: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: |-
56
+ Check whether a GitHub commit is counted as a \
57
+ contribution for a specific GitHub user.
58
+ email:
59
+ - jdennes@gmail.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - .gitignore
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - contribution-checker.gemspec
70
+ - lib/contribution-checker.rb
71
+ - lib/contribution-checker/checker.rb
72
+ - lib/contribution-checker/version.rb
73
+ homepage: ''
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.0.3
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Check whether a commit is counted as a contribution.
97
+ test_files: []