-
Notifications
You must be signed in to change notification settings - Fork 0
/
add_depr_wkflw_issues.py
161 lines (136 loc) · 6.63 KB
/
add_depr_wkflw_issues.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
#!/usr/bin/env python3
"""
Usage:
python -m add-depr-wkflw-issues.py
Requires:
GITHUB_AUTH token in local environment
Description:
Transfers reference workflow template to all repos in the org. Additionally,
if the org doesn't have issues enabled, transfers a reference issue template
and issue configuration (if issues are enabled, inheriting a more open
reference issue template set will suffice).
"""
import json
import logging
import sys
import time
from github_helpers import *
# Switch to DEBUG for additional debugging info
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
LOG = logging.getLogger(__name__)
def main(org, root_dir, exclude_private=False, interactive=False):
"""
Goes through all repos in an org, clones them, makes a new branch, copies
specific files, commits them, creates a pull request, and merges the pull
request.
* org (str): GitHub organization
* root_dir (str): path to directory to clone repos (on Mac, may look like
`/Users/<uname>/path/to/dir`
* exclude_private (bool): if True, script skips private repos (default
False)
* interactive (bool): if True, pauses before committing files upstream and
awaits user confirmation
"""
gh_headers = get_github_headers()
branch_name = "tcril/depr-automation-workflow"
workflow_template_name = "add-depr-ticket-to-depr-board.yml"
issue_template_name = "depr-ticket.yml"
commit_msg_wkflow_only = "build: add DEPR workflow automation"
pr_details_wkflow_only = {
"title": "Add DEPR workflow automation",
"body": "## This PR was autogenerated\n\n## This PR will be automerged\n\nThis pr introduces workflow automation which allows us to put DEPR tickets from this repo onto the global DEPR project board. It also notifies the `#depr-slash-n-burn` Slack room when new issues are created."
}
commit_msg_with_issue = commit_msg_wkflow_only + " & default issue overrides"
pr_details_with_issue = {
"title": pr_details_wkflow_only["title"] + " & default issue overrides",
"body": pr_details_wkflow_only["body"] + "\n\nSince this repo currently does not have Issues enabled, a special override configuration has been added to turn off all issue types except DEPR tickets. This will allow us to turn on Issues in this repo without opening the gates for other types of reports."
}
prs = []
pr_failed = []
repos_skipped = []
for repo_data in get_repos(gh_headers, org, exclude_private):
(rname, ssh_url, dbranch, has_issues, count) = repo_data
LOG.info("\n\n******* CHECKING REPO: {} ({}) ************".format(rname, count))
repo_path = get_repo_path(rname, root_dir)
# clone repo; if exists, checkout the default branch & pull latest
clone_repo(root_dir, repo_path, ssh_url, dbranch)
if issue_config_exists(repo_path):
# Some repos may already configure issues, so don't overwrite
LOG.info("Skipping {} (don't want to overwrite config.yml)".format(rname))
repos_skipped.append([rname, "config exists"])
continue
if not new_branch(repo_path, branch_name):
# this branch already exists
LOG.info("Skipping {}, branch already exists".format(rname))
repos_skipped.append([rname, "branch exists"])
continue
add_files(
root_dir,
repo_path,
workflow_template_name,
has_issues,
issue_template_name
)
if interactive:
try:
interactive_commit(repo_path)
except RepoError:
# move on to next repo
continue
# If the repo has issues only committing the workflow, otherwise also
# committing the issue template and configuration
commit_msg = commit_msg_wkflow_only if has_issues else commit_msg_with_issue
pr_details = pr_details_wkflow_only if has_issues else pr_details_with_issue
make_commit(repo_path, commit_msg)
try:
pr_url = make_pr(gh_headers, org, rname, branch_name, dbranch, pr_details)
prs.append(pr_url)
except PrCreationError as pr_err:
LOG.info(pr_err.__str__())
# info you need to retry
pr_failed.append((org, rname, branch_name, dbranch, pr_details))
# Without, you hit secondary rate limits if you have more than ~30
# repos. I tried 3, too short. 30, totally worked. there's a good number
# in between that i'm sure
time.sleep(5)
LOG.info(
"Processed {} repos; see output/prs.json ({}) and output/failed.json ({})".format(
count, len(prs), len(pr_failed)
)
)
LOG.info("Skipped these repos as branch was already defined: {}".format(repos_skipped))
with open("output/prs.json", "w") as f:
f.write(json.dumps(prs))
with open("output/failed.json", "w") as f2:
f2.write(json.dumps(pr_failed))
def add_files(root_dir, repo_path, wtemplate_name, has_issues, itemplate_name):
"""
For the given repo (represented by the repo_path) which resides in the
root_dir, copies a workflow template from the root_dir/.github/workflow-templates
directory into repo_path/.github/workflow-templates.
If the repo does not have issues enabled, copies
root_dir/override_config.yml and root_dir/.github/ISSUE_TEMPLATE/itemplate_name
into repo_path/.github/ISSUE_TEMPLATE/config.yml and itemplate_name, respectively
"""
mkdir(repo_path, ".github")
mkdir(repo_path, ".github/workflows")
dot_github_path = get_repo_path('.github', root_dir)
workflow_template_path = dot_github_path + '/workflow-templates/' + wtemplate_name
workflow_destination_path = repo_path + '/.github/workflows'
cp(repo_path, workflow_template_path, workflow_destination_path)
if not has_issues:
# if issues aren't enabled on this repo yet, we copy over the DEPR
# template as well as a config file to turn on the DEPR template
mkdir(repo_path, ".github/ISSUE_TEMPLATE")
issue_template_path = dot_github_path + "/.github/ISSUE_TEMPLATE/" + itemplate_name
cp(repo_path, issue_template_path, ".github/ISSUE_TEMPLATE")
cp(repo_path, "../override_config.yml", ".github/ISSUE_TEMPLATE/config.yml")
def issue_config_exists(repo_path):
"""
returns True if the issue template config.yml file exists in the repo_path
"""
path_to_config = repo_path + "/.github/ISSUE_TEMPLATE/config.yml"
return os.path.exists(path_to_config)
if __name__ == "__main__":
root_dir = "/Users/sarinacanelake/openedx/"
main("openedx", root_dir, True, False)