forked from pingcap/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreate_empty_translation_pr.py
More file actions
266 lines (219 loc) · 11.2 KB
/
Copy pathcreate_empty_translation_pr.py
File metadata and controls
266 lines (219 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# This script can create an empty PR in your target repo based on your specified source language PR.
# Before running this script:
# 1. Get a GitHub personal access token (https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) and save it in a text file.
# 2. Ensure that you have forked your target repo because the changes in the new PR will be committed to your forked repository first.
import requests
import base64
import re
source_pr_url = "https://github.com/pingcap/docs-cn/pull/13895" # update this URL to your PR link
my_github_id = "qiancai" # update this ID to your GitHub ID
my_github_token_file_path = r"/Users/grcai/Documents/PingCAP/Python_scripts/GitHub/gh_token5.txt"
# Read the GitHub personal access token from your local file.
with open(my_github_token_file_path, "r") as f:
access_token = f.read().strip()
# For getting the information about the source language PR
def get_pr_info(pr_url):
url_parts = pr_url.split("/")
source_repo_owner = url_parts[3]
source_repo_name = url_parts[4]
pr_number = url_parts[6]
url = f"https://api.github.com/repos/{source_repo_owner}/{source_repo_name}/pulls/{pr_number}"
headers = {"Accept": "application/vnd.github.v3+json"}
response = requests.get(url, headers=headers)
try:
response.raise_for_status()
pr_data = response.json()
source_title = pr_data["title"]
source_description = pr_data["body"]
exclude_labels = ["size", "translation", "status", "first-time-contributor", "contribution"]
source_labels = [label["name"] for label in pr_data.get("labels", []) if not any(exclude_label in label["name"] for exclude_label in exclude_labels)]
base_repo = pr_data["base"]["repo"]["full_name"]
base_branch = pr_data["base"]["ref"]
head_repo = pr_data["head"]["repo"]["full_name"]
head_branch = pr_data["head"]["ref"]
print(f"Getting source language PR information was successful. The head branch name is: {head_branch}")
return source_title, source_description, source_labels, base_repo, base_branch, head_repo, head_branch, pr_number
except requests.exceptions.HTTPError as e:
print(f"Failed to get source language PR information: {response.text}")
raise e
# For syncing the corresponding branch of my forked repository to the latest upstream
def sync_my_repo_branch(target_repo_owner, target_repo_name,my_repo_owner, my_repo_name, base_branch):
# Get the branch reference SHA of the upstream repository.
api_url = f"https://api.github.com/repos/{target_repo_owner}/{target_repo_name}/git/refs/heads/{base_branch}"
headers = {"Authorization": f"Bearer {access_token}"}
response = requests.get(api_url, headers=headers)
if response.status_code == 200:
upstream_sha = response.json().get("object", {}).get("sha")
else:
print("Failed to get the upstream repository branch reference.")
exit()
# Update the branch reference of your fork repository
api_url = f"https://api.github.com/repos/{my_repo_owner}/{my_repo_name}/git/refs/heads/{base_branch}"
data = {
"sha": upstream_sha,
"force": True
}
print("Syncing the latest content from the upstream branch...")
response = requests.patch(api_url, headers=headers, json=data)
if response.status_code == 200:
print("The content sync is successful!")
else:
print("Failed to sync the latest content from the upstream branch.")
# For creating a new branch in my forked repository
def create_branch(repo_owner, repo_name, branch_name, base_branch, access_token):
api_url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/git/refs"
headers = {"Authorization": f"Bearer {access_token}"}
# Get a reference to the base branch
base_branch_url = f"heads/{base_branch}"
response = requests.get(f"{api_url}/{base_branch_url}", headers=headers)
if response.status_code == 200:
base_branch_ref = response.json().get("object", {}).get("sha")
if base_branch_ref:
# Create a reference to a new branch
branch_ref = f"refs/heads/{branch_name}"
data = {
"ref": branch_ref,
"sha": base_branch_ref
}
response = requests.post(api_url, headers=headers, json=data)
if response.status_code == 201:
branch_url = f"https://github.com/{repo_owner}/{repo_name}/tree/{branch_name}"
print(f"A new branch is created successfully. The branch address is: {branch_url}")
return branch_url
else:
print(f"Failed to create the branch: {response.text}")
raise requests.exceptions.HTTPError(response.text)
else:
print("Base branch reference not found.")
raise ValueError("Base branch reference not found.")
else:
print(f"Failed to get base branch reference: {response.text}")
raise requests.exceptions.HTTPError(response.text)
# For adding a temporary temp.md file to the new branch
def create_file_in_branch(repo_owner, repo_name, branch_name, access_token, file_path, file_content, commit_message):
url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/contents/{file_path}"
headers = {
"Authorization": f"Bearer {access_token}",
"Accept": "application/vnd.github.v3+json"
}
data = {
"message": commit_message,
"branch": branch_name,
"content": base64.b64encode(file_content.encode()).decode()
}
response = requests.put(url, headers=headers, json=data)
response.raise_for_status()
print("A temp file is created successfully!")
# For creating a PR in the target repository and adding labels to the target PR
def create_pull_request(target_repo_owner, target_repo_name, base_branch, my_repo_owner, my_repo_name, new_branch_name, access_token, title, body, labels):
url = f"https://api.github.com/repos/{target_repo_owner}/{target_repo_name}/pulls"
headers = {
"Accept": "application/vnd.github.v3+json",
"Authorization": f"Bearer {access_token}"
}
data = {
"title": title,
"body": body,
"head": f"{my_repo_owner}:{new_branch_name}",
"base": base_branch
}
response = requests.post(url, headers=headers, json=data)
try:
response.raise_for_status()
pr_data = response.json()
pr_url = pr_data["html_url"]
print(f"Your target PR is created successfully. The PR address is: {pr_url}")
url_parts = pr_url.split("/")
pr_number = url_parts[6]
# Add labels to the created PR
label_url = f"https://api.github.com/repos/{target_repo_owner}/{target_repo_name}/issues/{pr_number}/labels"
payload = labels # which is an array containing the labels to be added
response_labels = requests.post(label_url, headers=headers, json=payload)
if response_labels.status_code == 200:
print("Labels are added successfully.")
else:
print("Failed to add labels.")
return pr_url
except requests.exceptions.HTTPError as e:
print(f"Fails to create the target PR: {response.text}")
raise e
# For changing the description of the translation PR
def update_pr_description(source_description):
source_pr_CLA = "https://cla-assistant.io/pingcap/" + base_repo
new_pr_CLA = "https://cla-assistant.io/pingcap/" + target_repo_name
new_pr_description = source_description.replace(source_pr_CLA, new_pr_CLA)
new_pr_description = new_pr_description.replace("This PR is translated from:", "This PR is translated from: " + source_pr_url)
if "tips for choosing the affected versions" in source_description:
new_pr_description = re.sub(r'.*?\[tips for choosing the affected version.*?\n\n?',"",new_pr_description)
return new_pr_description
# For deleting temp.md
def delete_file_in_branch(repo_owner, repo_name, branch_name, access_token, file_path, commit_message):
url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/contents/{file_path}"
headers = {
"Authorization": f"Bearer {access_token}",
"Accept": "application/vnd.github.v3+json"
}
params = {
"ref": branch_name
}
# Get information about the file
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
file_info = response.json()
# Prepare the request data to delete the file
data = {
"message": commit_message,
"sha": file_info["sha"],
"branch": branch_name
}
# Send a request to delete a file
try:
response = requests.delete(url, headers=headers, params=params, json=data)
response.raise_for_status()
print("The temp.md is deleted successfully!")
except requests.exceptions.HTTPError as e:
print(f"Failed to delete temp.md. Error message: {response.text}")
raise e
elif response.status_code == 404:
print(f"The temp.md file does not exist in branch {branch_name}.")
else:
print(f"Failed to get file information. Error message: {response.text}")
# Get the information of the source language PR
source_title, source_description, source_labels, base_repo, base_branch, head_repo, head_branch, source_pr_number = get_pr_info(source_pr_url)
# Get the repo info of my foked repository and the target repository, and the translation label
my_repo_owner = my_github_id
target_repo_owner = "pingcap"
if "pingcap/docs-cn/pull" in source_pr_url:
my_repo_name = "docs"
target_repo_name = "docs"
translation_label = "translation/from-docs-cn"
elif "pingcap/docs/pull" in source_pr_url:
target_repo_name = "docs-cn"
my_repo_name = "docs-cn"
translation_label = "translation/from-docs"
else:
print ("Error: The provided URL is not a pull request of pingcap/docs-cn or pingcap/docs.")
print("Exiting the program...")
exit(1)
source_labels.append(translation_label)
#print ("The following labels will be reused for the translation PR.")
#print (source_labels)
# Sync from upstream
sync_my_repo_branch(target_repo_owner, target_repo_name,my_repo_owner, my_repo_name, base_branch)
# Create a new branch in the repository that I forked
new_branch_name = head_branch + "-" + source_pr_number
## print (my_repo_owner, my_repo_name, new_branch_name, base_branch )
create_branch(my_repo_owner, my_repo_name, new_branch_name, base_branch, access_token)
# Create a temporary temp.md file in the new branch
file_path = "temp.md"
file_content = "This is a test file."
commit_message = "Add temp.md"
create_file_in_branch(my_repo_owner, my_repo_name, new_branch_name, access_token, file_path, file_content, commit_message)
# Create the target PR
title = source_title
body = update_pr_description(source_description)
labels = source_labels
create_pull_request(target_repo_owner, target_repo_name, base_branch, my_repo_owner, my_repo_name, new_branch_name, access_token, title, body, labels)
# Delete the temporary temp.md file
commit_message2 = "Delete temp.md"
delete_file_in_branch(my_repo_owner, my_repo_name, new_branch_name, access_token, file_path, commit_message2)