File indexing completed on 2024-05-19 15:24:57
0001 #!/usr/bin/env python3 0002 0003 import os 0004 import yaml 0005 import shlex 0006 import pathlib 0007 import argparse 0008 import subprocess 0009 from collections import namedtuple 0010 0011 CiData = namedtuple("CiData", ["entries", "variables", "default", "args"]) 0012 0013 0014 def list_jobs(data: CiData): 0015 for name in sorted(data.entries.keys()): 0016 print(name) 0017 0018 0019 def write_script(file, steps, name): 0020 file.write(r"echo -e '\x1b[1m%s\x1b[m'" % name) 0021 file.write("\n") 0022 for step in steps: 0023 file.write(step + "\n") 0024 0025 0026 def exec_cmd(cmd_args): 0027 print(" ".join(map(shlex.quote, cmd_args))) 0028 subprocess.call(cmd_args) 0029 0030 0031 def run_job(data: CiData): 0032 job_data = data.default 0033 job_data.update(data.entries[data.args.job]) 0034 0035 image = job_data["image"] 0036 0037 git_recursive = data.variables.get("GIT_SUBMODULE_STRATEGY") == "recursive" 0038 0039 parent_dir = data.args.work_path 0040 job_filename = data.args.job.replace(":", "_").replace("/", "_") 0041 work_dir = parent_dir / job_filename 0042 0043 if data.args.local_files: 0044 work_dir = data.args.clone_url 0045 elif not work_dir.exists(): 0046 parent_dir.mkdir(parents=True, exist_ok=True) 0047 git_args = [data.args.clone_url, job_filename, "-b", data.args.branch] 0048 if git_recursive: 0049 git_args.append("--recursive") 0050 exec_cmd(["git", "-C", str(parent_dir), "clone"] + git_args) 0051 else: 0052 exec_cmd(["git", "-C", str(work_dir), "pull"]) 0053 if git_recursive: 0054 exec_cmd(["git", "-C", str(work_dir), "submodule", "update"]) 0055 0056 script_filename = parent_dir / (job_filename + ".sh") 0057 with open(script_filename, "w") as script_file: 0058 scripts = ["before_script", "script", "after_script"] 0059 script_file.write("#!/usr/bin/env bash\nset -ex\ncd /ci\n") 0060 for script in scripts: 0061 write_script(script_file, job_data.get(script, []), script) 0062 script_filename.chmod(0o755) 0063 0064 script_wrapper_filename = parent_dir / "ci_wrapper.sh" 0065 with open(script_wrapper_filename, "w") as script_file: 0066 script_file.write("#!/usr/bin/env bash\ncd /ci\n/ci.sh || bash") 0067 script_wrapper_filename.chmod(0o755) 0068 0069 docker_vars = ["-e", "DISPLAY"] 0070 for item in data.variables.items(): 0071 docker_vars.append("-e") 0072 docker_vars.append("%s=%s" % item) 0073 0074 if data.args.privileged: 0075 docker_vars.append("--privileged") 0076 0077 exec_cmd([ 0078 "docker", 0079 "run", "-it", 0080 "-v", "%s:/ci" % work_dir, 0081 "-v", "%s:/ci.sh" % script_filename, 0082 "-v", "%s:/ci_wrapper.sh" % script_wrapper_filename, 0083 "-v" "/tmp/.X11-unix", 0084 ] + docker_vars + [ 0085 image, 0086 "bash", "-c", "/ci_wrapper.sh" 0087 ]) 0088 0089 0090 def main(): 0091 root = pathlib.Path(__file__).parent.parent 0092 file = root / ".gitlab-ci.yml" 0093 0094 parser = argparse.ArgumentParser() 0095 parser.add_argument("--input-file", "-i", default=file, type=pathlib.Path) 0096 0097 sub = parser.add_subparsers() 0098 sub.add_parser("list-jobs", aliases=["list", "ls"]).set_defaults(action=list_jobs) 0099 0100 sub_run = sub.add_parser("run") 0101 sub_run.set_defaults(action=run_job) 0102 sub_run.add_argument("job") 0103 sub_run.add_argument("--local-files", action="store_true", help="Use the directory from --clone-url as is instead of cloning from git") 0104 sub_run.add_argument("--privileged", action="store_true") 0105 sub_run.add_argument("--clone-url", default=str(root)) # default="https://gitlab.com/mattbas/glaxnimate.git") 0106 sub_run.add_argument("--work-path", default=pathlib.Path("/tmp/glaxnimate_ci"), type=pathlib.Path) 0107 sub_run.add_argument("--branch", "-b", default="master") 0108 0109 ns = parser.parse_args() 0110 0111 with open(ns.input_file) as infile: 0112 doc = yaml.load(infile.read(), Loader=yaml.FullLoader) 0113 0114 default = doc.pop("default", {}) 0115 variables = doc.pop("variables", {}) 0116 0117 ns.action(CiData(doc, variables, default, ns)) 0118 0119 0120 if __name__ == "__main__": 0121 main()