Skip to content

Commit deb91ce

Browse files
Merge Upstream Workflow Logging (#1712)
## Что этот PR делает Делает логи подробнее для отладки.
1 parent d1a884e commit deb91ce

File tree

2 files changed

+98
-53
lines changed

2 files changed

+98
-53
lines changed

.github/workflows/merge_upstream.yml

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ jobs:
4343
CHANGELOG_AUTHOR: 'ParadiseSS13'
4444
TRANSLATE_CHANGES: 'true'
4545
OPENAI_API_KEY: ${{ secrets.ORG_EMPTY_TOKEN }}
46+
LOG_LEVEL: ${{ runner.debug && 'DEBUG' || 'INFO' }}
4647
run: |
4748
git config --global user.email "[email protected]"
4849
git config --global user.name "Upstream Sync"

tools/merge-upstream/merge_upstream.py

+97-53
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import enum
2+
import logging
23
import os
34
import re
45
import subprocess
@@ -55,6 +56,7 @@ class PullDetails(typing.TypedDict):
5556

5657
def check_env():
5758
"""Check if the required environment variables are set."""
59+
logging.debug("Checking environment variables...")
5860
required_vars = [
5961
"GITHUB_TOKEN",
6062
"TARGET_REPO",
@@ -67,9 +69,12 @@ def check_env():
6769
required_vars.append("OPENAI_API_KEY")
6870
missing_vars = [var for var in required_vars if not os.getenv(var)]
6971
if missing_vars:
72+
logging.error("Missing required environment variables: %s", ", ".join(missing_vars))
7073
raise EnvironmentError(f"Missing required environment variables: {', '.join(missing_vars)}")
7174

7275

76+
logging.basicConfig(level=os.getenv("LOG_LEVEL", "INFO").upper())
77+
7378
# Environment variables
7479
TRANSLATE_CHANGES = os.getenv("TRANSLATE_CHANGES", "False").lower() in ("true", "yes", "1")
7580
CHANGELOG_AUTHOR = os.getenv("CHANGELOG_AUTHOR", "")
@@ -86,73 +91,82 @@ def check_env():
8691

8792
def run_command(command: str) -> str:
8893
"""Run a shell command and return its output."""
94+
logging.debug("Running command: %s", command)
8995
try:
9096
result: CompletedProcess[str] = subprocess.run(command, shell=True, capture_output=True, text=True)
9197
result.check_returncode()
98+
logging.debug("Command output: %s", result.stdout.strip())
9299
return result.stdout.strip()
93100
except subprocess.CalledProcessError as e:
94-
print(f"Error executing command: {command}\nExit code: {e.returncode}\nOutput: {e.output}\nError: {e.stderr}")
101+
logging.error("Error executing command: %s", command)
102+
logging.error("Exit code: %d, Output: %s, Error: %s", e.returncode, e.output, e.stderr)
95103
raise
96104

97105

98106
def setup_repo():
99107
"""Clone the repository and set up the upstream remote."""
100-
print(f"Cloning repository: {TARGET_REPO}")
108+
logging.info("Cloning repository: %s", TARGET_REPO)
101109
run_command(f"git clone https://x-access-token:{GITHUB_TOKEN}@github.com/{TARGET_REPO}.git repo")
102110
os.chdir("repo")
103111
run_command(f"git remote add upstream https://x-access-token:{GITHUB_TOKEN}@github.com/{UPSTREAM_REPO}.git")
104-
print(run_command(f"git remote -v"))
112+
logging.info("Git remotes set up: %s", run_command(f"git remote -v"))
105113

106114

107115
def update_merge_branch():
108116
"""Update the merge branch with the latest changes from upstream."""
109-
print(f"Fetching branch {UPSTREAM_BRANCH} from upstream...")
117+
logging.info("Fetching branch %s from upstream...", UPSTREAM_BRANCH)
110118
run_command(f"git fetch upstream {UPSTREAM_BRANCH}")
111119
run_command(f"git fetch origin")
112120
all_branches: list[str] = run_command("git branch -a").split()
121+
logging.debug("Fetched branches: %s", all_branches)
113122

114123
if f"remotes/origin/{MERGE_BRANCH}" not in all_branches:
115-
print(f"Branch '{MERGE_BRANCH}' does not exist. Creating it from upstream/{UPSTREAM_BRANCH}...")
124+
logging.info("Branch '%s' does not exist. Creating it from upstream/%s...", MERGE_BRANCH, UPSTREAM_BRANCH)
116125
run_command(f"git checkout -b {MERGE_BRANCH} upstream/{UPSTREAM_BRANCH}")
117126
run_command(f"git push -u origin {MERGE_BRANCH}")
118127
return
119128

120-
print(f"Resetting {MERGE_BRANCH} onto upstream/{UPSTREAM_BRANCH}...")
129+
logging.info("Resetting '%s' onto upstream/%s...", MERGE_BRANCH, UPSTREAM_BRANCH)
121130
run_command(f"git checkout {MERGE_BRANCH}")
122131
run_command(f"git reset --hard upstream/{UPSTREAM_BRANCH}")
123-
124-
print("Pushing changes to origin...")
132+
logging.info("Pushing changes to origin...")
125133
run_command(f"git push origin {MERGE_BRANCH} --force")
126134

127135

128136
def detect_commits() -> list[str]:
129137
"""Detect commits from upstream not yet in downstream."""
130-
print("Detecting new commits from upstream...")
138+
logging.info("Detecting new commits from upstream...")
131139
commit_log: list[str] = run_command(f"git log {TARGET_BRANCH}..{MERGE_BRANCH} --pretty=format:'%h %s'").split("\n")
132140
commit_log.reverse()
141+
logging.debug("Detected commits: %s", commit_log)
133142
return commit_log
134143

135144

136145
def fetch_pull(github: Github, pull_number: int) -> PullRequest | None:
137146
"""Fetch the pull request from GitHub."""
147+
logging.debug("Fetching pull request #%d", pull_number)
138148
upstream_repo: Repository = github.get_repo(UPSTREAM_REPO)
139149

140150
max_retries = 3
141151
for attempt in range(max_retries):
142152
try:
143-
return upstream_repo.get_pull(int(pull_number))
153+
pull = upstream_repo.get_pull(int(pull_number))
154+
logging.debug("Successfully fetched PR #%d: %s", pull_number, pull.title)
155+
return pull
144156
except Exception as e:
145-
print(f"Error fetching PR #{pull_number}: {e}")
157+
logging.error("Error fetching PR #%d: %s", pull_number, e)
146158
if attempt + 1 < max_retries:
159+
logging.warning("Retrying fetch for PR #%d (attempt %d/%d)", pull_number, attempt + 1, max_retries)
147160
time.sleep(2)
148161
else:
162+
logging.error("Failed to fetch PR #%d after %d attempts", pull_number, max_retries)
149163
return None
150164

151165

152166
def build_details(github: Github, commit_log: list[str],
153167
translate: typing.Optional[typing.Callable[[typing.Dict[int, list[Change]]], None]]) -> PullDetails:
154168
"""Generate data from parsed commits."""
155-
print("Building details...")
169+
logging.info("Building pull request details from commit log...")
156170
pull_number_pattern: Pattern[str] = re.compile("#(?P<id>\\d+)")
157171
details = PullDetails(
158172
changelog={},
@@ -168,55 +182,63 @@ def build_details(github: Github, commit_log: list[str],
168182
for commit in commit_log:
169183
match = re.search(pull_number_pattern, commit)
170184
if not match:
171-
print(f"Skipping {commit}")
185+
logging.debug("Skipping commit without pull request reference: %s", commit)
172186
continue
173187

174188
pull_number = int(match.group("id"))
175189

176190
if pull_number in pull_cache:
177-
print(
178-
f"WARNING: pull duplicate found.\n"
179-
f"1: {pull_cache[pull_number]}\n"
180-
f"2: {commit}"
191+
logging.warning(
192+
"Duplicate pull request detected for #%d\n"
193+
"Existing: %s\n"
194+
"New: %s",
195+
pull_number, pull_cache[pull_number], commit
181196
)
182-
print(f"Skipping {commit}")
183197
continue
184198

185199
pull_cache[pull_number] = commit
186200
futures[executor.submit(fetch_pull, github, pull_number)] = pull_number
187201

188202
for future in as_completed(futures):
189203
pull_number = futures[future]
190-
pull: PullRequest | None = future.result()
191-
192-
if not pull:
193-
print(f"Pull {pull_number} was not fetched. Skipping.")
194-
continue
195-
196-
process_pull(details, pull)
204+
try:
205+
pull: PullRequest | None = future.result()
206+
if not pull:
207+
logging.warning("Failed to fetch pull request #%d. Skipping.", pull_number)
208+
continue
209+
process_pull(details, pull)
210+
except Exception as e:
211+
logging.error("Error processing pull request #%d: %s", pull_number, e)
197212

198213
if translate:
199214
translate(details["changelog"])
200215

216+
logging.info("Details building complete. Processed %d pull requests.", len(details["merge_order"]))
201217
return details
202218

203219

204220
def process_pull(details: PullDetails, pull: PullRequest):
205221
"""Handle fetched pull request data during details building."""
222+
logging.debug("Processing pull request #%d: %s", pull.number, pull.title)
206223
pull_number: int = pull.number
207224
labels: list[str] = [label.name for label in pull.get_labels()]
208225
pull_changes: list[Change] = []
226+
209227
try:
210228
for label in labels:
211229
if label == UpstreamLabel.CONFIG_CHANGE.value:
212230
details["config_changes"].append(pull)
231+
logging.debug("Detected CONFIG_CHANGE label for PR #%d", pull_number)
213232
elif label == UpstreamLabel.SQL_CHANGE.value:
214233
details["sql_changes"].append(pull)
234+
logging.debug("Detected SQL_CHANGE label for PR #%d", pull_number)
215235
elif label == UpstreamLabel.WIKI_CHANGE.value:
216236
details["wiki_changes"].append(pull)
237+
logging.debug("Detected WIKI_CHANGE label for PR #%d", pull_number)
217238

218239
parsed = changelog_utils.parse_changelog(pull.body)
219240
if parsed and parsed["changes"]:
241+
logging.debug("Parsed changelog for PR #%d: %s", pull_number, parsed["changes"])
220242
for change in parsed["changes"]:
221243
pull_changes.append(Change(
222244
tag=change["tag"],
@@ -226,28 +248,34 @@ def process_pull(details: PullDetails, pull: PullRequest):
226248

227249
if pull_changes:
228250
details["changelog"][pull_number] = pull_changes
251+
logging.debug("Added %d changes for PR #%d", len(pull_changes), pull_number)
229252
except Exception as e:
230-
print(
231-
f"An error occurred while processing {pull.html_url}\n"
232-
f"Body: {pull.body}"
253+
logging.error(
254+
"An error occurred while processing PR #%d: %s\n"
255+
"Body: %s",
256+
pull.number, e, pull.body
233257
)
234-
raise e
258+
raise
235259

236260

237261
def translate_changelog(changelog: typing.Dict[int, list[Change]]):
238262
"""Translate changelog using OpenAI API."""
239-
print("Translating changelog...")
263+
logging.info("Translating changelog...")
240264
if not changelog:
265+
logging.warning("No changelog entries to translate.")
241266
return
242267

243268
changes: list[Change] = [change for changes in changelog.values() for change in changes]
244269
if not changes:
270+
logging.warning("No changes found in the changelog to translate.")
245271
return
246272

273+
logging.debug("Preparing text for translation: %d changes", len(changes))
274+
text = "\n".join([change["message"] for change in changes])
275+
logging.debug(text)
247276
script_dir = Path(__file__).resolve().parent
248277
with open(script_dir.joinpath("translation_context.txt"), encoding="utf-8") as f:
249278
context = "\n".join(f.readlines()).strip()
250-
text = "\n".join([change["message"] for change in changes])
251279

252280
client = OpenAI(
253281
base_url="https://models.inference.ai.azure.com",
@@ -265,12 +293,13 @@ def translate_changelog(changelog: typing.Dict[int, list[Change]]):
265293
translated_text: str | None = response.choices[0].message.content
266294

267295
if not translated_text:
268-
print("WARNING: changelog translation failed!")
269-
print(response)
296+
logging.warning("Changelog translation failed!")
297+
logging.debug("Translation API response: %s", response)
270298
return
271299

272300
for change, translated_message in zip(changes, translated_text.split("\n"), strict=True):
273301
change["translated_message"] = translated_message
302+
logging.debug("Translated: %s -> %s", change["message"], translated_message)
274303

275304

276305
def silence_pull_url(pull_url: str) -> str:
@@ -280,35 +309,44 @@ def silence_pull_url(pull_url: str) -> str:
280309

281310
def prepare_pull_body(details: PullDetails) -> str:
282311
"""Build new pull request body from the generated changelog."""
312+
logging.info("Preparing pull request body...")
283313
pull_body: str = (
284314
f"This pull request merges upstream/{UPSTREAM_BRANCH}. "
285315
f"Resolve possible conflicts manually and make sure all the changes are applied correctly.\n"
286316
)
287317

288318
if not details:
319+
logging.warning("No pull details provided. Using default body.")
289320
return pull_body
290321

291322
label_to_pulls: dict[UpstreamLabel, list[PullRequest]] = {
292323
UpstreamLabel.CONFIG_CHANGE: details["config_changes"],
293324
UpstreamLabel.SQL_CHANGE: details["sql_changes"],
294325
UpstreamLabel.WIKI_CHANGE: details["wiki_changes"]
295326
}
327+
296328
for label, fetched_pulls in label_to_pulls.items():
297329
if not fetched_pulls:
330+
logging.debug("No pulls found for label '%s'", label.value)
298331
continue
299332

300333
pull_body += (
301334
f"\n> [!{LABEL_BLOCK_STYLE[label]}]\n"
302335
f"> {label.value}:\n"
303336
)
304337
for fetched_pull in fetched_pulls:
305-
pull_body += f"> {silence_pull_url(fetched_pull.html_url)}\n"
338+
silenced_url = silence_pull_url(fetched_pull.html_url)
339+
logging.debug("Adding pull #%d to body: %s", fetched_pull.number, silenced_url)
340+
pull_body += f"> {silenced_url}\n"
306341

307342
if not details["changelog"]:
343+
logging.info("No changelog entries found.")
308344
return pull_body
309345

346+
logging.info("Adding changelog entries to pull request body.")
310347
pull_body += f"\n## Changelog\n"
311348
pull_body += f":cl: {CHANGELOG_AUTHOR}\n" if CHANGELOG_AUTHOR else ":cl:\n"
349+
312350
for pull_number in details["merge_order"]:
313351
if pull_number not in details["changelog"]:
314352
continue
@@ -319,44 +357,50 @@ def prepare_pull_body(details: PullDetails) -> str:
319357
pull_url: str = silence_pull_url(change["pull"].html_url)
320358
if translated_message:
321359
pull_body += f"{tag}: {translated_message} <!-- {message} ({pull_url}) -->\n"
360+
logging.debug("Added translated change for PR #%d: %s", pull_number, translated_message)
322361
else:
323362
pull_body += f"{tag}: {message} <!-- ({pull_url}) -->\n"
363+
logging.debug("Added original change for PR #%d: %s", pull_number, message)
324364
pull_body += "/:cl:\n"
325365

366+
logging.info("Pull request body prepared successfully.")
326367
return pull_body
327368

328369

329370
def create_pr(repo: Repository, details: PullDetails):
330371
"""Create a pull request with the processed changelog."""
372+
logging.info("Creating pull request...")
331373
pull_body: str = prepare_pull_body(details)
332-
print("Creating pull request...")
333-
334-
# Create the pull request
335-
pull: PullRequest = repo.create_pull(
336-
title=f"Merge Upstream {datetime.today().strftime('%d.%m.%Y')}",
337-
body=pull_body,
338-
head=MERGE_BRANCH,
339-
base=TARGET_BRANCH
340-
)
341374

342-
if details["wiki_changes"]:
343-
pull.add_to_labels(DownstreamLabel.WIKI_CHANGE)
375+
try:
376+
# Create the pull request
377+
pull: PullRequest = repo.create_pull(
378+
title=f"Merge Upstream {datetime.today().strftime('%d.%m.%Y')}",
379+
body=pull_body,
380+
head=MERGE_BRANCH,
381+
base=TARGET_BRANCH
382+
)
383+
logging.info("Pull request created: %s", pull.html_url)
344384

345-
print("Pull request created successfully.")
385+
if details["wiki_changes"]:
386+
pull.add_to_labels(DownstreamLabel.WIKI_CHANGE)
387+
logging.debug("Added WIKI_CHANGE label to pull request.")
388+
except Exception as e:
389+
logging.error("Failed to create pull request: %s", e)
390+
raise
346391

347392

348393
def check_pull_exists(target_repo: Repository, base: str, head: str):
349-
"""Check if the merge pull request already exist. In this case, fail the action."""
350-
print("Checking on existing pull request...")
394+
"""Check if the merge pull request already exists."""
395+
logging.info("Checking if pull request already exists between '%s' and '%s'...", base, head)
351396
owner: str = target_repo.owner.login
352397
base_strict = f"{owner}:{base}"
353398
head_strict = f"{owner}:{head}"
354399
existing_pulls: PaginatedList[PullRequest] = target_repo.get_pulls(state="open", base=base_strict, head=head_strict)
355-
for pull in existing_pulls:
356-
print(f"Pull request already exists. {pull.html_url}")
357-
358-
if existing_pulls.totalCount:
400+
if existing_pulls.totalCount > 0:
401+
logging.error("Pull request already exists: %s", ", ".join(pull.html_url for pull in existing_pulls))
359402
exit(1)
403+
logging.debug("No existing pull requests found.")
360404

361405
if __name__ == "__main__":
362406
github = Github(GITHUB_TOKEN)
@@ -372,4 +416,4 @@ def check_pull_exists(target_repo: Repository, base: str, head: str):
372416
details: PullDetails = build_details(github, commit_log, translate_changelog if TRANSLATE_CHANGES else None)
373417
create_pr(target_repo, details)
374418
else:
375-
print(f"No changes detected from {UPSTREAM_REPO}/{UPSTREAM_BRANCH}. Skipping pull request creation.")
419+
logging.info("No changes detected from %s/%s. Skipping pull request creation.", UPSTREAM_REPO, UPSTREAM_BRANCH)

0 commit comments

Comments
 (0)