-
Notifications
You must be signed in to change notification settings - Fork 12
/
open_contrib_pr.py
164 lines (141 loc) · 5.43 KB
/
open_contrib_pr.py
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
#!/usr/bin/env python
""" Automatically open a pull request for repositories that have no CONTRIBUTING.md file """
import json
import os
from time import sleep
import auth
import env
import github3
def get_repos_json(gh_actor, repos_json_location, token, endpoint):
"""
Get the list of repositories from the JSON file.
Args:
gh_actor (str): The GitHub actor (username).
repos_json_location (str): The location of the JSON file containing the repositories.
token (str): The GitHub personal access token.
endpoint (str): The GitHub endpoint.
Returns:
dict: A dictionary containing the list of repositories.
"""
os.system(f"git clone https://{gh_actor}:{token}@{endpoint}/{repos_json_location}")
with open(str(repos_json_location), "r", encoding="utf-8") as repos_file:
innersource_repos = json.loads(repos_file.read())
return innersource_repos
def main(): # pragma: no cover
"""
Automatically open a pull request for repositories that have no CONTRIBUTING.md
file from a list of repositories in a JSON file
"""
env_vars = env.get_env_vars()
gh_actor = env_vars.gh_actor
organization = env_vars.organization
pr_body = env_vars.pr_body
pr_title = env_vars.pr_title
repos_json_location = env_vars.repos_json_location
token = env_vars.gh_token
gh_app_id = env_vars.gh_app_id
gh_app_installation_id = env_vars.gh_app_installation_id
gh_app_private_key_bytes = env_vars.gh_app_private_key_bytes
ghe = env_vars.gh_enterprise_url
gh_app_enterprise_only = env_vars.gh_app_enterprise_only
# Auth to GitHub.com
github_connection = auth.auth_to_github(
token,
gh_app_id,
gh_app_installation_id,
gh_app_private_key_bytes,
ghe,
gh_app_enterprise_only,
)
if not token and gh_app_id and gh_app_installation_id and gh_app_private_key_bytes:
token = auth.get_github_app_installation_token(
ghe, gh_app_id, gh_app_private_key_bytes, gh_app_installation_id
)
endpoint = ghe.removeprefix("https://") if ghe else "github.com"
os.system("git config --global user.name 'GitHub Actions'")
os.system(f"git config --global user.email 'no-reply@{endpoint}'")
# Get innersource repos from organization
innersource_repos = get_repos_json(gh_actor, repos_json_location, token, endpoint)
for repo in innersource_repos:
print(repo["name"])
# check if the repo has a contributing.md file
try:
if repo["_InnerSourceMetadata"]["guidelines"] == "CONTRIBUTING.md":
continue
except KeyError:
# clone the repo
repo_name = clone_repository(gh_actor, token, endpoint, repo)
if not repo_name:
continue
# checkout a branch called contributing-doc
branch_name = "contributing-doc"
os.chdir(f"{repo_name}")
os.system(f"git checkout -b {branch_name}")
# copy, customize, and git add the template file
os.system("cp /action/workspace/CONTRIBUTING-template.md CONTRIBUTING.md")
os.system(f"sed -i 's/Project-Name/{repo_name}/g' CONTRIBUTING.md")
os.system("git add CONTRIBUTING.md")
# git commit that file
os.system(
"git commit -m'Request to add a document outlining how to contribute'"
)
# git push the branch
os.system(f"git push -u origin {branch_name}")
# open a PR from that branch to the default branch
default_branch = repo["default_branch"]
# create the pull request
create_pull_request(
organization,
pr_body,
pr_title,
github_connection,
repo_name,
branch_name,
default_branch,
)
# Clean up repository dir
os.chdir("../")
os.system(f"rm -rf {repo_name}")
# rate limit to 20 repos per hour
print("Waiting 3 minutes so as not to exceed API limits")
sleep(180)
def create_pull_request(
organization,
pr_body,
pr_title,
github_connection,
repo_name,
branch_name,
default_branch,
):
"""Create a pull request."""
repository_object = github_connection.repository(organization, repo_name)
try:
repository_object.create_pull(
title=pr_title,
body=pr_body,
head=branch_name,
base=default_branch,
)
except github3.exceptions.UnprocessableEntity:
print("Pull request already exists")
except github3.exceptions.ForbiddenError:
print("Pull request failed")
except github3.exceptions.NotFoundError:
print("Pull request failed")
except github3.exceptions.ConnectionError:
print("Pull request failed")
except Exception as e: # pylint: disable=broad-exception-caught
print(e)
def clone_repository(gh_actor, token, endpoint, repo):
"""Clone the repository and return the name of the repository."""
repo_full_name = repo["full_name"]
repo_name = repo["name"]
try:
os.system(f"git clone https://{gh_actor}:{token}@{endpoint}/{repo_full_name}")
except OSError as e:
print(f"Failed to clone repository: {e}")
return None
return repo_name
if __name__ == "__main__":
main() # pragma: no cover