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/whitelist.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, Whitelist

Constant Summary collapse

VERSION =
'1.1.2'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(repo, from, to) ⇒ Checker

Get repo metadata and compare with the owners



22
23
24
25
26
27
28
# 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

Instance Attribute Details

#owners_listObject (readonly)

Returns the value of attribute owners_list.



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

def owners_list
  @owners_list
end

Instance Method Details

#added_filesObject



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

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

#changes_for_patterns(patterns) ⇒ Object



42
43
44
# 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_analyzeObject



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

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

#changes_with_ownership(owner = '') ⇒ Object



59
60
61
62
63
64
65
# 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

#codeownersObject



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

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

#commit_changes!Object



117
118
119
120
121
# 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?Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/codeowners/checker.rb', line 113

def consistent?
  results.none?
end

#defined_owner?(file) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
84
85
86
87
88
89
# 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!Object



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

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

#hash_of_arraysObject



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

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

#main_groupObject



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

def main_group
  codeowners.main_group
end

#missing_referenceObject



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

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

#pattern_has_files(pattern) ⇒ Object



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

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

#patterns_by_ownerObject



46
47
48
49
50
51
52
53
# 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_lineObject



123
124
125
126
127
# 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_patternObject



67
68
69
70
71
# 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

#whitelistObject



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

def whitelist
  @whitelist ||= Whitelist.new(whitelist_filename)
end

#whitelist?Boolean

Returns:

  • (Boolean)


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

def whitelist?
  whitelist.exist?
end

#whitelist_filenameObject



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

def whitelist_filename
  @whitelist_filename ||= CodeOwners.filename(@repo_dir) + '_WHITELIST'
end