Last active
July 8, 2020 18:25
-
-
Save matheusd/02453f59e9d9da731eff154733d87b6c to your computer and use it in GitHub Desktop.
A script to check a dcrlnd commit if it's reasonably sane. Useful to check a range of commits by using a `git rebase [target] --exec ./checkcommit.py --modtidy --test --rpc --lint --showcommit --nofooter`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/python3 | |
import sys | |
import subprocess | |
from os import path | |
from functools import reduce | |
class bcolors: | |
RED = '\033[31m' | |
BLUE = '\033[34m' | |
GREEN = '\033[32m' | |
YELLOW = '\033[33m' | |
ENDC = '\033[0m' | |
def fgBlue(s): | |
return "%s%s%s" % (bcolors.BLUE, s, bcolors.ENDC) | |
def fgRed(s): | |
return "%s%s%s" % (bcolors.RED, s, bcolors.ENDC) | |
def fgGreen(s): | |
return "%s%s%s" % (bcolors.GREEN, s, bcolors.ENDC) | |
def fgYellow(s): | |
return "%s%s%s" % (bcolors.YELLOW, s, bcolors.ENDC) | |
def hasArg(a): | |
return a in sys.argv | |
def cmd(c): | |
res = subprocess.run(c, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) | |
stdout = res.stdout.decode('unicode_escape') | |
return (res.returncode, stdout) | |
def affectedDirs(): | |
(res, stdout) = cmd(["git", "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD"]) | |
if res != 0: | |
print("git diff-tree returned an error") | |
print(stdout) | |
raise Exception("internal error") | |
lines = stdout.split("\n") | |
dirs = [path.dirname(f) for f in lines] | |
dirs = ["./"+d if d != "" else "." for d in dirs] | |
dirs = sorted(list(set(dirs))) | |
if len(dirs) == 0: | |
return [] | |
if dirs[0] == ".": | |
dirs = dirs[1:] | |
dirs.append(".") | |
return dirs | |
def wtDirty(): | |
(res, stdout) = cmd(["git", "status", "--porcelain"]) | |
return res != 0 or stdout != "" | |
def printCurrentCommit(): | |
(res, stdout) = cmd(["git", "log", "--decorate", "--abbrev-commit", "--format=format:%C(bold green)%ci%C(reset) %<(20,trunc)%C(dim white)%an%C(reset) %C(bold blue)%h%C(reset) %<(60,trunc)%C(white)%s%C(reset) %C(auto)%D%C(reset)", "-1", "--color=always"]) | |
print(fgYellow("Current Commit:")) | |
print(stdout) | |
if res != 0: | |
raise Exception("unable to get git log") | |
def reportErrors(outs): | |
for i in range(len(outs)): | |
(c, res, stdout) = outs[i] | |
if res == 0: | |
continue | |
print("\n%s failed\n" % fgRed(" ".join(c))) | |
print(stdout) | |
def main(): | |
outs = [] | |
failed = False | |
progress = not hasArg("-quiet") | |
failFast = hasArg("-1") | |
pkgs = affectedDirs() | |
testTags = '-tags=dev debug' | |
if wtDirty(): | |
fgRed("Cannot be used with a dirty working tree") | |
if hasArg("--showcommit"): | |
printCurrentCommit() | |
# Packages that shouldn't be tested during individual --build. | |
build_excludes = ["./docker/dcrwallet", "./lntest/itest", "./.github/workflows", | |
"./docs"] | |
test_excludes = [x for x in build_excludes] | |
# Run the command and accumulate the result. | |
def accCmd(c): | |
nonlocal outs | |
nonlocal failed | |
if progress: | |
print("exec %s" % fgBlue('{:>70}'.format(" ".join(c))), end=" ", flush=True) | |
(res, stdout) = cmd(c) | |
if res != 0: | |
failed = True | |
outs.append((c, res, stdout)) | |
if progress: | |
print(fgRed("✗")) | |
if failFast: | |
reportErrors(outs) | |
raise Exception("failed fast") | |
else: | |
if progress: | |
print(fgGreen("✓")) | |
return res == 0 | |
# Processing steps | |
if hasArg("--lint"): | |
accCmd(["make", "lint"]) | |
if hasArg("--build"): | |
for i in range(len(pkgs)): | |
if pkgs[i] in build_excludes: | |
continue | |
accCmd(["go", "build", pkgs[i]]) | |
if hasArg("--fullbuild"): | |
accCmd(["make", "build"]) | |
if hasArg("--test"): | |
for i in range(len(pkgs)): | |
if pkgs[i] in test_excludes: | |
continue | |
accCmd(["go", "test", testTags, "-timeout=8m", pkgs[i]]) | |
# Regenerate rpc and check if it's different than committed one. | |
if hasArg("--rpc"): | |
changedRpc = reduce((lambda acc, pkg: acc or "lnrpc" in pkg), pkgs) | |
if changedRpc: | |
if accCmd(["make", "rpc"]): | |
if wtDirty(): | |
reportErrors(outs) | |
print(fgRed("'make rpc' generated uncommitted changes")) | |
raise Exception("make rpc error") | |
if hasArg("--modtidy"): | |
accCmd(["go", "mod", "tidy"]) | |
if wtDirty(): | |
reportErrors(outs) | |
print(ftRed("'go mod tidy' generated uncommitted changes")) | |
raise Exception("go mod tidy") | |
if failed: | |
reportErrors(outs) | |
raise Exception("Failed!") | |
if progress: | |
print("\n") | |
if not hasArg("--nofooter"): | |
print(fgGreen("All's well that ends well!")) | |
if __name__ == "__main__": | |
try: | |
main() | |
except Exception as e: | |
print(e) | |
print(fgRed("Exiting with failure")) | |
sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment