22
from datetime import datetime
24
XVFB_PRE_CMD = "xvfb-run --auto-servernum --server-args='-screen 0, 1024x768x24' "
25
REPO = os.getenv("GITHUB_REPOSITORY") or "apache/superset"
26
GITHUB_EVENT_NAME = os.getenv("GITHUB_REPOSITORY") or "push"
27
CYPRESS_RECORD_KEY = os.getenv("CYPRESS_RECORD_KEY") or ""
30
def compute_hash(file_path: str) -> str:
31
return hashlib.md5(file_path.encode()).hexdigest()
34
def compute_group_index(hash_value: str, num_groups: int) -> int:
35
return int(hash_value, 16) % num_groups
38
def generate_build_id() -> str:
40
rounded_minute = now.minute - (now.minute % 20)
41
rounded_time = now.replace(minute=rounded_minute, second=0, microsecond=0)
42
return (os.getenv("GITHUB_SHA") or "DUMMY")[:8] + rounded_time.strftime(
48
spec_list: list[str], _filter: str, group: str, use_dashboard: bool
50
cypress_cmd = "./node_modules/.bin/cypress run"
52
os.environ["TERM"] = "xterm"
53
os.environ["ELECTRON_DISABLE_GPU"] = "true"
54
build_id = generate_build_id()
55
browser = os.getenv("CYPRESS_BROWSER", "chrome")
59
spec: str = "cypress/e2e/*/**/*"
62
f'{cypress_cmd} --spec "{spec}" --browser {browser} '
63
f"--record --group {group} --tag {REPO},{GITHUB_EVENT_NAME} "
64
f"--parallel --ci-build-id {build_id}"
68
os.environ.pop("CYPRESS_RECORD_KEY", None)
69
spec_list_str = ",".join(sorted(spec_list))
71
spec_list_str = ",".join(sorted([s for s in spec_list if _filter in s]))
74
f"{cypress_cmd} --browser {browser} "
75
f'--spec "{spec_list_str}" '
81
parser = argparse.ArgumentParser(
82
description="Generate Cypress commands based on test file hash"
87
help="Use Cypress Dashboard for parallelization",
90
"--parallelism", type=int, default=10, help="Number of parallel groups"
93
"--parallelism-id", type=int, required=True, help="ID of the parallelism group"
96
"--filter", type=str, required=False, default=None, help="filter to test"
98
parser.add_argument("--group", type=str, default="Default", help="Group name")
102
help="Print the command instead of executing it",
104
args = parser.parse_args()
106
script_dir = os.path.dirname(os.path.abspath(__file__))
107
cypress_base_path = "superset-frontend/cypress-base/"
108
cypress_base_full_path = os.path.join(script_dir, "../", cypress_base_path)
109
cypress_tests_path = os.path.join(cypress_base_full_path, "cypress/e2e")
112
for root, _, files in os.walk(cypress_tests_path):
114
if file.endswith("test.ts") or file.endswith("test.js"):
116
os.path.join(root, file).replace(cypress_base_full_path, "")
120
groups: dict[int, list[str]] = {i: [] for i in range(args.parallelism)}
123
sorted_test_files = sorted(test_files)
126
for index, test_file in enumerate(sorted_test_files):
127
group_index = index % args.parallelism
128
groups[group_index].append(test_file)
130
group_id = args.parallelism_id
131
spec_list = groups[group_id]
132
cmd = get_cypress_cmd(spec_list, args.filter, args.group, args.use_dashboard)
135
subprocess.run(cmd, shell=True, check=True, stdout=None, stderr=None)
138
if __name__ == "__main__":