Class: Codeowners::Checker

Inherits:
Object
  • Object
show all
Defined in:
lib/codeowners/checker.rb,
lib/codeowners/checker/array.rb,
lib/codeowners/checker/group.rb,
lib/codeowners/checker/owner.rb,
lib/codeowners/checker/version.rb,
lib/codeowners/checker/group/line.rb,
lib/codeowners/checker/code_owners.rb,
lib/codeowners/checker/group/empty.rb,
lib/codeowners/checker/owners_list.rb,
lib/codeowners/checker/line_grouper.rb,
lib/codeowners/checker/file_as_array.rb,
lib/codeowners/checker/group/comment.rb,
lib/codeowners/checker/group/pattern.rb,
lib/codeowners/checker/group/group_end_comment.rb,
lib/codeowners/checker/group/unrecognized_line.rb,
lib/codeowners/checker/group/group_begin_comment.rb

Overview

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

Defined Under Namespace

Modules: Array, Owner Classes: CodeOwners, FileAsArray, Group, LineGrouper, OwnersList

Constant Summary collapse

VERSION =
'1.1.1'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(repo, from, to) ⇒ Checker

Get repo metadata and compare with the owners


21
22
23
24
25
26
27
# File 'lib/codeowners/checker.rb', line 21

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

Instance Attribute Details

#owners_listObject (readonly)

Returns the value of attribute owners_list


18
19
20
# File 'lib/codeowners/checker.rb', line 18

def owners_list
  @owners_list
end

Instance Method Details

#added_filesObject


33
34
35
# File 'lib/codeowners/checker.rb', line 33

def added_files
  changes_to_analyze.select { |_k, v| v == 'A' }.keys
end

#changes_for_patterns(patterns) ⇒ Object


41
42
43
# File 'lib/codeowners/checker.rb', line 41

def changes_for_patterns(patterns)
  @git.diff(@from, @to).path(patterns).name_status.keys
end

#changes_to_analyzeObject


29
30
31
# File 'lib/codeowners/checker.rb', line 29

def changes_to_analyze
  @git.diff(@from, @to).name_status
end

#changes_with_ownership(owner = '') ⇒ Object


58
59
60
61
62
63
64
# File 'lib/codeowners/checker.rb', line 58

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

#codeownersObject


90
91
92
93
94
# File 'lib/codeowners/checker.rb', line 90

def codeowners
  @codeowners ||= CodeOwners.new(
    FileAsArray.new(CodeOwners.filename(@repo_dir))
  )
end

#commit_changes!Object


104
105
106
107
108
# File 'lib/codeowners/checker.rb', line 104

def commit_changes!
  @git.add(File.realpath(@codeowners.filename))
  @git.add(File.realpath(@owners_list.filename))
  @git.commit('Fix pattern :robot:')
end

#consistent?Boolean

Returns:

  • (Boolean)

100
101
102
# File 'lib/codeowners/checker.rb', line 100

def consistent?
  results.none?
end

#defined_owner?(file) ⇒ Boolean

Returns:

  • (Boolean)

80
81
82
83
84
85
86
87
88
# File 'lib/codeowners/checker.rb', line 80

def defined_owner?(file)
  codeowners.find do |line|
    next unless line.pattern?

    return true if line.match_file?(file)
  end

  false
end

#fix!Object


37
38
39
# File 'lib/codeowners/checker.rb', line 37

def fix!
  Enumerator.new { |yielder| catch(:user_quit) { results.each { |r| yielder << r } } }
end

#hash_of_arraysObject


54
55
56
# File 'lib/codeowners/checker.rb', line 54

def hash_of_arrays
  Hash.new { |h, k| h[k] = [] }
end

#main_groupObject


96
97
98
# File 'lib/codeowners/checker.rb', line 96

def main_group
  codeowners.main_group
end

#missing_referenceObject


72
73
74
# File 'lib/codeowners/checker.rb', line 72

def missing_reference
  @missing_reference ||= added_files.reject(&method(:defined_owner?))
end

#pattern_has_files(pattern) ⇒ Object


76
77
78
# File 'lib/codeowners/checker.rb', line 76

def pattern_has_files(pattern)
  @git.ls_files(pattern.gsub(%r{^/}, '')).any?
end

#patterns_by_ownerObject


45
46
47
48
49
50
51
52
# File 'lib/codeowners/checker.rb', line 45

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_lineObject


110
111
112
# File 'lib/codeowners/checker.rb', line 110

def unrecognized_line
  @unrecognized_line ||= codeowners.select { |line| line.is_a?(Codeowners::Checker::Group::UnrecognizedLine) }
end

#useless_patternObject


66
67
68
69
70
# File 'lib/codeowners/checker.rb', line 66

def useless_pattern
  @useless_pattern ||= codeowners.select do |line|
    line.pattern? && !pattern_has_files(line.pattern)
  end
end