class GemsBond::Fetchers::Github
Fetches data from GitHub
Constants
- REPOSITORY_REGEX
GitHub repository pattern, e.g.: “github.com/BigBigDoudou/gems_bond”
Public Class Methods
Initializes an instance @param url [String] URL of the GitHub repository @return [GemsBond::Fetchers::Github]
GemsBond::Fetchers::Fetcher::new
# File lib/gems_bond/fetchers/github.rb, line 23 def initialize(url) super(url) @url = url end
Validates that `url` matches GitHub repository URL
# File lib/gems_bond/fetchers/github.rb, line 15 def valid_url?(url) url&.match?(REPOSITORY_REGEX) end
Public Instance Methods
Returns number of contributors @return [Integer] @note GitHub API does not provide this number out of the box
so we fetch all repository contributors and paginate with 1 per page thus the last page (from headers) should equal the number of contributors
# File lib/gems_bond/fetchers/github.rb, line 58 def contributors_count client = Octokit::Client.new(access_token: token, per_page: 1) client.contributors(@repository_path) response = client.last_response links = response.headers[:link] # e.g.: "[...] <https://api.github.com/repositories/8514/contributors?per_page=1&page=377>; rel=\"last\"" return 0 unless links Integer(links.match(/.*per_page=1&page=(?<last>\d+)>; rel="last"/)[:last], 10) end
Returns number of days since last commit @return [Date]
# File lib/gems_bond/fetchers/github.rb, line 86 def days_since_last_commit return unless last_commit_date Integer(Date.today - last_commit_date) end
Returns number of forks @return [Integer]
# File lib/gems_bond/fetchers/github.rb, line 43 def forks_count @repository["forks"] end
Returns date of last commit (on main branch) @return [Date]
# File lib/gems_bond/fetchers/github.rb, line 77 def last_commit_date date = client.commits(@repository_path).first[:commit][:committer][:date] return unless date Date.parse(date.to_s) end
Returns size of the lib directory @return [Integer]
# File lib/gems_bond/fetchers/github.rb, line 94 def lib_size contents_size = dir_size("lib") return unless contents_size lines_count_estimation = contents_size / 25 return lines_count_estimation if lines_count_estimation < 100 lines_count_estimation - lines_count_estimation % 100 end
Returns number of open issues @return [Integer]
# File lib/gems_bond/fetchers/github.rb, line 71 def open_issues_count @repository["open_issues"] end
Returns number of stars @return [Integer]
# File lib/gems_bond/fetchers/github.rb, line 49 def stars_count @repository["watchers"] end
Starts the service @return [Boolean] @note rescue connection errors with nil
GemsBond::Fetchers::Fetcher#start
# File lib/gems_bond/fetchers/github.rb, line 31 def start super parse_url login # ensure repository exists (otherwise it raises Octokit error) set_repository rescue Octokit::Unauthorized, Octokit::InvalidRepository, Octokit::NotFound stop end
Private Instance Methods
Initializes a client @return [Octokit::Client]
# File lib/gems_bond/fetchers/github.rb, line 127 def client Octokit::Client.new(access_token: token) end
Returns size of the given directory @param dir_path [String] path to the directory, e.g.: “lib/devise/strategies” @return [Integer] @note sum size of each subdirectories recursively
# File lib/gems_bond/fetchers/github.rb, line 147 def dir_size(dir_path) contents = client.contents(@repository_path, path: dir_path) # starts accumulator with size of files acc = contents .select { |content| content[:type] == "file" } .sum { |content| content[:size] } # adds size of subdirectories to the accumulator, with recursion acc += contents .select { |content| content[:type] == "dir" } .sum { |sub_dir| dir_size("#{dir_path}/#{sub_dir[:name]}") } acc rescue Octokit::NotFound nil end
Logs with client @return [String] GitHub'username
# File lib/gems_bond/fetchers/github.rb, line 119 def login return unless token @login ||= client.user.login end
Parses url to find out repository path @return [String] @raise Octokit::InvalidRepository if the url pattern is invalid
# File lib/gems_bond/fetchers/github.rb, line 109 def parse_url matches = @url.match(REPOSITORY_REGEX) raise Octokit::InvalidRepository unless matches path = matches[:repository].split("/") @repository_path = "#{path[0]}/#{path[1]}" end
Returns repository object @return [Sawyer::Resource]
# File lib/gems_bond/fetchers/github.rb, line 139 def set_repository @repository = client.repo(@repository_path) end
Returns token from configuration @return [String, nil]
# File lib/gems_bond/fetchers/github.rb, line 133 def token GemsBond.configuration&.github_token end