Skip to content

Instantly share code, notes, and snippets.

@tiffany352
Last active August 24, 2022 22:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiffany352/c0a17b6ef0dd8ff5ee0276b9d3bad43f to your computer and use it in GitHub Desktop.
Save tiffany352/c0a17b6ef0dd8ff5ee0276b9d3bad43f to your computer and use it in GitHub Desktop.
I think I got whoowns.py from someone on slack, but I modified it to output CSV.
import io
import subprocess
import whoowns
import argparse
def main():
parser = argparse.ArgumentParser(description="Generates a CSV of all files in the repo and which codeowner is set.")
parser.add_argument("out")
args = parser.parse_args()
owners = whoowns.get_owners('./CODEOWNERS')
file = io.open(args.out, "w", encoding="utf-8")
file.write("path,owners\n")
all_files = subprocess.run(["git", "ls-files"], capture_output=True, text=True).stdout.split('\n')
for path in all_files:
file_owners = owners.of(path)
file.write("%s,%s\n" % (path, " ".join(map(lambda o: o[1], file_owners))))
file.flush()
file.close()
if __name__ == "__main__":
main()
# Returns list of codeowners for files touched in current branch.
def "whoowns" [] {
let root = (git rev-parse --show-toplevel | str trim)
enter $root
let changed_files = (git diff --name-only upstream/master...HEAD | lines)
let files = (python ~\Documents\Scripts\whoowns.py $changed_files)
exit
$files | from csv | sort-by owner file
}
def "flag-status" [] {
ls flags\tbennett\ |
par-each {|it|
do -i {
git log -1 --pretty=format:%ci $it.name
} |
complete |
select stdout |
update stdout { |it|
$it.stdout |
into datetime
} |
insert flag {
$it.name |
parse "flags\\tbennett\\{flag}.json" |
get flag
}
} |
rename date flag |
flatten |
sort-by date
}
def "merge-stable" [branch] {
git checkout $branch;
git pull --set-upstream origin $branch;
git fetch upstream;
git merge upstream/stable;
git push
}
import glob
import argparse
import json
import os
import subprocess
import re
import sys
from codeowners import CodeOwners
import whoowns
flag_regex = re.compile('FASTFLAGVARIABLE\((\w+),\s*\w+\)')
def main():
parser = argparse.ArgumentParser(description="Find fast flags owned by the given team")
parser.add_argument("team")
parser.add_argument("fflags_repo")
args = parser.parse_args()
team = args.team
fflags_repo = args.fflags_repo
co_path = whoowns.find_codeowners_path(os.getcwd())
dir, filename = os.path.split(co_path)
os.chdir(dir)
files = list(filter(lambda f: f.endswith((".h", ".cpp")), subprocess.run(["git", "ls-files"], capture_output=True, text=True).stdout.split('\n')))
owner = ('TEAM', team)
with open(co_path, "rt") as f:
owners = CodeOwners(f.read())
found = []
count = 0
last = None
for file in files:
next = count / len(files) * 100.0
if last != next:
if last != None:
sys.stdout.write("\x1b[1A\x1b[2K") # move up cursor and delete whole line
print("Running... %d%%" % (next))
last = next
count += 1
# print("testing", file)
# print("owners", owners.of(file))
# print("needle", owner)
if owner in owners.of(file):
# print("have match!!!!", file)
with open(file, "rt") as f:
for flag in flag_regex.findall(f.read()):
# print(file, flag)
flag_glob = "flags/*/*%s.json" % flag
# print(flag_glob)
# print(fflags_repo)
flag_value = None
flag_age = ''
flag_timestamp = 0
for match in glob.glob(flag_glob, root_dir=fflags_repo, recursive=True):
with open(fflags_repo + "/" + match, "rt") as f:
data = json.load(f)
flag_age = subprocess.run(["git", "log", "-n", "1", "--pretty=format:%cr", file], capture_output=True, text=True).stdout
flag_timestamp = int(subprocess.run(["git", "log", "-n", "1", "--pretty=format:%ct", file], capture_output=True, text=True).stdout)
if 'Buckets' in data:
flag_value = "complex"
else:
for bucket, value in data.items():
flag_value = "%s in %s" % (value, bucket)
# print("| % 50s | % 50s | % 20s | % 15s |" % (file, flag, flag_value, flag_age))
found.append({
"file": file.removeprefix('Client/'),
"flag": flag,
"value": flag_value,
"age": flag_age,
"timestamp": flag_timestamp,
})
found.sort(key=lambda item: item["timestamp"])
sys.stdout.write("\x1b[1A\x1b[2K") # delete progress bar
for item in found:
print("| % 50s | % 50s | % 20s | % 15s |" % (item["file"], item["flag"], item["value"], item["age"]))
if __name__ == "__main__":
main()
import argparse
import codeowners
import os
def find_codeowners_path(p):
"""Searches the folder containing the path 'p' and all parents until
a CODEOWNERS file is found. Returns 'None' if no file is found."""
head, tail = os.path.split(p)
if tail == '':
return None
co_path = os.path.join(head, 'CODEOWNERS')
if os.path.exists(co_path):
return os.path.normpath(co_path)
else:
return find_codeowners_path(head)
def make_relative(root, path):
"""Converts a path to a unix-style path relative to the root folder"""
p = os.path.normpath(os.path.abspath(path))
abs_root = os.path.abspath(root)
prefix = os.path.commonprefix([abs_root, p])
if prefix != abs_root:
raise Exception(f'{p} does not exist under the root folder {abs_root}')
relpath = os.path.relpath(p, abs_root)
return relpath.replace('\\', '/')
def describe_owners(file_path):
co_path = find_codeowners_path(file_path)
if co_path:
owners = get_owners(co_path)
rel_path = make_relative(os.path.split(co_path)[0], file_path)
results = owners.of(rel_path)
if len(results) == 0:
print(f'"{file_path}",none,"No matching entries in CODEOWNERS"')
else:
for result in results:
print(f'"{file_path}",{result[0].lower()},"{result[1]}"')
else:
print(f'"{file_path}",none,"Unable to find CODEOWNERS file"')
def get_owners(co_path):
"""Get a CodeOwners object for the specified CODEOWNERS file path"""
with open(co_path, "rt") as f:
# process the file to remove leading /'s which don't seem to be handled properly by the
# codeowners python module.
contents = []
for line in f.readlines():
stripped_line = line.strip()
if stripped_line.startswith('/'):
stripped_line = stripped_line[1:]
contents.append(stripped_line)
processed = "\n".join(contents)
return codeowners.CodeOwners(processed)
def main():
parser = argparse.ArgumentParser(description="Show user/team ownership information for specified files")
parser.add_argument("files", nargs='+')
args = parser.parse_args()
print('file,owner_type,owner')
for file in args.files:
describe_owners(file)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment