sdadfadas

Форк
0
/
cypress_run.py 
139 строк · 4.8 Кб
1
# Licensed to the Apache Software Foundation (ASF) under one
2
# or more contributor license agreements.  See the NOTICE file
3
# distributed with this work for additional information
4
# regarding copyright ownership.  The ASF licenses this file
5
# to you under the Apache License, Version 2.0 (the
6
# "License"); you may not use this file except in compliance
7
# with the License.  You may obtain a copy of the License at
8
#
9
#   http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing,
12
# software distributed under the License is distributed on an
13
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
# KIND, either express or implied.  See the License for the
15
# specific language governing permissions and limitations
16
# under the License.
17

18
import argparse
19
import hashlib
20
import os
21
import subprocess
22
from datetime import datetime
23

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 ""
28

29

30
def compute_hash(file_path: str) -> str:
31
    return hashlib.md5(file_path.encode()).hexdigest()
32

33

34
def compute_group_index(hash_value: str, num_groups: int) -> int:
35
    return int(hash_value, 16) % num_groups
36

37

38
def generate_build_id() -> str:
39
    now = datetime.now()
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(
43
        "%Y%m%d%H%M"
44
    )
45

46

47
def get_cypress_cmd(
48
    spec_list: list[str], _filter: str, group: str, use_dashboard: bool
49
) -> str:
50
    cypress_cmd = "./node_modules/.bin/cypress run"
51

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")
56

57
    if use_dashboard:
58
        # Run using cypress.io service
59
        spec: str = "cypress/e2e/*/**/*"
60
        cmd = (
61
            f"{XVFB_PRE_CMD} "
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}"
65
        )
66
    else:
67
        # Run local, but split the execution
68
        os.environ.pop("CYPRESS_RECORD_KEY", None)
69
        spec_list_str = ",".join(sorted(spec_list))
70
        if _filter:
71
            spec_list_str = ",".join(sorted([s for s in spec_list if _filter in s]))
72
        cmd = (
73
            f"{XVFB_PRE_CMD} "
74
            f"{cypress_cmd} --browser {browser} "
75
            f'--spec "{spec_list_str}" '
76
        )
77
    return cmd
78

79

80
def main() -> None:
81
    parser = argparse.ArgumentParser(
82
        description="Generate Cypress commands based on test file hash"
83
    )
84
    parser.add_argument(
85
        "--use-dashboard",
86
        action="store_true",
87
        help="Use Cypress Dashboard for parallelization",
88
    )
89
    parser.add_argument(
90
        "--parallelism", type=int, default=10, help="Number of parallel groups"
91
    )
92
    parser.add_argument(
93
        "--parallelism-id", type=int, required=True, help="ID of the parallelism group"
94
    )
95
    parser.add_argument(
96
        "--filter", type=str, required=False, default=None, help="filter to test"
97
    )
98
    parser.add_argument("--group", type=str, default="Default", help="Group name")
99
    parser.add_argument(
100
        "--dry-run",
101
        action="store_true",
102
        help="Print the command instead of executing it",
103
    )
104
    args = parser.parse_args()
105

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")
110

111
    test_files = []
112
    for root, _, files in os.walk(cypress_tests_path):
113
        for file in files:
114
            if file.endswith("test.ts") or file.endswith("test.js"):
115
                test_files.append(
116
                    os.path.join(root, file).replace(cypress_base_full_path, "")
117
                )
118

119
    # Initialize groups
120
    groups: dict[int, list[str]] = {i: [] for i in range(args.parallelism)}
121

122
    # Sort test files to ensure deterministic distribution
123
    sorted_test_files = sorted(test_files)
124

125
    # Distribute test files in a round-robin manner
126
    for index, test_file in enumerate(sorted_test_files):
127
        group_index = index % args.parallelism
128
        groups[group_index].append(test_file)
129

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)
133
    print(f"RUN: {cmd}")
134
    if not args.dry_run:
135
        subprocess.run(cmd, shell=True, check=True, stdout=None, stderr=None)
136

137

138
if __name__ == "__main__":
139
    main()
140

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.