codeowners-checker 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new(:rubocop)
9
+
10
+ task default: %i[spec rubocop]
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5
+
6
+ require 'codeowners/cli/main'
7
+
8
+ Codeowners::Cli::Main.start ARGV
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'code/ownership/checker'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'codeowners/checker/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'codeowners-checker'
9
+ spec.version = Codeowners::Checker::VERSION
10
+ spec.authors = ['Jônatas Davi Paganini', 'Eva Kadlecová', 'Michal Papis']
11
+ spec.email = ['open-source@toptal.com']
12
+
13
+ spec.summary = 'Check consistency of Github CODEOWNERS and git changes.'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'bin'
20
+ spec.executables = ['codeowners-checker']
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_dependency 'fuzzy_match', '~> 2.1'
24
+ spec.add_dependency 'git', '~> 1.5'
25
+ spec.add_dependency 'thor', '~> 0.20.3'
26
+ spec.add_development_dependency 'bundler', '~> 1.16'
27
+ spec.add_development_dependency 'pry', '~> 0.12.2'
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rb-readline', '~> 0.5.5'
30
+ spec.add_development_dependency 'rspec', '~> 3.0'
31
+ spec.add_development_dependency 'rubocop', '~> 0.61.1'
32
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.30'
33
+ spec.add_development_dependency 'simplecov', '~> 0.16.1'
34
+ end
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1350" height="559.33"><rect width="1350" height="559.33" rx="5" ry="5" class="a"/><svg y="0%" x="0%"><circle cx="20" cy="20" r="6" fill="#ff5f58"/><circle cx="40" cy="20" r="6" fill="#ffbd2e"/><circle cx="60" cy="20" r="6" fill="#18c132"/></svg><svg height="499.33" viewBox="0 0 131 49.933" width="1310" x="15" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="50"><style>@keyframes j{0%{transform:translateX(0)}5.77%{transform:translateX(-131px)}5.91%{transform:translateX(-262px)}7.22%{transform:translateX(-393px)}7.84%{transform:translateX(-524px)}8.29%{transform:translateX(-655px)}8.9%{transform:translateX(-786px)}9.55%{transform:translateX(-917px)}10.2%{transform:translateX(-1048px)}12.57%{transform:translateX(-1179px)}14.02%{transform:translateX(-1310px)}15.87%{transform:translateX(-1441px)}16.16%{transform:translateX(-1572px)}16.83%{transform:translateX(-1703px)}17.22%{transform:translateX(-1834px)}18.26%{transform:translateX(-1965px)}26.12%{transform:translateX(-2096px)}27.78%{transform:translateX(-2227px)}30.13%{transform:translateX(-2489px)}34.33%{transform:translateX(-2620px)}35.58%{transform:translateX(-2751px)}36.16%{transform:translateX(-2882px)}36.9%{transform:translateX(-3013px)}37.79%{transform:translateX(-3144px)}38.28%{transform:translateX(-3275px)}38.74%{transform:translateX(-3406px)}39.27%{transform:translateX(-3537px)}41.32%{transform:translateX(-3668px)}42.11%{transform:translateX(-3799px)}42.64%{transform:translateX(-3930px)}43.68%{transform:translateX(-4061px)}44.3%{transform:translateX(-4192px)}44.96%{transform:translateX(-4323px)}45.97%{transform:translateX(-4454px)}46.61%{transform:translateX(-4585px)}47.51%{transform:translateX(-4716px)}48.07%{transform:translateX(-4847px)}48.77%{transform:translateX(-4978px)}49.52%{transform:translateX(-5109px)}49.94%{transform:translateX(-5240px)}50.81%{transform:translateX(-5633px)}55.56%{transform:translateX(-5764px)}57.47%{transform:translateX(-5895px)}57.48%{transform:translateX(-6026px)}62.68%{transform:translateX(-6157px)}64.07%{transform:translateX(-6419px)}66.81%{transform:translateX(-6550px)}68.72%{transform:translateX(-6681px)}69.53%{transform:translateX(-6812px)}70.4%{transform:translateX(-6943px)}71.26%{transform:translateX(-7074px)}71.8%{transform:translateX(-7205px)}72.31%{transform:translateX(-7336px)}72.74%{transform:translateX(-7467px)}74.57%{transform:translateX(-7598px)}75.81%{transform:translateX(-7729px)}76.82%{transform:translateX(-7860px)}77.46%{transform:translateX(-7991px)}78.04%{transform:translateX(-8122px)}78.62%{transform:translateX(-8253px)}79.11%{transform:translateX(-8384px)}79.56%{transform:translateX(-8515px)}80.52%{transform:translateX(-8646px)}81.39%{transform:translateX(-8777px)}81.6%{transform:translateX(-8908px)}81.88%{transform:translateX(-9039px)}82.32%{transform:translateX(-9170px)}83.52%{transform:translateX(-9432px)}88.21%{transform:translateX(-9563px)}89.78%{transform:translateX(-9694px)}90.14%{transform:translateX(-9825px)}95.23%{transform:translateX(-9956px)}96.45%{transform:translateX(-10087px)}96.64%{transform:translateX(-10218px)}96.75%{transform:translateX(-10349px)}to{transform:translateX(-10480px)}}.a{fill:#282d35}.f{fill:#b9c0cb}.g{fill:#a8cc8c}.l{fill:#b9c0cb;text-decoration:underline}.m{fill:#e88388;font-weight:700}</style><g font-size="1.67" font-family="Monaco,Consolas,Menlo,'Bitstream Vera Sans Mono','Powerline Symbols',monospace"><defs><symbol id="1"><text y="1.67" class="f">Evas-MBP%</text></symbol><symbol id="2"><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="f">check</text></symbol><symbol id="3"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">added:</text><text x="12.024" y="1.67" class="f">&quot;app/controllers/application_controller.rb&quot;.</text><text x="57.114" y="1.67" class="f">Add</text><text x="61.122" y="1.67" class="f">owner</text><text x="67.134" y="1.67" class="f">to</text><text x="70.14" y="1.67" class="f">CODEOWNERS?</text><text x="82.164" y="1.67" class="f">y</text></symbol><symbol id="4"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text></symbol><symbol id="5"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@</text></symbol><symbol id="6"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@c</text></symbol><symbol id="7"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@co</text></symbol><symbol id="8"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@com</text></symbol><symbol id="9"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@comp</text></symbol><symbol id="10"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@compa</text></symbol><symbol id="11"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@compan</text></symbol><symbol id="12"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@company</text></symbol><symbol id="13"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@company/</text></symbol><symbol id="14"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@company/b</text></symbol><symbol id="15"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@company/backend-devs</text></symbol><symbol id="16"><text y="1.67" class="f">Possible</text><text x="9.018" y="1.67" class="f">groups</text><text x="16.032" y="1.67" class="f">to</text><text x="19.038" y="1.67" class="f">which</text><text x="25.05" y="1.67" class="f">the</text><text x="29.058" y="1.67" class="f">pattern</text><text x="37.074" y="1.67" class="f">belongs:</text></symbol><symbol id="17"><text y="1.67" class="f">1</text><text x="2.004" y="1.67" class="f">-</text><text x="4.008" y="1.67" class="f">#</text><text x="6.012" y="1.67" class="f">Backend</text></symbol><symbol id="18"><text y="1.67" class="f">Choose</text><text x="7.014" y="1.67" class="f">group:</text><text x="15.03" y="1.67" class="f">1</text></symbol><symbol id="19"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">added:</text><text x="12.024" y="1.67" class="f">&quot;lib/invoices.rb&quot;.</text><text x="31.062" y="1.67" class="f">Add</text><text x="35.07" y="1.67" class="f">owner</text><text x="41.082" y="1.67" class="f">to</text><text x="44.088" y="1.67" class="f">CODEOWNERS?</text><text x="56.112" y="1.67" class="f">y</text></symbol><symbol id="20"><text y="1.67" class="f">File</text><text x="5.01" y="1.67" class="f">owner(s):</text><text x="16.032" y="1.67" class="f">@company/billing-team</text></symbol><symbol id="21"><text y="1.67" class="f">Add</text><text x="4.008" y="1.67" class="f">to</text><text x="7.014" y="1.67" class="f">the</text><text x="11.022" y="1.67" class="f">end</text><text x="15.03" y="1.67" class="f">of</text><text x="18.036" y="1.67" class="f">the</text><text x="22.044" y="1.67" class="f">codeowners</text><text x="33.066" y="1.67" class="f">file?</text><text x="39.078" y="1.67" class="f">y</text></symbol><symbol id="22"><text y="1.67" class="f">Commit</text><text x="7.014" y="1.67" class="f">changes?</text><text x="16.032" y="1.67" class="f">y</text></symbol><symbol id="a"><path fill="transparent" d="M0 0h131v24H0z"/></symbol><symbol id="b"><path fill="#6f7683" d="M0 0h1.102v2.171H0z"/></symbol></defs><path class="a" d="M0 0h131v49.933H0z"/><g style="animation-duration:23.886376s;animation-iteration-count:infinite;animation-name:j;animation-timing-function:steps(1,end)"><svg width="10611"><svg><use xlink:href="#a"/><use xlink:href="#b" x="-.004"/></svg><svg x="131"><use xlink:href="#a"/><use xlink:href="#b" x="-.004"/></svg><svg x="262"><use xlink:href="#a"/><use xlink:href="#b" x="9.996"/><use xlink:href="#1"/></svg><svg x="393"><use xlink:href="#a"/><use xlink:href="#b" x="10.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="l">c</text></svg><svg x="524"><use xlink:href="#a"/><use xlink:href="#b" x="11.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="l">co</text></svg><svg x="655"><use xlink:href="#a"/><use xlink:href="#b" x="12.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="m">cod</text></svg><svg x="786"><use xlink:href="#a"/><use xlink:href="#b" x="13.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">code</text></svg><svg x="917"><use xlink:href="#a"/><use xlink:href="#b" x="14.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="m">codeo</text></svg><svg x="1048"><use xlink:href="#a"/><use xlink:href="#b" x="15.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="m">codeow</text></svg><svg x="1179"><use xlink:href="#a"/><use xlink:href="#b" x="28.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text></svg><svg x="1310"><use xlink:href="#a"/><use xlink:href="#b" x="29.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="l">c</text></svg><svg x="1441"><use xlink:href="#a"/><use xlink:href="#b" x="30.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="f">ch</text></svg><svg x="1572"><use xlink:href="#a"/><use xlink:href="#b" x="31.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="f">che</text></svg><svg x="1703"><use xlink:href="#a"/><use xlink:href="#b" x="32.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="f">chec</text></svg><svg x="1834"><use xlink:href="#a"/><use xlink:href="#b" x="33.996"/><use xlink:href="#2"/></svg><svg x="1965"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="2.146"/><use xlink:href="#2"/></svg><svg x="2096"><use xlink:href="#a"/><use xlink:href="#b" x="81.996" y="2.146"/><use xlink:href="#2"/><text y="3.841" class="f">File</text><text x="5.01" y="3.841" class="f">added:</text><text x="12.024" y="3.841" class="f">&quot;app/controllers/application_controller.rb&quot;.</text><text x="57.114" y="3.841" class="f">Add</text><text x="61.122" y="3.841" class="f">owner</text><text x="67.134" y="3.841" class="f">to</text><text x="70.14" y="3.841" class="f">CODEOWNERS?</text></svg><svg x="2227"><use xlink:href="#a"/><use xlink:href="#b" x="82.996" y="2.146"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/></svg><svg x="2358"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/></svg><svg x="2489"><use xlink:href="#a"/><use xlink:href="#b" x="15.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/></svg><svg x="2620"><use xlink:href="#a"/><use xlink:href="#b" x="16.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#5" y="4.342"/></svg><svg x="2751"><use xlink:href="#a"/><use xlink:href="#b" x="17.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#6" y="4.342"/></svg><svg x="2882"><use xlink:href="#a"/><use xlink:href="#b" x="18.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#7" y="4.342"/></svg><svg x="3013"><use xlink:href="#a"/><use xlink:href="#b" x="19.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#8" y="4.342"/></svg><svg x="3144"><use xlink:href="#a"/><use xlink:href="#b" x="20.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#9" y="4.342"/></svg><svg x="3275"><use xlink:href="#a"/><use xlink:href="#b" x="21.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#10" y="4.342"/></svg><svg x="3406"><use xlink:href="#a"/><use xlink:href="#b" x="22.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#11" y="4.342"/></svg><svg x="3537"><use xlink:href="#a"/><use xlink:href="#b" x="23.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#12" y="4.342"/></svg><svg x="3668"><use xlink:href="#a"/><use xlink:href="#b" x="24.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#13" y="4.342"/></svg><svg x="3799"><use xlink:href="#a"/><use xlink:href="#b" x="25.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#14" y="4.342"/></svg><svg x="3930"><use xlink:href="#a"/><use xlink:href="#b" x="26.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/ba</text></svg><svg x="4061"><use xlink:href="#a"/><use xlink:href="#b" x="27.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/bac</text></svg><svg x="4192"><use xlink:href="#a"/><use xlink:href="#b" x="28.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/back</text></svg><svg x="4323"><use xlink:href="#a"/><use xlink:href="#b" x="29.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/backe</text></svg><svg x="4454"><use xlink:href="#a"/><use xlink:href="#b" x="30.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/backen</text></svg><svg x="4585"><use xlink:href="#a"/><use xlink:href="#b" x="31.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/backend</text></svg><svg x="4716"><use xlink:href="#a"/><use xlink:href="#b" x="32.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/backend-</text></svg><svg x="4847"><use xlink:href="#a"/><use xlink:href="#b" x="33.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/backend-d</text></svg><svg x="4978"><use xlink:href="#a"/><use xlink:href="#b" x="34.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/backend-de</text></svg><svg x="5109"><use xlink:href="#a"/><use xlink:href="#b" x="35.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><text y="6.012" class="f">File</text><text x="5.01" y="6.012" class="f">owner(s):</text><text x="16.032" y="6.012" class="f">@company/backend-dev</text></svg><svg x="5240"><use xlink:href="#a"/><use xlink:href="#b" x="36.996" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/></svg><svg x="5371"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="6.488"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/></svg><svg x="5502"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="10.83"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/></svg><svg x="5633"><use xlink:href="#a"/><use xlink:href="#b" x="14.996" y="10.83"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><text y="12.525" class="f">Choose</text><text x="7.014" y="12.525" class="f">group:</text></svg><svg x="5764"><use xlink:href="#a"/><use xlink:href="#b" x="15.996" y="10.83"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/></svg><svg x="5895"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="13.001"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/></svg><svg x="6026"><use xlink:href="#a"/><use xlink:href="#b" x="55.996" y="13.001"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><text y="14.696" class="f">File</text><text x="5.01" y="14.696" class="f">added:</text><text x="12.024" y="14.696" class="f">&quot;lib/invoices.rb&quot;.</text><text x="31.062" y="14.696" class="f">Add</text><text x="35.07" y="14.696" class="f">owner</text><text x="41.082" y="14.696" class="f">to</text><text x="44.088" y="14.696" class="f">CODEOWNERS?</text></svg><svg x="6157"><use xlink:href="#a"/><use xlink:href="#b" x="56.996" y="13.001"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/></svg><svg x="6288"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/></svg><svg x="6419"><use xlink:href="#a"/><use xlink:href="#b" x="15.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#4" y="15.197"/></svg><svg x="6550"><use xlink:href="#a"/><use xlink:href="#b" x="16.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#5" y="15.197"/></svg><svg x="6681"><use xlink:href="#a"/><use xlink:href="#b" x="17.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#6" y="15.197"/></svg><svg x="6812"><use xlink:href="#a"/><use xlink:href="#b" x="18.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#7" y="15.197"/></svg><svg x="6943"><use xlink:href="#a"/><use xlink:href="#b" x="19.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#8" y="15.197"/></svg><svg x="7074"><use xlink:href="#a"/><use xlink:href="#b" x="20.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#9" y="15.197"/></svg><svg x="7205"><use xlink:href="#a"/><use xlink:href="#b" x="21.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#10" y="15.197"/></svg><svg x="7336"><use xlink:href="#a"/><use xlink:href="#b" x="22.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#11" y="15.197"/></svg><svg x="7467"><use xlink:href="#a"/><use xlink:href="#b" x="23.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#12" y="15.197"/></svg><svg x="7598"><use xlink:href="#a"/><use xlink:href="#b" x="24.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#13" y="15.197"/></svg><svg x="7729"><use xlink:href="#a"/><use xlink:href="#b" x="25.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#14" y="15.197"/></svg><svg x="7860"><use xlink:href="#a"/><use xlink:href="#b" x="26.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/bi</text></svg><svg x="7991"><use xlink:href="#a"/><use xlink:href="#b" x="27.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/bil</text></svg><svg x="8122"><use xlink:href="#a"/><use xlink:href="#b" x="28.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/bill</text></svg><svg x="8253"><use xlink:href="#a"/><use xlink:href="#b" x="29.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/billi</text></svg><svg x="8384"><use xlink:href="#a"/><use xlink:href="#b" x="30.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/billin</text></svg><svg x="8515"><use xlink:href="#a"/><use xlink:href="#b" x="31.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/billing</text></svg><svg x="8646"><use xlink:href="#a"/><use xlink:href="#b" x="32.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/billing-</text></svg><svg x="8777"><use xlink:href="#a"/><use xlink:href="#b" x="33.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/billing-t</text></svg><svg x="8908"><use xlink:href="#a"/><use xlink:href="#b" x="34.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/billing-te</text></svg><svg x="9039"><use xlink:href="#a"/><use xlink:href="#b" x="35.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><text y="16.867" class="f">File</text><text x="5.01" y="16.867" class="f">owner(s):</text><text x="16.032" y="16.867" class="f">@company/billing-tea</text></svg><svg x="9170"><use xlink:href="#a"/><use xlink:href="#b" x="36.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/></svg><svg x="9301"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="17.343"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/></svg><svg x="9432"><use xlink:href="#a"/><use xlink:href="#b" x="38.996" y="17.343"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/><text y="19.038" class="f">Add</text><text x="4.008" y="19.038" class="f">to</text><text x="7.014" y="19.038" class="f">the</text><text x="11.022" y="19.038" class="f">end</text><text x="15.03" y="19.038" class="f">of</text><text x="18.036" y="19.038" class="f">the</text><text x="22.044" y="19.038" class="f">codeowners</text><text x="33.066" y="19.038" class="f">file?</text></svg><svg x="9563"><use xlink:href="#a"/><use xlink:href="#b" x="39.996" y="17.343"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/><use xlink:href="#21" y="17.368"/></svg><svg x="9694"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="19.514"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/><use xlink:href="#21" y="17.368"/></svg><svg x="9825"><use xlink:href="#a"/><use xlink:href="#b" x="15.996" y="19.514"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/><use xlink:href="#21" y="17.368"/><text y="21.209" class="f">Commit</text><text x="7.014" y="21.209" class="f">changes?</text></svg><svg x="9956"><use xlink:href="#a"/><use xlink:href="#b" x="16.996" y="19.514"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/><use xlink:href="#21" y="17.368"/><use xlink:href="#22" y="19.539"/></svg><svg x="10087"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="21.685"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/><use xlink:href="#21" y="17.368"/><use xlink:href="#22" y="19.539"/></svg><svg x="10218"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="21.685"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/><use xlink:href="#21" y="17.368"/><use xlink:href="#22" y="19.539"/></svg><svg x="10349"><use xlink:href="#a"/><use xlink:href="#b" x="9.996" y="21.685"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/><use xlink:href="#21" y="17.368"/><use xlink:href="#22" y="19.539"/><use xlink:href="#1" y="21.71"/></svg><svg x="10480"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="23.856"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="15.197"/><use xlink:href="#21" y="17.368"/><use xlink:href="#22" y="19.539"/><use xlink:href="#1" y="21.71"/></svg></svg></g></g></svg></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1350" height="559.33"><rect width="1350" height="559.33" rx="5" ry="5" class="a"/><svg y="0%" x="0%"><circle cx="20" cy="20" r="6" fill="#ff5f58"/><circle cx="40" cy="20" r="6" fill="#ffbd2e"/><circle cx="60" cy="20" r="6" fill="#18c132"/></svg><svg height="499.33" viewBox="0 0 131 49.933" width="1310" x="15" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="50"><style>@keyframes j{0%{transform:translateX(0)}8.43%{transform:translateX(-131px)}8.58%{transform:translateX(-262px)}10.85%{transform:translateX(-393px)}11.44%{transform:translateX(-524px)}12.04%{transform:translateX(-655px)}12.8%{transform:translateX(-786px)}13.62%{transform:translateX(-917px)}15%{transform:translateX(-1048px)}16.64%{transform:translateX(-1179px)}17.48%{transform:translateX(-1310px)}18.07%{transform:translateX(-1441px)}19.02%{transform:translateX(-1572px)}19.68%{transform:translateX(-1703px)}21.08%{transform:translateX(-1834px)}31.09%{transform:translateX(-2096px)}43.03%{transform:translateX(-2227px)}44.85%{transform:translateX(-2358px)}44.9%{transform:translateX(-2620px)}50.66%{transform:translateX(-2751px)}53.08%{transform:translateX(-2882px)}53.19%{transform:translateX(-3144px)}63.72%{transform:translateX(-3275px)}65.64%{transform:translateX(-3537px)}71.26%{transform:translateX(-3668px)}72.87%{transform:translateX(-3799px)}73.88%{transform:translateX(-3930px)}74.34%{transform:translateX(-4061px)}75.12%{transform:translateX(-4192px)}75.81%{transform:translateX(-4323px)}76.63%{transform:translateX(-4454px)}77.8%{transform:translateX(-4585px)}80.16%{transform:translateX(-4716px)}81.24%{transform:translateX(-4847px)}82.02%{transform:translateX(-4978px)}82.24%{transform:translateX(-5109px)}85.12%{transform:translateX(-5371px)}89.93%{transform:translateX(-5502px)}92.02%{transform:translateX(-5633px)}92.37%{transform:translateX(-5764px)}92.49%{transform:translateX(-5895px)}to{transform:translateX(-6026px)}}.a{fill:#282d35}.f{fill:#b9c0cb}.g{fill:#a8cc8c}.l{fill:#b9c0cb;text-decoration:underline}.m{fill:#e88388;font-weight:700}</style><g font-size="1.67" font-family="Monaco,Consolas,Menlo,'Bitstream Vera Sans Mono','Powerline Symbols',monospace"><defs><symbol id="1"><text y="1.67" class="f">Evas-MBP%</text></symbol><symbol id="2"><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="f">check</text></symbol><symbol id="3"><text y="1.67" class="f">Pattern</text><text x="8.016" y="1.67" class="f">&quot;app/models/billng.rb&quot;</text><text x="31.062" y="1.67" class="f">doesn&apos;t</text><text x="39.078" y="1.67" class="f">match.</text></symbol><symbol id="4"><text y="1.67" class="f">Replace</text><text x="8.016" y="1.67" class="f">with:</text><text x="14.028" y="1.67" class="f">&quot;app/models/billing.rb&quot;?</text></symbol><symbol id="5"><text y="1.67" class="f">(y)</text><text x="4.008" y="1.67" class="f">yes</text></symbol><symbol id="6"><text y="1.67" class="f">(i)</text><text x="4.008" y="1.67" class="f">ignore</text></symbol><symbol id="7"><text y="1.67" class="f">(e)</text><text x="4.008" y="1.67" class="f">edit</text><text x="9.018" y="1.67" class="f">the</text><text x="13.026" y="1.67" class="f">pattern</text></symbol><symbol id="8"><text y="1.67" class="f">(d)</text><text x="4.008" y="1.67" class="f">delete</text><text x="11.022" y="1.67" class="f">the</text><text x="15.03" y="1.67" class="f">pattern</text></symbol><symbol id="9"><text x="1.002" y="1.67" class="f">[y,</text><text x="5.01" y="1.67" class="f">i,</text><text x="8.016" y="1.67" class="f">e,</text><text x="11.022" y="1.67" class="f">d]</text></symbol><symbol id="10"><text x="1.002" y="1.67" class="f">[y,</text><text x="5.01" y="1.67" class="f">i,</text><text x="8.016" y="1.67" class="f">e,</text><text x="11.022" y="1.67" class="f">d]</text><text x="14.028" y="1.67" class="f">y</text></symbol><symbol id="11"><text y="1.67" class="f">Pattern</text><text x="8.016" y="1.67" class="f">&quot;lib/security/*&quot;</text><text x="25.05" y="1.67" class="f">doesn&apos;t</text><text x="33.066" y="1.67" class="f">match.</text></symbol><symbol id="12"><text x="1.002" y="1.67" class="f">[i,</text><text x="5.01" y="1.67" class="f">e,</text><text x="8.016" y="1.67" class="f">d]</text><text x="11.022" y="1.67" class="f">d</text></symbol><symbol id="13"><text y="1.67" class="f">Pattern</text><text x="8.016" y="1.67" class="f">&quot;.rubo.yml&quot;</text><text x="20.04" y="1.67" class="f">doesn&apos;t</text><text x="28.056" y="1.67" class="f">match.</text></symbol><symbol id="14"><text y="1.67" class="f">Replace</text><text x="8.016" y="1.67" class="f">with:</text><text x="14.028" y="1.67" class="f">&quot;db&quot;?</text></symbol><symbol id="15"><text x="1.002" y="1.67" class="f">[y,</text><text x="5.01" y="1.67" class="f">i,</text><text x="8.016" y="1.67" class="f">e,</text><text x="11.022" y="1.67" class="f">d]</text><text x="14.028" y="1.67" class="f">e</text></symbol><symbol id="16"><text y="1.67" class="f">Replace</text><text x="8.016" y="1.67" class="f">pattern</text><text x="16.032" y="1.67" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="1.67" class="f">with:</text><text x="35.07" y="1.67" class="f">.rubocop.yml</text></symbol><symbol id="17"><text y="1.67" class="f">Commit</text><text x="7.014" y="1.67" class="f">changes?</text><text x="16.032" y="1.67" class="f">y</text></symbol><symbol id="a"><path fill="transparent" d="M0 0h131v24H0z"/></symbol><symbol id="b"><path fill="#6f7683" d="M0 0h1.102v2.171H0z"/></symbol></defs><path class="a" d="M0 0h131v49.933H0z"/><g style="animation-duration:19.572061s;animation-iteration-count:infinite;animation-name:j;animation-timing-function:steps(1,end)"><svg width="6157"><svg><use xlink:href="#a"/><use xlink:href="#b" x="-.004"/></svg><svg x="131"><use xlink:href="#a"/><use xlink:href="#b" x="-.004"/></svg><svg x="262"><use xlink:href="#a"/><use xlink:href="#b" x="9.996"/><use xlink:href="#1"/></svg><svg x="393"><use xlink:href="#a"/><use xlink:href="#b" x="10.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="l">c</text></svg><svg x="524"><use xlink:href="#a"/><use xlink:href="#b" x="11.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="l">co</text></svg><svg x="655"><use xlink:href="#a"/><use xlink:href="#b" x="12.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="m">cod</text></svg><svg x="786"><use xlink:href="#a"/><use xlink:href="#b" x="13.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">code</text></svg><svg x="917"><use xlink:href="#a"/><use xlink:href="#b" x="14.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="m">codeo</text></svg><svg x="1048"><use xlink:href="#a"/><use xlink:href="#b" x="28.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text></svg><svg x="1179"><use xlink:href="#a"/><use xlink:href="#b" x="29.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="l">c</text></svg><svg x="1310"><use xlink:href="#a"/><use xlink:href="#b" x="30.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="f">ch</text></svg><svg x="1441"><use xlink:href="#a"/><use xlink:href="#b" x="31.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="f">che</text></svg><svg x="1572"><use xlink:href="#a"/><use xlink:href="#b" x="32.996"/><text y="1.67" class="f">Evas-MBP%</text><text x="10.02" y="1.67" class="g">codeowners-checker</text><text x="29.058" y="1.67" class="f">chec</text></svg><svg x="1703"><use xlink:href="#a"/><use xlink:href="#b" x="33.996"/><use xlink:href="#2"/></svg><svg x="1834"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="2.146"/><use xlink:href="#2"/></svg><svg x="1965"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="4.317"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/></svg><svg x="2096"><use xlink:href="#a"/><use xlink:href="#b" x="13.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#9" y="15.197"/></svg><svg x="2227"><use xlink:href="#a"/><use xlink:href="#b" x="14.996" y="15.172"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/></svg><svg x="2358"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="17.343"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/></svg><svg x="2489"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="19.514"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/></svg><svg x="2620"><use xlink:href="#a"/><use xlink:href="#b" x="10.996" y="26.027"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><text x="1.002" y="27.722" class="f">[i,</text><text x="5.01" y="27.722" class="f">e,</text><text x="8.016" y="27.722" class="f">d]</text></svg><svg x="2751"><use xlink:href="#a"/><use xlink:href="#b" x="11.996" y="26.027"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/></svg><svg x="2882"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="28.198"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/></svg><svg x="3013"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="30.369"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/></svg><svg x="3144"><use xlink:href="#a"/><use xlink:href="#b" x="13.996" y="41.224"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#9" y="41.249"/></svg><svg x="3275"><use xlink:href="#a"/><use xlink:href="#b" x="14.996" y="41.224"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/></svg><svg x="3406"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/></svg><svg x="3537"><use xlink:href="#a"/><use xlink:href="#b" x="34.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text></svg><svg x="3668"><use xlink:href="#a"/><use xlink:href="#b" x="35.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.</text></svg><svg x="3799"><use xlink:href="#a"/><use xlink:href="#b" x="36.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.r</text></svg><svg x="3930"><use xlink:href="#a"/><use xlink:href="#b" x="37.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.ru</text></svg><svg x="4061"><use xlink:href="#a"/><use xlink:href="#b" x="38.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.rub</text></svg><svg x="4192"><use xlink:href="#a"/><use xlink:href="#b" x="39.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.rubo</text></svg><svg x="4323"><use xlink:href="#a"/><use xlink:href="#b" x="40.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.ruboc</text></svg><svg x="4454"><use xlink:href="#a"/><use xlink:href="#b" x="41.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.ruboco</text></svg><svg x="4585"><use xlink:href="#a"/><use xlink:href="#b" x="42.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.rubocop</text></svg><svg x="4716"><use xlink:href="#a"/><use xlink:href="#b" x="43.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.rubocop.</text></svg><svg x="4847"><use xlink:href="#a"/><use xlink:href="#b" x="44.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.rubocop.y</text></svg><svg x="4978"><use xlink:href="#a"/><use xlink:href="#b" x="45.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><text y="45.09" class="f">Replace</text><text x="8.016" y="45.09" class="f">pattern</text><text x="16.032" y="45.09" class="f">&quot;.rubo.yml&quot;</text><text x="28.056" y="45.09" class="f">with:</text><text x="35.07" y="45.09" class="f">.rubocop.ym</text></svg><svg x="5109"><use xlink:href="#a"/><use xlink:href="#b" x="46.996" y="43.395"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><use xlink:href="#16" y="43.42"/></svg><svg x="5240"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="45.566"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><use xlink:href="#16" y="43.42"/></svg><svg x="5371"><use xlink:href="#a"/><use xlink:href="#b" x="15.996" y="45.566"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><use xlink:href="#16" y="43.42"/><text y="47.261" class="f">Commit</text><text x="7.014" y="47.261" class="f">changes?</text></svg><svg x="5502"><use xlink:href="#a"/><use xlink:href="#b" x="16.996" y="45.566"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><use xlink:href="#16" y="43.42"/><use xlink:href="#17" y="45.591"/></svg><svg x="5633"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="47.737"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><use xlink:href="#16" y="43.42"/><use xlink:href="#17" y="45.591"/></svg><svg x="5764"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="47.737"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><use xlink:href="#16" y="43.42"/><use xlink:href="#17" y="45.591"/></svg><svg x="5895"><use xlink:href="#a"/><use xlink:href="#b" x="9.996" y="47.737"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><use xlink:href="#16" y="43.42"/><use xlink:href="#17" y="45.591"/><use xlink:href="#1" y="47.762"/></svg><svg x="6026"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="49.908"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#10" y="15.197"/><use xlink:href="#11" y="17.368"/><use xlink:href="#7" y="19.539"/><use xlink:href="#8" y="21.71"/><use xlink:href="#6" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#5" y="32.565"/><use xlink:href="#6" y="34.736"/><use xlink:href="#7" y="36.907"/><use xlink:href="#8" y="39.078"/><use xlink:href="#15" y="41.249"/><use xlink:href="#16" y="43.42"/><use xlink:href="#17" y="45.591"/><use xlink:href="#1" y="47.762"/></svg></svg></g></g></svg></svg>
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'git'
4
+ require 'logger'
5
+
6
+ require_relative 'checker/code_owners'
7
+ require_relative 'checker/file_as_array'
8
+ require_relative 'checker/group'
9
+
10
+ module Codeowners
11
+ # Check if code owners are consistent between a git repository and the CODEOWNERS file.
12
+ # It compares what's being changed in the PR and check if the current files and folders
13
+ # are also being declared in the CODEOWNERS file.
14
+ class Checker
15
+ attr_accessor :when_useless_pattern, :when_new_file
16
+
17
+ # Get repo metadata and compare with the owners
18
+ def initialize(repo, from, to)
19
+ @git = Git.open(repo, log: Logger.new(IO::NULL))
20
+ @repo_dir = repo
21
+ @from = from || 'HEAD'
22
+ @to = to
23
+ end
24
+
25
+ def transformers
26
+ @transformers ||= []
27
+ end
28
+
29
+ def changes_to_analyze
30
+ @git.diff(@from, @to).name_status
31
+ end
32
+
33
+ def added_files
34
+ changes_to_analyze.select { |_k, v| v == 'A' }.keys
35
+ end
36
+
37
+ def check!
38
+ {
39
+ missing_ref: missing_reference,
40
+ useless_pattern: useless_pattern
41
+ }
42
+ end
43
+
44
+ def changes_for_patterns(patterns)
45
+ @git.diff(@from, @to).path(patterns).name_status.keys
46
+ end
47
+
48
+ def patterns_by_owner
49
+ @patterns_by_owner ||=
50
+ codeowners.each_with_object(hash_of_arrays) do |line, patterns_by_owner|
51
+ next unless line.pattern?
52
+
53
+ line.owners.each { |owner| patterns_by_owner[owner] << line.pattern }
54
+ end
55
+ end
56
+
57
+ def hash_of_arrays
58
+ Hash.new { |h, k| h[k] = [] }
59
+ end
60
+
61
+ def changes_with_ownership(owner = '')
62
+ patterns_by_owner.each_with_object({}) do |(own, patterns), changes_with_owners|
63
+ next if (owner != '') && (own != owner)
64
+
65
+ changes_with_owners[own] = changes_for_patterns(patterns)
66
+ end
67
+ end
68
+
69
+ def useless_pattern
70
+ codeowners.select do |line|
71
+ next unless line.pattern?
72
+
73
+ unless pattern_has_files(line.pattern)
74
+ @when_useless_pattern&.call(line)
75
+ true
76
+ end
77
+ end
78
+ end
79
+
80
+ def missing_reference
81
+ added_files.reject(&method(:defined_owner?))
82
+ end
83
+
84
+ def pattern_has_files(pattern)
85
+ @git.ls_files(pattern).any?
86
+ end
87
+
88
+ def defined_owner?(file)
89
+ codeowners.find do |line|
90
+ next unless line.pattern?
91
+
92
+ return true if line.match_file?(file)
93
+ end
94
+
95
+ @when_new_file&.call(file) if @when_new_file
96
+ false
97
+ end
98
+
99
+ def codeowners
100
+ @codeowners ||= CodeOwners.new(
101
+ FileAsArray.new(codeowners_filename),
102
+ transformers: transformers
103
+ )
104
+ end
105
+
106
+ def main_group
107
+ codeowners.main_group
108
+ end
109
+
110
+ def commit_changes!
111
+ @git.add(codeowners_filename)
112
+ @git.commit('Fix pattern :robot:')
113
+ end
114
+
115
+ private
116
+
117
+ def codeowners_filename
118
+ directories = ['', '.github', 'docs', '.gitlab']
119
+ paths = directories.map { |dir| File.join(@repo_dir, dir, 'CODEOWNERS') }
120
+ Dir.glob(paths).first || paths.first
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codeowners
4
+ class Checker
5
+ # Array.delete in contrary to Ruby documentation uses == instead of equal? for comparison.
6
+ # safe_delete removes an object from an array comparing objects by equal? method.
7
+ module Array
8
+ def safe_delete(object)
9
+ delete_at(index { |item| item.equal?(object) })
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ Array.prepend(Codeowners::Checker::Array)
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'group'
4
+ require_relative 'array'
5
+
6
+ module Codeowners
7
+ class Checker
8
+ # Manage CODEOWNERS file reading and re-writing.
9
+ class CodeOwners
10
+ include Enumerable
11
+
12
+ attr_reader :file_manager, :transform_line_procs
13
+
14
+ def initialize(file_manager, transformers: nil)
15
+ @file_manager = file_manager
16
+ @transform_line_procs = [
17
+ method(:build_line),
18
+ *transformers
19
+ ]
20
+ end
21
+
22
+ def persist!
23
+ file_manager.content = to_content
24
+ end
25
+
26
+ def main_group
27
+ @main_group ||= Group.parse(list)
28
+ end
29
+
30
+ def each(&block)
31
+ main_group.each(&block)
32
+ end
33
+
34
+ def to_content
35
+ main_group.to_content
36
+ end
37
+
38
+ private
39
+
40
+ def list
41
+ @list ||= @file_manager.content.yield_self do |list|
42
+ transform_line_procs.each do |transform_line_proc|
43
+ list = list.flat_map { |line| transform_line_proc.call(line) }.compact
44
+ end
45
+ list
46
+ end
47
+ end
48
+
49
+ def build_line(line)
50
+ Codeowners::Checker::Group::Line.build(line)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codeowners
4
+ class Checker
5
+ # Convert CODEOWNERS file content to an array.
6
+ class FileAsArray
7
+ def initialize(file)
8
+ @file = file
9
+ @target_dir, = File.split(@file)
10
+ end
11
+
12
+ def content
13
+ @content ||= File.readlines(@file).map(&:chomp)
14
+ rescue Errno::ENOENT
15
+ @content = []
16
+ end
17
+
18
+ def content=(content)
19
+ @content = content
20
+
21
+ Dir.mkdir(@target_dir) unless Dir.exist?(@target_dir)
22
+
23
+ File.open(@file, 'w+') do |f|
24
+ f.puts content
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'line_grouper'
4
+ require_relative 'group/line'
5
+ require_relative 'array'
6
+
7
+ module Codeowners
8
+ class Checker
9
+ # Manage the groups content and handle operations on the groups.
10
+ class Group
11
+ include Enumerable
12
+
13
+ attr_accessor :parent
14
+
15
+ def self.parse(lines)
16
+ new.parse(lines)
17
+ end
18
+
19
+ def initialize
20
+ @list = []
21
+ end
22
+
23
+ def each(&block)
24
+ @list.each do |object|
25
+ if object.is_a?(Group)
26
+ object.each(&block)
27
+ else
28
+ block.call(object)
29
+ end
30
+ end
31
+ end
32
+
33
+ def parse(lines)
34
+ LineGrouper.call(self, lines)
35
+ end
36
+
37
+ def to_content
38
+ @list.flat_map(&:to_content)
39
+ end
40
+
41
+ # Returns an array of strings representing the structure of the group.
42
+ # It indent internal subgroups for readability and debugging purposes.
43
+ def to_tree(indentation = '')
44
+ @list.each_with_index.flat_map do |item, index|
45
+ if indentation.empty?
46
+ item.to_tree(indentation + ' ')
47
+ elsif index.zero?
48
+ item.to_tree(indentation + '+ ')
49
+ elsif index == @list.length - 1
50
+ item.to_tree(indentation + '\\ ')
51
+ else
52
+ item.to_tree(indentation + '| ')
53
+ end
54
+ end
55
+ end
56
+
57
+ def owner
58
+ owners.first
59
+ end
60
+
61
+ # Owners are ordered by the amount of occurrences
62
+ def owners
63
+ all_owners.group_by(&:itself).sort_by do |_owner, occurrences|
64
+ -occurrences.count
65
+ end.map(&:first)
66
+ end
67
+
68
+ def subgroups_owned_by(owner)
69
+ @list.flat_map do |item|
70
+ return [] unless item.is_a?(Group)
71
+
72
+ a = []
73
+ a << item if item.owner == owner
74
+ a += item.subgroups_owned_by(owner)
75
+ a
76
+ end.compact
77
+ end
78
+
79
+ def title
80
+ @list.first.to_s
81
+ end
82
+
83
+ def create_subgroup
84
+ group = self.class.new
85
+ group.parent = self
86
+ @list << group
87
+ group
88
+ end
89
+
90
+ def add(line)
91
+ line.parent = self
92
+ @list << line
93
+ end
94
+
95
+ def insert(line)
96
+ line.parent = self
97
+ index = insert_at_index(line)
98
+ @list.insert(index, line)
99
+ end
100
+
101
+ def remove(line)
102
+ @list.safe_delete(line)
103
+ remove! unless any?(Pattern)
104
+ end
105
+
106
+ def remove!
107
+ @list.clear
108
+ parent&.remove(self)
109
+ self.parent = nil
110
+ end
111
+
112
+ def ==(other)
113
+ other.kind_of?(Group) && other.list == list
114
+ end
115
+
116
+ protected
117
+
118
+ attr_accessor :list
119
+
120
+ private
121
+
122
+ def all_owners
123
+ flat_map do |item|
124
+ item.owners if item.pattern?
125
+ end.compact
126
+ end
127
+
128
+ def insert_at_index(line)
129
+ patterns = @list.grep(Pattern)
130
+ new_patterns_sorted = patterns.dup.push(line).sort
131
+ new_pattern_index = new_patterns_sorted.index { |l| l.equal? line }
132
+
133
+ if new_pattern_index > 0 # rubocop:disable Style/NumericPredicate
134
+ new_pattern_index + 1
135
+ else
136
+ find_last_line_of_initial_comments
137
+ end
138
+ end
139
+
140
+ def find_last_line_of_initial_comments
141
+ @list.each_with_index do |item, index|
142
+ return index unless item.is_a?(Comment)
143
+ end
144
+ 0
145
+ end
146
+ end
147
+ end
148
+ end