1*9473e04dSbugGenerator 2*9473e04dSbugGeneratorimport sys 3*9473e04dSbugGeneratorimport argparse 4*9473e04dSbugGeneratorimport yaml 5*9473e04dSbugGeneratorimport os 6*9473e04dSbugGeneratorfrom datetime import date 7*9473e04dSbugGeneratorimport time 8*9473e04dSbugGenerator 9*9473e04dSbugGeneratorgithub_yaml = "" 10*9473e04dSbugGeneratorworkspace = "" 11*9473e04dSbugGeneratornemu_home = "" 12*9473e04dSbugGeneratoram_home = "" 13*9473e04dSbugGeneratorhead_sha = "" 14*9473e04dSbugGeneratorwave_home = "" 15*9473e04dSbugGeneratorperf_home = "" 16*9473e04dSbugGeneratorset_env = "" 17*9473e04dSbugGeneratorsh_path = "" 18*9473e04dSbugGenerator 19*9473e04dSbugGeneratordef remove_empty(list_str): 20*9473e04dSbugGenerator list_new = [] 21*9473e04dSbugGenerator for s in list_str: 22*9473e04dSbugGenerator if not (s == ""): 23*9473e04dSbugGenerator list_new.append(s) 24*9473e04dSbugGenerator return list_new 25*9473e04dSbugGenerator 26*9473e04dSbugGeneratordef split_cmd(cmd): 27*9473e04dSbugGenerator c = cmd.replace("\\\n", " ") 28*9473e04dSbugGenerator c = remove_empty(c.split("\n")) 29*9473e04dSbugGenerator cs = [] 30*9473e04dSbugGenerator for ci in c: 31*9473e04dSbugGenerator ci = ci.replace("\\\n", " ") 32*9473e04dSbugGenerator ci = ci.replace("\n\n", "\n") 33*9473e04dSbugGenerator ci = ci.replace(" ", " ") 34*9473e04dSbugGenerator if ci[-1] == "\n": 35*9473e04dSbugGenerator ci = ci[:-1] 36*9473e04dSbugGenerator cs.append(ci) 37*9473e04dSbugGenerator return cs 38*9473e04dSbugGenerator 39*9473e04dSbugGeneratordef parse_yaml(yaml_file): 40*9473e04dSbugGenerator file_data = open(yaml_file, "r", encoding="utf-8").read() 41*9473e04dSbugGenerator yaml_data = yaml.load(file_data, Loader=yaml.CLoader) 42*9473e04dSbugGenerator return yaml_data 43*9473e04dSbugGenerator 44*9473e04dSbugGeneratordef show(test_info): 45*9473e04dSbugGenerator name = test_info["name"] 46*9473e04dSbugGenerator print(name) 47*9473e04dSbugGenerator 48*9473e04dSbugGeneratordef run_test(test_info, numa, run_mode): 49*9473e04dSbugGenerator name = test_info["name"] 50*9473e04dSbugGenerator coe_key = "continue-on-error" 51*9473e04dSbugGenerator to_key = "timeout-minutes" 52*9473e04dSbugGenerator s_key = "steps" 53*9473e04dSbugGenerator continue_on_error = True if (coe_key not in test_info.keys()) else (False if (test_info[coe_key] == "false") else True) 54*9473e04dSbugGenerator timeout_minutes = 9999 if (to_key not in test_info.keys()) else int(test_info[to_key]) 55*9473e04dSbugGenerator if s_key not in test_info.keys(): 56*9473e04dSbugGenerator print(name, " ", s_key, " not found in yaml, skip") 57*9473e04dSbugGenerator sys.exit() 58*9473e04dSbugGenerator steps_raw = test_info[s_key] 59*9473e04dSbugGenerator # print("Steps") 60*9473e04dSbugGenerator # print(steps) 61*9473e04dSbugGenerator steps = {} 62*9473e04dSbugGenerator for s in steps_raw: 63*9473e04dSbugGenerator if "name" in s.keys(): 64*9473e04dSbugGenerator steps[s["name"]] = s["run"] 65*9473e04dSbugGenerator # print(steps) 66*9473e04dSbugGenerator 67*9473e04dSbugGenerator replace_list = [ 68*9473e04dSbugGenerator ["--numa", "--numa" if numa else ""], 69*9473e04dSbugGenerator ["$GITHUB_WORKSPACE", f"{workspace}"], 70*9473e04dSbugGenerator ["$HEAD_SHA", f"{head_sha}"], 71*9473e04dSbugGenerator ["$PERF_HOME", f"{perf_home}"], 72*9473e04dSbugGenerator ["$WAVE_HOME", f"{wave_home}"], 73*9473e04dSbugGenerator ["$AM_HOME", f"{am_home}"] 74*9473e04dSbugGenerator ] 75*9473e04dSbugGenerator 76*9473e04dSbugGenerator steps.pop("set env") 77*9473e04dSbugGenerator 78*9473e04dSbugGenerator for s in steps.keys(): 79*9473e04dSbugGenerator for r in replace_list: 80*9473e04dSbugGenerator steps[s] = steps[s].replace(r[0], r[1]) 81*9473e04dSbugGenerator 82*9473e04dSbugGenerator cmd = [] 83*9473e04dSbugGenerator for s in steps.keys(): 84*9473e04dSbugGenerator cs = split_cmd(steps[s]) 85*9473e04dSbugGenerator cmd = cmd + cs 86*9473e04dSbugGenerator 87*9473e04dSbugGenerator if run_mode: 88*9473e04dSbugGenerator for c in cmd: 89*9473e04dSbugGenerator f_c = set_env + " " + c 90*9473e04dSbugGenerator print(f"[CMD] {f_c}", flush=True) 91*9473e04dSbugGenerator os.system(f_c) 92*9473e04dSbugGenerator else: 93*9473e04dSbugGenerator if (sh_path is None): 94*9473e04dSbugGenerator print("sh_path is None") 95*9473e04dSbugGenerator sys.exit() 96*9473e04dSbugGenerator elif (not os.path.exists(sh_path)): 97*9473e04dSbugGenerator os.mkdir(sh_path) 98*9473e04dSbugGenerator 99*9473e04dSbugGenerator 100*9473e04dSbugGenerator sh_file_name = os.path.join(sh_path, "_".join(name.strip().replace("-", "").split())+".sh") 101*9473e04dSbugGenerator with open(sh_file_name, "w") as tmp_sh: 102*9473e04dSbugGenerator tmp_sh.write(f"mkdir -p {wave_home}\n") 103*9473e04dSbugGenerator tmp_sh.write(f"mkdir -p {perf_home}\n") 104*9473e04dSbugGenerator for c in cmd: 105*9473e04dSbugGenerator print(c) 106*9473e04dSbugGenerator tmp_sh.write(c+"\n") 107*9473e04dSbugGenerator 108*9473e04dSbugGeneratorif __name__ == "__main__": 109*9473e04dSbugGenerator # Usage: 110*9473e04dSbugGenerator # 1. run ci test 111*9473e04dSbugGenerator # python3 scripts/local_ci.py --xs-path $(pwd) --run 112*9473e04dSbugGenerator # More Params: 113*9473e04dSbugGenerator # --pick-test MC: only run 'EMU - MC' 114*9473e04dSbugGenerator 115*9473e04dSbugGenerator # 2. print ci test name 116*9473e04dSbugGenerator # python3 scripts/local_ci.py --xs-path $(pwd) --show-test 117*9473e04dSbugGenerator # This can also use --pick-test 118*9473e04dSbugGenerator 119*9473e04dSbugGenerator # 3. print ci test command into splited sh files. Run the sh manualy. 120*9473e04dSbugGenerator # python3 scripts/local_ci.py --xs-path $(pwd) --sh-path /nfs/home/zhangzifei/work/xs-master/ci-sh 121*9473e04dSbugGenerator # just remove --run 122*9473e04dSbugGenerator 123*9473e04dSbugGenerator # Other Params: 124*9473e04dSbugGenerator # --numa: use numa ctrl, require eypc 125*9473e04dSbugGenerator # --head-sha: magic word, default is today's date 126*9473e04dSbugGenerator # --nemu-home/--am-home: don't know if it is used 127*9473e04dSbugGenerator 128*9473e04dSbugGenerator parser = argparse.ArgumentParser(description="run ci locally") 129*9473e04dSbugGenerator parser.add_argument("--xs-path", type=str, help="XiangShan, NOOP_HOME") 130*9473e04dSbugGenerator parser.add_argument("--nemu-home", type=str, help="NEMU_HOME") 131*9473e04dSbugGenerator parser.add_argument("--am-home", type=str, help="AM_HOME") 132*9473e04dSbugGenerator parser.add_argument("--sh-path", type=str, help="ci's sh file path") 133*9473e04dSbugGenerator parser.add_argument("--head-sha", type=str, help="magic word") 134*9473e04dSbugGenerator parser.add_argument("--run", action='store_true', help="run test, not gen sh") 135*9473e04dSbugGenerator parser.add_argument("--numa", action='store_true', help="epyc numactl") 136*9473e04dSbugGenerator parser.add_argument("--show-test", action="store_true", help="print test case") 137*9473e04dSbugGenerator parser.add_argument("--pick-test", type=str, help="pick only one test") 138*9473e04dSbugGenerator 139*9473e04dSbugGenerator args = parser.parse_args() 140*9473e04dSbugGenerator 141*9473e04dSbugGenerator print(args) 142*9473e04dSbugGenerator 143*9473e04dSbugGenerator workspace = os.getenv("NOOP_HOME") if (args.xs_path is None) else args.xs_path 144*9473e04dSbugGenerator head_sha = date.today().strftime(r"%Y%m%d") if (args.head_sha is None) else args.head_sha 145*9473e04dSbugGenerator wave_home = os.path.join(workspace, "wave", head_sha) 146*9473e04dSbugGenerator perf_home = os.path.join(workspace, "perf", head_sha) 147*9473e04dSbugGenerator github_yaml = os.path.join(workspace, ".github/workflows/emu.yml") 148*9473e04dSbugGenerator nemu_home = os.getenv("NEMU_HOME") if (args.nemu_home is None) else args.nemu_home 149*9473e04dSbugGenerator am_home = os.getenv("AM_HOME") if (args.am_home is None) else args.am_home 150*9473e04dSbugGenerator set_env = f"NEMU_HOME={nemu_home} NOOP_HOME={workspace} WAVE_HOME={wave_home} PERF_HOME={perf_home} AM_HOME={am_home}" 151*9473e04dSbugGenerator sh_path = f"{workspace}/ci-sh" if (args.sh_path is None) else args.sh_path 152*9473e04dSbugGenerator 153*9473e04dSbugGenerator print("workspace(NOOP_HOME): ", workspace) 154*9473e04dSbugGenerator print("head_sha: ", head_sha) 155*9473e04dSbugGenerator print("wave_home: ", wave_home) 156*9473e04dSbugGenerator print("perf_home: ", perf_home) 157*9473e04dSbugGenerator print("github_yaml: ", github_yaml) 158*9473e04dSbugGenerator print("nemu_home: ", nemu_home) 159*9473e04dSbugGenerator print("am_home: ", am_home) 160*9473e04dSbugGenerator print("set_env: ", set_env) 161*9473e04dSbugGenerator print("sh_path", sh_path) 162*9473e04dSbugGenerator 163*9473e04dSbugGenerator input("Press Enter to continue") 164*9473e04dSbugGenerator 165*9473e04dSbugGenerator ci_tests = parse_yaml(github_yaml)["jobs"] 166*9473e04dSbugGenerator 167*9473e04dSbugGenerator if (args.show_test): 168*9473e04dSbugGenerator for test in ci_tests.keys(): 169*9473e04dSbugGenerator show(ci_tests[test]) 170*9473e04dSbugGenerator else: 171*9473e04dSbugGenerator for test in ci_tests.keys(): 172*9473e04dSbugGenerator if args.pick_test is not None: 173*9473e04dSbugGenerator if (args.pick_test in ci_tests[test]["name"]): 174*9473e04dSbugGenerator run_test(ci_tests[test], args.numa, args.run) 175*9473e04dSbugGenerator else: 176*9473e04dSbugGenerator run_test(ci_tests[test], args.numa, args.run)