class ContributionChecker::Checker
The Checker
.
Public Class Methods
Initialise a new Checker
instance with an API access token and commit URL.
@param options [Hash] Options which should take the form: {
:access_token => "<Your 40 char GitHub API token>", :commit_url => "https://github.com/user/repo/commit/sha"
}
@return [ContributionChecker::Checker] Contribution checker initialised for an authenticated user and a specific commit
# File lib/contribution-checker/checker.rb, line 22 def initialize(options = {}) options.each do |key, val| instance_variable_set :"@#{key}", val end @client = Octokit::Client.new(:access_token => @access_token) end
Public Instance Methods
Checks whether the commit is counted as a contribution for the authenticated user.
@return [Hash] The return value takes the following form: {
:contribution => true, :and_criteria => { :commit_email_is_not_generic => true, :commit_in_valid_branch => true, :repo_not_a_fork => true, :commit_email_linked_to_user => true, :commit_email => "me@foo.com", :default_branch => "master" }, :or_criteria => { :user_has_starred_repo => false, :user_can_push_to_repo => false, :user_is_repo_org_member => true, :user_has_fork_of_repo => false, :user_has_opened_issue_or_pr_in_repo => false }
}
# File lib/contribution-checker/checker.rb, line 51 def check @nwo, @sha = parse_commit_url @commit_url begin @commit = @client.commit @nwo, @sha rescue ArgumentError raise ContributionChecker::InvalidCommitUrlError rescue Octokit::NotFound raise ContributionChecker::InvalidCommitUrlError rescue Octokit::Unauthorized raise ContributionChecker::InvalidAccessTokenError end @repo = @client.repository @nwo @user = @client.user @commit_email_is_not_generic = commit_email_is_not_generic? @commit_in_valid_branch = commit_in_valid_branch? @repo_not_a_fork = !repository_is_fork? @commit_email_linked_to_user = commit_email_linked_to_user? @user_has_starred_repo = user_has_starred_repo? @user_can_push_to_repo = user_can_push_to_repo? @user_is_repo_org_member = user_is_repo_org_member? @user_has_fork_of_repo = user_has_fork_of_repo? @user_has_opened_issue_or_pr_in_repo = user_has_opened_issue_or_pr_in_repo? { :contribution => and_criteria_met? && or_criteria_met?, :and_criteria => { :commit_email_is_not_generic => @commit_email_is_not_generic, :commit_in_valid_branch => @commit_in_valid_branch, :repo_not_a_fork => @repo_not_a_fork, :commit_email_linked_to_user => @commit_email_linked_to_user, :commit_email => @commit[:commit][:author][:email], :default_branch => @repo[:default_branch], }, :or_criteria => { :user_has_starred_repo => @user_has_starred_repo, :user_can_push_to_repo => @user_can_push_to_repo, :user_is_repo_org_member => @user_is_repo_org_member, :user_has_fork_of_repo => @user_has_fork_of_repo, :user_has_opened_issue_or_pr_in_repo => @user_has_opened_issue_or_pr_in_repo, } } end
Private Instance Methods
Checks whether the “and” criteria for counting a commit as a contribution are correctly met.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 259 def and_criteria_met? @commit_email_is_not_generic && @commit_in_valid_branch && @repo_not_a_fork && @commit_email_linked_to_user end
Checks that the commit was not authored using a non-generic email. For example, this will return false when the commit was authored using emails like me@example.com, me@localhost, me@fake.org, etc.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 116 def commit_email_is_not_generic? @commit[:commit][:author][:email] !~ Regexp.union( /[@.](example|test|fake|none)\.?(com|net|org)?\z/i, /[@.]local\.?(host)?\z/i, ) end
Checks whether the commit email is linked to the authenticated user's GitHub account.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 167 def commit_email_linked_to_user? @emails = @client.emails @emails.map { |e| e[:email] }.include? @commit[:commit][:author][:email] end
Checks whether the commit is in a valid branch. A valid branch is defined as either the default branch of the repository, or the gh-pages branch.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 127 def commit_in_valid_branch? # If two refs are entirely different commit histories, the API responds # with a 404. Rescue Octokit::NotFound in this case. begin default_compare = @client.compare @repo[:full_name], @repo[:default_branch], @commit[:sha] rescue Octokit::NotFound default_compare = nil end # The compare status should be "identical" or "behind" if the commit is in # the default branch if default_compare.nil? || !(%w(identical behind).include?(default_compare[:status])) # If the commit is not in the default branch, check the gh-pages branch begin gh_pages_compare = @client.compare @repo[:full_name], "gh-pages", @commit[:sha] rescue Octokit::NotFound gh_pages_compare = nil end return false if !gh_pages_compare return false if !%w(identical behind).include? gh_pages_compare [:status] end true end
Checks whether the “or” criteria for counting a commit as a contribution are correctly met.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 270 def or_criteria_met? @user_has_starred_repo || @user_can_push_to_repo || @user_is_repo_org_member || @user_has_fork_of_repo || @user_has_opened_issue_or_pr_in_repo end
Parses the commit URL provided.
@return [Array] URL parts: nwo, sha
# File lib/contribution-checker/checker.rb, line 100 def parse_commit_url(url) begin parts = URI.parse(@commit_url).path.split("/") nwo = "#{parts[1]}/#{parts[2]}" sha = parts[4] return nwo, sha rescue raise ContributionChecker::InvalidCommitUrlError end end
Checks whether the repository is a fork.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 159 def repository_is_fork? @repo[:fork] end
Checks whether the authenticated user has push access to the repository in which the commit exists.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 194 def user_can_push_to_repo? @repo[:permissions][:push] end
Checks whether the authenticated user has forked the repository in which the commit exists.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 202 def user_has_fork_of_repo? # The API doesn't provide a simple means of checking whether a user has # forked a repository. # First, if there are no forks for the repository, return false. return false if @repo[:forks_count] == 0 # Then check whether it's worth getting the list of forks if @repo[:forks_count] <= 100 repo_forks = @client.forks @repo[:full_name], :per_page => 100 repo_forks.each do |f| return true if f[:owner][:login] == @user[:login] end end # Then try to directly find a repository with the same name as the # repository in which the commit exists. potential_fork_nwo = "#{@user[:login]}/#{@repo[:name]}" begin potential_fork = @client.repository potential_fork_nwo if potential_fork[:fork] return true if potential_fork[:parent][:full_name] == @repo[:full_name] end rescue Octokit::NotFound # Keep going... end # Otherwise, get the user's forks and check the `parent` field of each # fork to see whether it matches @repo. @client.auto_paginate = true @user_repos = @client.repos @user_forks = @user_repos.select { |r| r[:fork] } @user_forks.each do |f| r = @client.repository f[:full_name] if r[:parent][:full_name] == @repo[:full_name] @client.auto_paginate = false return true end end @client.auto_paginate = false false end
Checks whether the authenticated user has opened an issue or pull request in the repository in which the commit exists.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 249 def user_has_opened_issue_or_pr_in_repo? issues_and_prs = @client.list_issues @nwo, :creator => @user[:login], :state => "all" issues_and_prs.any? end
Checks whether the authenticated user has starred the repository in which the commit exists.
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 176 def user_has_starred_repo? @client.starred? @nwo end
Checks whether the authenticated user is a member of the organization that owns the repository (if the repository is owned by an organization account).
@return [Boolean]
# File lib/contribution-checker/checker.rb, line 185 def user_is_repo_org_member? return false if @repo[:owner][:type] != "Organization" @client.organization_member? @repo[:owner][:login], @user[:login] end