-
Notifications
You must be signed in to change notification settings - Fork 218
initial support for --close-pr (REVIEW) #2401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
8fdbdc1
964f696
fd5fcbb
07467c6
6b08c43
6d51226
50c8729
979d888
5ffc967
e5898ba
1efaf34
c0345f1
29acced
7bf3a2a
1bf0dc4
91f46e2
34f6996
03583e7
c433ecc
5fd515c
fb89e0b
580feb2
527b41e
eda7b5c
6e2cc2d
eb4eb0b
fc2e7bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,7 @@ | |
| import tempfile | ||
| import time | ||
| import urllib2 | ||
| from datetime import datetime, timedelta | ||
| from distutils.version import LooseVersion | ||
| from vsc.utils import fancylogger | ||
| from vsc.utils.missing import nub | ||
|
|
@@ -96,6 +97,9 @@ | |
| KEYRING_GITHUB_TOKEN = 'github_token' | ||
| URL_SEPARATOR = '/' | ||
|
|
||
| VALID_CLOSE_PR_REASONS = {'archived': 'uses an archived toolchain', | ||
| 'inactive': 'no activity for > 6 months', | ||
| 'obsolete': 'obsoleted by more recent PRs'} | ||
|
|
||
| class Githubfs(object): | ||
| """This class implements some higher level functionality on top of the Github api""" | ||
|
|
@@ -369,12 +373,8 @@ def fetch_easyconfigs_from_pr(pr, path=None, github_user=None): | |
| mkdir(path, parents=True) | ||
|
|
||
| _log.debug("Fetching easyconfigs from PR #%s into %s" % (pr, path)) | ||
| pr_url = lambda g: g.repos[GITHUB_EB_MAIN][GITHUB_EASYCONFIGS_REPO].pulls[pr] | ||
|
|
||
| status, pr_data = github_api_get_request(pr_url, github_user) | ||
| if status != HTTP_STATUS_OK: | ||
| raise EasyBuildError("Failed to get data for PR #%d from %s/%s (status: %d %s)", | ||
| pr, GITHUB_EB_MAIN, GITHUB_EASYCONFIGS_REPO, status, pr_data) | ||
| status, pr_data, pr_url = fetch_pr_data(pr, GITHUB_EB_MAIN, GITHUB_EASYCONFIGS_REPO, github_user) | ||
|
|
||
| # if PR is open and mergable, download develop and patch | ||
| stable = pr_data['mergeable_state'] == GITHUB_MERGEABLE_STATE_CLEAN | ||
|
|
@@ -970,6 +970,60 @@ def not_eligible(msg): | |
| return res | ||
|
|
||
|
|
||
| def close_pr(pr, reasons): | ||
| """ | ||
| Close specified pull request | ||
| """ | ||
| github_user = build_option('github_user') | ||
| if github_user is None: | ||
| raise EasyBuildError("GitHub user must be specified to use --close-pr") | ||
|
|
||
| pr_target_account = build_option('pr_target_account') | ||
| pr_target_repo = build_option('pr_target_repo') | ||
|
|
||
| status, pr_data, pr_url = fetch_pr_data(pr, pr_target_account, pr_target_repo, github_user) | ||
|
|
||
| if pr_data['state'] == GITHUB_STATE_CLOSED: | ||
| raise EasyBuildError("PR #%d from %s/%s is already closed.", pr, pr_target_account, pr_target_repo) | ||
|
|
||
| pr_owner = pr_data['user']['login'] | ||
| msg = "\n%s/%s PR #%s was submitted by %s, " % (pr_target_account, pr_target_repo, pr, pr_owner) | ||
| msg += "you are using GitHub account '%s'\n" % github_user | ||
| print_msg(msg, prefix=False) | ||
|
|
||
| dry_run = build_option('dry_run') or build_option('extended_dry_run') | ||
|
|
||
| if not reasons: | ||
| relevant_reasons = [] | ||
| if datetime.now() - datetime.strptime(pr_data['updated_at'], "%Y-%m-%dT%H:%M:%SZ") > timedelta(days=180): | ||
| relevant_reasons.append('inactive') | ||
| # TODO: check the other valid reasons | ||
| if not relevant_reasons: | ||
| raise EasyBuildError("No reason specified and none found from PR data, " | ||
| "please use --close-pr-reasons or --close-pr-msg") | ||
| else: | ||
| reasons = ", ".join([VALID_CLOSE_PR_REASONS[reason] for reason in relevant_reasons]) | ||
|
|
||
| msg = "@%s, this PR is being closed for the following reason(s): %s.\n" % (pr_data['user']['login'], reasons) | ||
| msg += "Please don't hesitate to reopen this PR or add a comment if you feel this contribution is still relevant.\n" | ||
| msg += "For more information on our policy w.r.t. closing PRs, see " | ||
| msg += "https://easybuild.readthedocs.io/en/latest/Contributing.html#why-a-pull-request-may-be-closed-by-a-maintainer" | ||
boegel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| post_comment_in_issue(pr, msg, account=pr_target_account, repo=pr_target_repo, github_user=github_user) | ||
|
|
||
| if dry_run: | ||
| print_msg("[DRY RUN] Closed %s/%s pull request #%s" % (pr_target_account, pr_target_repo, pr), prefix=False) | ||
| else: | ||
| github_token = fetch_github_token(github_user) | ||
| if github_token is None: | ||
| raise EasyBuildError("GitHub token for user '%s' must be available to use --close-pr", github_user) | ||
| g = RestClient(GITHUB_API_URL, username=github_user, token=github_token) | ||
| pull_url = g.repos[pr_target_account][pr_target_repo].pulls[pr] | ||
| body = {'state': 'closed'} | ||
| status, data = pull_url.post(body=body) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a lot of duplication here too, maybe time for a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @migueldiascosta Does this suggestion still make sense, or not?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @boegel I don't know - each case is slightly different, but I may be missing an obvious generalization
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just took a look myself, it's indeed not entirely trivial, so let's leave it as is (for now). |
||
| if not status == HTTP_STATUS_OK: | ||
| raise EasyBuildError("Failed to close PR #%s; status %s, data: %s", pr, status, data) | ||
|
|
||
|
|
||
| def merge_pr(pr): | ||
| """ | ||
| Merge specified pull request | ||
|
|
@@ -981,11 +1035,7 @@ def merge_pr(pr): | |
| pr_target_account = build_option('pr_target_account') | ||
| pr_target_repo = build_option('pr_target_repo') | ||
|
|
||
| pr_url = lambda g: g.repos[pr_target_account][pr_target_repo].pulls[pr] | ||
| status, pr_data = github_api_get_request(pr_url, github_user) | ||
| if status != HTTP_STATUS_OK: | ||
| raise EasyBuildError("Failed to get data for PR #%d from %s/%s (status: %d %s)", | ||
| pr, pr_target_account, pr_target_repo, status, pr_data) | ||
| status, pr_data, pr_url = fetch_pr_data(pr, pr_target_account, pr_target_repo, github_user) | ||
|
|
||
| msg = "\n%s/%s PR #%s was submitted by %s, " % (pr_target_account, pr_target_repo, pr, pr_data['user']['login']) | ||
| msg += "you are using GitHub account '%s'\n" % github_user | ||
|
|
@@ -1175,11 +1225,7 @@ def update_pr(pr, paths, ecs, commit_msg=None): | |
| pr_target_account = build_option('pr_target_account') | ||
| pr_target_repo = build_option('pr_target_repo') | ||
|
|
||
| pr_url = lambda g: g.repos[pr_target_account][pr_target_repo].pulls[pr] | ||
| status, pr_data = github_api_get_request(pr_url, github_user) | ||
| if status != HTTP_STATUS_OK: | ||
| raise EasyBuildError("Failed to get data for PR #%d from %s/%s (status: %d %s)", | ||
| pr, pr_target_account, pr_target_repo, status, pr_data) | ||
| status, pr_data, pr_url = fetch_pr_data(pr, pr_target_account, pr_target_repo, github_user) | ||
|
|
||
| # branch that corresponds with PR is supplied in form <account>:<branch_label> | ||
| account = pr_data['head']['label'].split(':')[0] | ||
|
|
@@ -1517,3 +1563,13 @@ def find_easybuild_easyconfig(github_user=None): | |
|
|
||
| eb_file = os.path.join(eb_parent_path, fn) | ||
| return eb_file | ||
|
|
||
boegel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| def fetch_pr_data(pr, pr_target_account, pr_target_repo, github_user): | ||
boegel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| """Fetch PR data from GitHub""" | ||
| pr_url = lambda g: g.repos[pr_target_account][pr_target_repo].pulls[pr] | ||
boegel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
boegel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
boegel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
boegel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| status, pr_data = github_api_get_request(pr_url, github_user) | ||
| if status != HTTP_STATUS_OK: | ||
| raise EasyBuildError("Failed to get data for PR #%d from %s/%s (status: %d %s)", | ||
| pr, pr_target_account, pr_target_repo, status, pr_data) | ||
| return status, pr_data, pr_url | ||
Uh oh!
There was an error while loading. Please reload this page.