sdadfadas

Форк
0
/
change_detector.py 
162 строки · 5.4 Кб
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 json
20
import os
21
import re
22
import subprocess
23
from typing import List
24
from urllib.request import Request, urlopen
25

26
# Define patterns for each group of files you're interested in
27
PATTERNS = {
28
    "python": [
29
        r"^\.github/workflows/.*python",
30
        r"^tests/",
31
        r"^superset/",
32
        r"^scripts/",
33
        r"^setup\.py",
34
        r"^requirements/.+\.txt",
35
        r"^.pylintrc",
36
    ],
37
    "frontend": [
38
        r"^\.github/workflows/.*(bashlib|frontend|e2e)",
39
        r"^superset-frontend/",
40
    ],
41
    "docker": [
42
        r"^Dockerfile$",
43
        r"^docker/",
44
    ],
45
    "docs": [
46
        r"^docs/",
47
    ],
48
}
49
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN")
50

51

52
def fetch_files_github_api(url: str):  # type: ignore
53
    """Fetches data using GitHub API."""
54
    req = Request(url)
55
    req.add_header("Authorization", f"token {GITHUB_TOKEN}")
56
    req.add_header("Accept", "application/vnd.github.v3+json")
57

58
    print(f"Fetching from {url}")
59
    with urlopen(req) as response:
60
        body = response.read()
61
        return json.loads(body)
62

63

64
def fetch_changed_files_pr(repo: str, pr_number: str) -> List[str]:
65
    """Fetches files changed in a PR using the GitHub API."""
66
    url = f"https://api.github.com/repos/{repo}/pulls/{pr_number}/files"
67
    files = fetch_files_github_api(url)
68
    return [file_info["filename"] for file_info in files]
69

70

71
def fetch_changed_files_push(repo: str, sha: str) -> List[str]:
72
    """Fetches files changed in the last commit for push events using GitHub API."""
73
    # Fetch commit details to get the parent SHA
74
    commit_url = f"https://api.github.com/repos/{repo}/commits/{sha}"
75
    commit_data = fetch_files_github_api(commit_url)
76
    if "parents" not in commit_data or len(commit_data["parents"]) < 1:
77
        raise RuntimeError("No parent commit found for comparison.")
78
    parent_sha = commit_data["parents"][0]["sha"]
79
    # Compare the current commit against its parent
80
    compare_url = f"https://api.github.com/repos/{repo}/compare/{parent_sha}...{sha}"
81
    comparison_data = fetch_files_github_api(compare_url)
82
    return [file["filename"] for file in comparison_data["files"]]
83

84

85
def detect_changes(files: List[str], check_patterns: List) -> bool:  # type: ignore
86
    """Detects if any of the specified files match the provided patterns."""
87
    for file in files:
88
        for pattern in check_patterns:
89
            if re.match(pattern, file):
90
                return True
91
    return False
92

93

94
def print_files(files: List[str]) -> None:
95
    print("\n".join([f"- {s}" for s in files]))
96

97

98
def main(event_type: str, sha: str, repo: str) -> None:
99
    """Main function to check for file changes based on event context."""
100
    print("SHA:", sha)
101
    print("EVENT_TYPE", event_type)
102
    if event_type == "pull_request":
103
        pr_number = os.getenv("GITHUB_REF", "").split("/")[-2]
104
        files = fetch_changed_files_pr(repo, pr_number)
105
        print("PR files:")
106
        print_files(files)
107

108
    elif event_type == "push":
109
        files = fetch_changed_files_push(repo, sha)
110
        print("Files touched since previous commit:")
111
        print_files(files)
112

113
    elif event_type == "workflow_dispatch":
114
        print("Workflow dispatched, assuming all changed")
115

116
    else:
117
        raise ValueError("Unsupported event type")
118

119
    changes_detected = {}
120
    for group, regex_patterns in PATTERNS.items():
121
        patterns_compiled = [re.compile(p) for p in regex_patterns]
122
        changes_detected[group] = event_type == "workflow_dispatch" or detect_changes(
123
            files, patterns_compiled
124
        )
125

126
    # Output results
127
    output_path = os.getenv("GITHUB_OUTPUT") or "/tmp/GITHUB_OUTPUT.txt"
128
    with open(output_path, "a") as f:
129
        for check, changed in changes_detected.items():
130
            if changed:
131
                print(f"{check}={str(changed).lower()}", file=f)
132
                print(f"Triggering group: {check}")
133

134

135
def get_git_sha() -> str:
136
    return os.getenv("GITHUB_SHA") or subprocess.check_output(
137
        ["git", "rev-parse", "HEAD"]
138
    ).strip().decode("utf-8")
139

140

141
if __name__ == "__main__":
142
    parser = argparse.ArgumentParser(
143
        description="Detect file changes based on event context"
144
    )
145
    parser.add_argument(
146
        "--event-type",
147
        default=os.getenv("GITHUB_EVENT_NAME") or "push",
148
        help="The type of event that triggered the workflow",
149
    )
150
    parser.add_argument(
151
        "--sha",
152
        default=get_git_sha(),
153
        help="The commit SHA for push events or PR head SHA",
154
    )
155
    parser.add_argument(
156
        "--repo",
157
        default=os.getenv("GITHUB_REPOSITORY") or "apache/superset",
158
        help="GitHub repository in the format owner/repo",
159
    )
160
    args = parser.parse_args()
161

162
    main(args.event_type, args.sha, args.repo)
163

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

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

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

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