class Codeowners::Checker

Check if code owners are consistent between a git repository and the CODEOWNERS file. It compares what's being changed in the PR and check if the current files and folders are also being declared in the CODEOWNERS file. By default (:validate_owners property) it also reads OWNERS with list of all possible/valid owners and validates every owner in CODEOWNERS is defined in OWNERS

Constants

VERSION

Attributes

owners_list[R]

Public Class Methods

new(repo, from, to) click to toggle source

Get repo metadata and compare with the owners

# File lib/codeowners/checker.rb, line 22
def initialize(repo, from, to)
  @git = Git.open(repo, log: Logger.new(IO::NULL))
  @repo_dir = repo
  @from = from || 'HEAD'
  @to = to
  @owners_list = OwnersList.new(@repo_dir)
end

Public Instance Methods

added_files() click to toggle source
# File lib/codeowners/checker.rb, line 34
def added_files
  changes_to_analyze.select { |_k, v| v == 'A' }.keys
end
changes_for_patterns(patterns) click to toggle source
# File lib/codeowners/checker.rb, line 42
def changes_for_patterns(patterns)
  @git.diff(@from, @to).path(patterns).name_status.keys.reject(&whitelist)
end
changes_to_analyze() click to toggle source
# File lib/codeowners/checker.rb, line 30
def changes_to_analyze
  @git.diff(@from, @to).name_status.reject(&whitelist)
end
changes_with_ownership(owner = '') click to toggle source
# File lib/codeowners/checker.rb, line 59
def changes_with_ownership(owner = '')
  patterns_by_owner.each_with_object({}) do |(own, patterns), changes_with_owners|
    next if (owner != '') && (own != owner)

    changes_with_owners[own] = changes_for_patterns(patterns)
  end
end
codeowners() click to toggle source
# File lib/codeowners/checker.rb, line 103
def codeowners
  @codeowners ||= CodeOwners.new(
    FileAsArray.new(CodeOwners.filename(@repo_dir))
  )
end
commit_changes!() click to toggle source
# File lib/codeowners/checker.rb, line 117
def commit_changes!
  @git.add(File.realpath(@codeowners.filename))
  @git.add(File.realpath(@owners_list.filename))
  @git.commit('Fix pattern :robot:')
end
consistent?() click to toggle source
# File lib/codeowners/checker.rb, line 113
def consistent?
  results.none?
end
defined_owner?(file) click to toggle source
# File lib/codeowners/checker.rb, line 81
def defined_owner?(file)
  codeowners.find do |line|
    next unless line.pattern?

    return true if line.match_file?(file)
  end

  false
end
fix!() click to toggle source
# File lib/codeowners/checker.rb, line 38
def fix!
  Enumerator.new { |yielder| catch(:user_quit) { results.each { |r| yielder << r } } }
end
hash_of_arrays() click to toggle source
# File lib/codeowners/checker.rb, line 55
def hash_of_arrays
  Hash.new { |h, k| h[k] = [] }
end
main_group() click to toggle source
# File lib/codeowners/checker.rb, line 109
def main_group
  codeowners.main_group
end
missing_reference() click to toggle source
# File lib/codeowners/checker.rb, line 73
def missing_reference
  @missing_reference ||= added_files.reject(&method(:defined_owner?))
end
pattern_has_files(pattern) click to toggle source
# File lib/codeowners/checker.rb, line 77
def pattern_has_files(pattern)
  @git.ls_files(pattern.gsub(%r{^/}, '')).reject(&whitelist).any?
end
patterns_by_owner() click to toggle source
# File lib/codeowners/checker.rb, line 46
def patterns_by_owner
  @patterns_by_owner ||=
    codeowners.each_with_object(hash_of_arrays) do |line, patterns_by_owner|
      next unless line.pattern?

      line.owners.each { |owner| patterns_by_owner[owner] << line.pattern.gsub(%r{^/}, '') }
    end
end
unrecognized_line() click to toggle source
# File lib/codeowners/checker.rb, line 123
def unrecognized_line
  @unrecognized_line ||= codeowners.select do |line|
    line.is_a?(Codeowners::Checker::Group::UnrecognizedLine)
  end.reject(&whitelist)
end
useless_pattern() click to toggle source
# File lib/codeowners/checker.rb, line 67
def useless_pattern
  @useless_pattern ||= codeowners.select do |line|
    line.pattern? && !pattern_has_files(line.pattern)
  end
end
whitelist() click to toggle source
# File lib/codeowners/checker.rb, line 99
def whitelist
  @whitelist ||= Whitelist.new(whitelist_filename)
end
whitelist?() click to toggle source
# File lib/codeowners/checker.rb, line 91
def whitelist?
  whitelist.exist?
end
whitelist_filename() click to toggle source
# File lib/codeowners/checker.rb, line 95
def whitelist_filename
  @whitelist_filename ||= CodeOwners.filename(@repo_dir) + '_WHITELIST'
end

Private Instance Methods

invalid_owners() click to toggle source
# File lib/codeowners/checker.rb, line 131
def invalid_owners
  @invalid_owners ||= @owners_list.invalid_owners(codeowners)
end
results() click to toggle source
# File lib/codeowners/checker.rb, line 135
def results
  @results ||= Enumerator.new do |yielder|
    missing_reference.each { |ref| yielder << [:missing_ref, ref] }
    useless_pattern.each { |pattern| yielder << [:useless_pattern, pattern] }
    invalid_owners.each { |(owner, missing)| yielder << [:invalid_owner, owner, missing] }
    unrecognized_line.each { |line| yielder << [:unrecognized_line, line] }
  end
end