class GitHubLabeler

Attributes

client[RW]
logger[RW]
repo_labels[RW]

Public Class Methods

new(token, verbose=false, labels=nil) click to toggle source
# File lib/github_labeler.rb, line 12
def initialize(token, verbose=false, labels=nil)
  @logger = Logger.new(STDERR)
  @logger.sev_threshold = verbose ? Logger::DEBUG : Logger::WARN

  @logger.debug "Creating new GitHubLabeler instance."

  @logger.debug "Creating a new Octokit client with token #{token[0..5]}"

  begin
    @client = Octokit::Client.new(:access_token => token)
    @client.rate_limit
  rescue Octokit::Unauthorized => exception
    @logger.error "Token #{token[0..5]} is not valid"
    raise ArgumentError.new("Token #{token[0..5]} is not valid")
  end

  @logger.debug "Token #{token[0..5]} is valid"

  @repo_labels = !labels.nil? ? labels : {}
end

Public Instance Methods

add_label_to_repo(repo, label, options = {}) click to toggle source

Create a single change for adding a label to a repo

# File lib/github_labeler.rb, line 203
def add_label_to_repo(repo, label, options = {})
  existing_label = @repo_labels[repo][label[:name].downcase]

  if existing_label
    if existing_label[:color] != label[:color] or existing_label[:name] != label[:name]
      @logger.warn "Label #{label[:name]} already exist, creating an update"
      return { :type => "update", :repo => repo, :label => label }
    end
  else
    return { :type => "add", :repo => repo, :label => label }
  end

  @logger.warn "Label #{label[:name]} already exist and is the same. No change created"
  return nil
end
add_labels_to_repos(repos, labels, options = {}) click to toggle source

Create changes for adding a list of labels to a list of repos

# File lib/github_labeler.rb, line 129
def add_labels_to_repos(repos, labels, options = {})
  @logger.debug "Adding labels to repositories"
  return process_labels_for_repos(repos, labels, method(:add_label_to_repo), options)
end
change_string(change, options = {}) click to toggle source

Get a human readable string representation of a change

# File lib/github_labeler.rb, line 295
def change_string(change, options = {})
  return "#{change[:repo]} - #{change[:type]} - #{change[:label][:name]} - color: #{change[:label][:color]} - new_name: #{change[:label][:new_name]}"
end
delete_label_from_repo(repo, label, options = {}) click to toggle source

Create a single change for deleting a label from a repo

# File lib/github_labeler.rb, line 222
def delete_label_from_repo(repo, label, options = {})
  existing_label = @repo_labels[repo][label[:name].downcase]

  if existing_label
    return { :type => "delete", :repo => repo, :label => label }
  end

  @logger.warn "Label #{label[:name]} doesn't exist. No change created"
  return nil
end
delete_labels_from_repos(repos, labels, options = {}) click to toggle source

Create changes for deleting a list of labels from a list of repos

# File lib/github_labeler.rb, line 137
def delete_labels_from_repos(repos, labels, options = {})
  @logger.debug "Deleting labels from repositories"
  return process_labels_for_repos(repos, labels, method(:delete_label_from_repo), options)
end
duplicate_labels_from_repo(repo_source, repos_end, options = {}) click to toggle source

Creates changes for duplicating labels from one repo to other repos

# File lib/github_labeler.rb, line 275
def duplicate_labels_from_repo(repo_source, repos_end, options = {})
  @logger.debug "Duplicating labels from repo #{repo_source}"
  source_repo_labels = export_labels_from_repo(repo_source, options)
  return add_labels_to_repos(repos_end, source_repo_labels, options)
end
execute_changes(changes, options = {}) click to toggle source

Executes a list of label changes. Each change has the following format:

{

:type => "update/create/delete",
:repo => "testrename/testing",
:label => {:color => "fc2929", :name => "design", :new_name => "ui"}

}

# File lib/github_labeler.rb, line 54
def execute_changes(changes, options = {})
  @logger.debug "Executing changes"

  if !is_remaining_rate_limit_sufficient?(changes.size)
    @logger.error "Remaining rate limit is not enough to make all changes. Wait for the limit to refresh and try again."
    return []
  end

  changes = validate_changes(changes, options)

  changes.each do |change|
    @logger.debug "Executing change: #{change_string(change)}"

    if change[:type] == "add"
      success = @client.add_label(change[:repo], change[:label][:name], change[:label][:color])

      if !@repo_labels[change[:repo]].nil?
        @repo_labels[change[:repo]][success[:name].downcase] = {:name => success[:name], :color => success[:color]}
      end

      @logger.debug "Change succeded"
      next
    end

    if change[:type] == "update"
      new_label = {:name => change[:label][:new_name] || change[:label][:name]}
      if !change[:label][:color].nil?
        new_label[:color] = change[:label][:color]
      end

      success = @client.update_label(change[:repo], change[:label][:name], new_label)

      if !@repo_labels[change[:repo]].nil?
        @repo_labels[change[:repo]][success[:name].downcase] = {:name => success[:name], :color => success[:color]}
      end

      @logger.debug "Change succeded"
      next
    end

    if change[:type] == "delete"
      success = @client.delete_label!(change[:repo], change[:label][:name])

      if !@repo_labels[change[:repo]].nil?
        @repo_labels[change[:repo]][change[:label][:name].downcase] = nil
      end

      @logger.debug "Change succeded"
      next
    end
  end

  @logger.debug "Done executing changes"

  return changes
end
export_labels_from_repo(repo, options = {}) click to toggle source

Fetches a list of labels for a repository

# File lib/github_labeler.rb, line 284
def export_labels_from_repo(repo, options = {})
  @logger.debug "Exporting labels from repo #{repo}"

  @client.labels(repo).map do |label|
    { :name => label[:name], :color => label[:color] }
  end
end
is_remaining_rate_limit_sufficient?(expected_number_of_calls) click to toggle source

Checks if the remaining rate limit allows us to make the specified number of changes

# File lib/github_labeler.rb, line 37
def is_remaining_rate_limit_sufficient?(expected_number_of_calls)
  remaining_limit = @client.rate_limit.remaining

  @logger.debug "There are #{expected_number_of_calls} API calls to be made, and the remaining API rate limit quota is #{remaining_limit}."

  return expected_number_of_calls <= @client.rate_limit.remaining
end
process_labels_for_repos(repos, labels, change_creator, options = {}) click to toggle source

Generic creation of changes for list of labels and list of repos

# File lib/github_labeler.rb, line 161
def process_labels_for_repos(repos, labels, change_creator, options = {})
  if !is_remaining_rate_limit_sufficient?(repos.size)
    @logger.error "Rate limit is not enough to process all labels in repositories"
    return nil
  end

  changes = []

  for repo in repos
    repo_name = repo if repo.instance_of?(String)
    repo_name = repo[:full_name] if repo.instance_of?(Hash)

    @logger.debug "Processing labels for repository #{repo_name}"

    refresh_repo_labels(repo_name, options)

    for label in labels
      @logger.debug "Processing label #{label[:name]}"
      change = change_creator.call(repo_name, label, options)
      changes << change if !change.nil?
    end
  end

  return changes
end
recolor_label_in_repo(repo, label, options = {}) click to toggle source

Create a single change for recoloring a label in a repo

# File lib/github_labeler.rb, line 256
def recolor_label_in_repo(repo, label, options = {})
  existing_label = @repo_labels[repo][label[:name].downcase]

  if existing_label
    if existing_label[:color] != label[:color]
      return { :type => "update", :repo => repo, :label => label }
    end
  else
    @logger.warn "Label #{label[:name]} doesn't exist. Creating a create change"
    return { :type => "add", :repo => repo, :label => label }
  end

  @logger.warn "Label #{label[:name]} exist and is the same. No change created"
  return nil
end
recolor_labels_in_repos(repos, labels, options = {}) click to toggle source

Create changes for recoloring a list of labels in a list of repos

# File lib/github_labeler.rb, line 153
def recolor_labels_in_repos(repos, labels, options = {})
  @logger.debug "Recoloring labels in repositories"
  return process_labels_for_repos(repos, labels, method(:recolor_label_in_repo), options)
end
refresh_repo_labels(repo, options = {}) click to toggle source

Fetches the list of labels in a repository and stores them in the labels cache

# File lib/github_labeler.rb, line 191
def refresh_repo_labels(repo, options = {})
  @logger.debug "Fetching label information for #{repo}"

  @repo_labels[repo] = {}
  @client.labels(repo).each do |label|
    @repo_labels[repo][label[:name].downcase] = label
  end
end
rename_label_in_repo(repo, label, options = {}) click to toggle source

Create a single change for renaming a label in a repo

# File lib/github_labeler.rb, line 236
def rename_label_in_repo(repo, label, options = {})
  existing_label = @repo_labels[repo][label[:name].downcase]

  if existing_label
    if label[:new_name] and label[:new_name] != label[:name]
      return { :type => "update", :repo => repo, :label => label }
    end
  else
    @logger.warn "Label #{label[:name]} doesn't exist. Creating a create change"
    newLabel = {:name => label[:new_name], :color => label[:color]}
    return { :type => "add", :repo => repo, :label => newLabel }
  end

  @logger.warn "Label #{label[:name]} exist and is the same. No change created"
  return nil
end
rename_labels_in_repos(repos, labels, options = {}) click to toggle source

Create changes for renaming a list of labels in a list of repos

# File lib/github_labeler.rb, line 145
def rename_labels_in_repos(repos, labels, options = {})
  @logger.debug "Renaming labels in repositories"
  return process_labels_for_repos(repos, labels, method(:rename_label_in_repo), options)
end
update_repos_labels_cache(repo, label) click to toggle source

Updates repo labels cache for a specific label

# File lib/github_labeler.rb, line 114
def update_repos_labels_cache(repo, label)
  @repo_labels[change[:repo]][change[:label][:name].downcase] = success
end
validate_changes(changes, options = {}) click to toggle source

Validates changes by merging multiple updates into one, removing duplicates, detecting conflicts, etc.

# File lib/github_labeler.rb, line 122
def validate_changes(changes, options = {})
  return changes.sort_by { |hsh| [hsh["repo"], hsh["type"]] }
end