diff --git a/contrib/infix-moon-secret.yaml b/contrib/infix-moon-secret.yaml new file mode 100644 index 0000000..04b102c --- /dev/null +++ b/contrib/infix-moon-secret.yaml @@ -0,0 +1,6 @@ +# A small example config showing how to add secrets such as access tokens. +# This config contains secret additions to the base config should not be +# version-controlled in the wild. Merge it with an additional -f FILE. +repos: + kernelkit/infix: + token: github_pat_XXXXX diff --git a/ghmoon b/ghmoon index 2ca9593..61a0df3 100755 --- a/ghmoon +++ b/ghmoon @@ -21,6 +21,15 @@ except: MIN_ENQUEUE_INTERVAL = 30 +def deep_merge(base, overlay): + """Recursively merge overlay into base. Dicts merge key-wise; everything else is replaced.""" + if isinstance(base, dict) and isinstance(overlay, dict): + out = dict(base) + for k, v in overlay.items(): + out[k] = deep_merge(base.get(k), v) if k in base else v + return out + return overlay + gistgh = None context = None config = None @@ -443,19 +452,25 @@ def init(args): global repos global wq - cfgfile = args.config - if not cfgfile: + cfgfiles = args.config + if not cfgfiles: for src in (os.path.expanduser("~/.ghmoon/config.yaml"), "/etc/ghmoon/config.yaml"): - try: - cfgfile = open(src, "r") + if os.path.exists(src): + cfgfiles = [src] break - except: - pass - assert cfgfile, "No config specified, an no default found" + assert cfgfiles, "No config specified, and no default found" + + config = {} + for path in cfgfiles: + with open(path, "r") as f: + config = deep_merge(config, yaml.load(f, Loader=yaml.FullLoader) or {}) + + if args.print_config: + yaml.dump(config, sys.stdout, default_flow_style=False, sort_keys=False) + sys.exit(0) - config = yaml.load(cfgfile, Loader=yaml.FullLoader) context = config.get("context", f"{getpass.getuser()}@{socket.gethostname()}") gistgh = GH(token=config.get("gist", {}).get("token")) @@ -470,7 +485,10 @@ def init(args): if __name__ == "__main__": parser = argparse.ArgumentParser(prog="ghmoon") parser.add_argument("-f", "--config-file", - type=argparse.FileType("r"), dest="config") + action="append", dest="config", default=[], + help="Config file (repeat to layer; later files override earlier ones)") + parser.add_argument("--print-config", action="store_true", + help="Print the merged config as YAML and exit") sps = parser.add_subparsers(dest="cmd")