This is an automated email from the ASF dual-hosted git repository.
dongjoon pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/master by this push:
new 8523ee5d90f [SPARK-44972][INFRA] Eagerly check if the token is valid
to align with the behavior of username/password auth
8523ee5d90f is described below
commit 8523ee5d90f854cdeb96c70cb16db7cd32f5429e
Author: Kent Yao <[email protected]>
AuthorDate: Mon Aug 28 09:05:09 2023 -0700
[SPARK-44972][INFRA] Eagerly check if the token is valid to align with the
behavior of username/password auth
### What changes were proposed in this pull request?
The SPARK-44802 now allows for token authentication when resolving Jira
issues in pull request merging. However, the token auth is kinda lazy during
the initial handshake, maintainers might get confused someday.
This pull request promptly calls the current_user() function to initiate
authentication and provides clear instructions for token expiration.
### Why are the changes needed?
make it easy for maintainers to update their expired Jira tokens.
### Does this PR introduce _any_ user-facing change?
no, for maintainers
### How was this patch tested?
locally verified the code snippet
### Was this patch authored or co-authored using generative AI tooling?
no
Closes #42625 from yaooqinn/SPARK-44802-FF.
Authored-by: Kent Yao <[email protected]>
Signed-off-by: Dongjoon Hyun <[email protected]>
---
dev/merge_spark_pr.py | 82 ++++++++++++++++++++++++++++++---------------------
1 file changed, 48 insertions(+), 34 deletions(-)
diff --git a/dev/merge_spark_pr.py b/dev/merge_spark_pr.py
index 01851b185dd..2e4b7d3a6fa 100755
--- a/dev/merge_spark_pr.py
+++ b/dev/merge_spark_pr.py
@@ -243,13 +243,6 @@ def cherry_pick(pr_num, merge_hash, default_branch):
def resolve_jira_issue(merge_branches, comment, default_jira_id=""):
- jira_server = {"server": JIRA_API_BASE}
-
- if JIRA_ACCESS_TOKEN is not None:
- asf_jira = jira.client.JIRA(jira_server, token_auth=JIRA_ACCESS_TOKEN)
- else:
- asf_jira = jira.client.JIRA(jira_server, basic_auth=(JIRA_USERNAME,
JIRA_PASSWORD))
-
jira_id = input("Enter a JIRA id [%s]: " % default_jira_id)
if jira_id == "":
jira_id = default_jira_id
@@ -263,7 +256,7 @@ def resolve_jira_issue(merge_branches, comment,
default_jira_id=""):
cur_summary = issue.fields.summary
cur_assignee = issue.fields.assignee
if cur_assignee is None:
- cur_assignee = choose_jira_assignee(issue, asf_jira)
+ cur_assignee = choose_jira_assignee(issue)
# Check again, we might not have chosen an assignee
if cur_assignee is None:
cur_assignee = "NOT ASSIGNED!!!"
@@ -362,7 +355,7 @@ def resolve_jira_issue(merge_branches, comment,
default_jira_id=""):
print("Successfully resolved %s with fixVersions=%s!" % (jira_id,
fix_versions))
-def choose_jira_assignee(issue, asf_jira):
+def choose_jira_assignee(issue):
"""
Prompt the user to choose who to assign the issue to in jira, given a list
of candidates,
including the original reporter and all commentators
@@ -395,7 +388,7 @@ def choose_jira_assignee(issue, asf_jira):
# assume it's a user id, and try to assign (might fail, we
just prompt again)
assignee = asf_jira.user(raw_assignee)
try:
- assign_issue(asf_jira, issue.key, assignee.name)
+ assign_issue(issue.key, assignee.name)
except Exception as e:
if (
e.__class__.__name__ == "JIRAError"
@@ -406,8 +399,8 @@ def choose_jira_assignee(issue, asf_jira):
"User '%s' cannot be assigned, add to contributors
role and try again?"
% assignee.name
)
- grant_contributor_role(assignee.name, asf_jira)
- assign_issue(asf_jira, issue.key, assignee.name)
+ grant_contributor_role(assignee.name)
+ assign_issue(issue.key, assignee.name)
else:
raise e
return assignee
@@ -418,22 +411,22 @@ def choose_jira_assignee(issue, asf_jira):
print("Error assigning JIRA, try again (or leave blank and fix
manually)")
-def grant_contributor_role(user: str, asf_jira):
+def grant_contributor_role(user: str):
role = asf_jira.project_role("SPARK", 10010)
role.add_user(user)
print("Successfully added user '%s' to contributors role" % user)
-def assign_issue(client, issue: int, assignee: str) -> bool:
+def assign_issue(issue: int, assignee: str) -> bool:
"""
Assign an issue to a user, which is a shorthand for
jira.client.JIRA.assign_issue.
The original one has an issue that it will search users again and only
choose the assignee
from 20 candidates. If it's unmatched, it picks the head blindly. In our
case, the assignee
is already resolved.
"""
- url = getattr(client, "_get_latest_url")(f"issue/{issue}/assignee")
+ url = getattr(asf_jira, "_get_latest_url")(f"issue/{issue}/assignee")
payload = {"name": assignee}
- getattr(client, "_session").put(url, data=json.dumps(payload))
+ getattr(asf_jira, "_session").put(url, data=json.dumps(payload))
return True
@@ -521,17 +514,43 @@ def get_current_ref():
return ref
+def initialize_jira():
+ global asf_jira
+ jira_server = {"server": JIRA_API_BASE}
+
+ if not JIRA_IMPORTED:
+ print("ERROR finding jira library. Run 'pip3 install jira' to
install.")
+ continue_maybe("Continue without jira?")
+ elif JIRA_ACCESS_TOKEN:
+ client = jira.client.JIRA(jira_server, token_auth=JIRA_ACCESS_TOKEN)
+ try:
+ # Eagerly check if the token is valid to align with the behavior
of username/password
+ # authn
+ client.current_user()
+ asf_jira = client
+ except Exception as e:
+ if e.__class__.__name__ == "JIRAError" and getattr(e,
"status_code", None) == 401:
+ msg = (
+ "ASF JIRA could not authenticate with the invalid or
expired token '%s'"
+ % JIRA_ACCESS_TOKEN
+ )
+ fail(msg)
+ else:
+ raise e
+ elif JIRA_USERNAME and JIRA_PASSWORD:
+ asf_jira = jira.client.JIRA(jira_server, basic_auth=(JIRA_USERNAME,
JIRA_PASSWORD))
+ else:
+ print("Neither JIRA_ACCESS_TOKEN nor JIRA_USERNAME/JIRA_PASSWORD are
set.")
+ continue_maybe("Continue without jira?")
+
+
def main():
+ initialize_jira()
global original_head
os.chdir(SPARK_HOME)
original_head = get_current_ref()
- # Check this up front to avoid failing the JIRA update at the very end
- if not JIRA_ACCESS_TOKEN and (not JIRA_USERNAME or not JIRA_PASSWORD):
- msg = "The env-vars JIRA_ACCESS_TOKEN or JIRA_USERNAME/JIRA_PASSWORD
are not set. Continue?"
- continue_maybe(msg)
-
branches = get_json("%s/branches" % GITHUB_API_BASE)
branch_names = list(filter(lambda x: x.startswith("branch-"), [x["name"]
for x in branches]))
# Assumes branch names can be sorted lexicographically
@@ -629,20 +648,15 @@ def main():
while input("\n%s (y/n): " % pick_prompt).lower() == "y":
merged_refs = merged_refs + [cherry_pick(pr_num, merge_hash,
latest_branch)]
- if JIRA_IMPORTED:
- if JIRA_ACCESS_TOKEN or (JIRA_USERNAME and JIRA_PASSWORD):
- continue_maybe("Would you like to update an associated JIRA?")
- jira_comment = "Issue resolved by pull request %s\n[%s/%s]" % (
- pr_num,
- GITHUB_BASE,
- pr_num,
- )
- resolve_jira_issues(title, merged_refs, jira_comment)
- else:
- print("Neither JIRA_ACCESS_TOKEN nor JIRA_USERNAME/JIRA_PASSWORD
are set.")
- print("Exiting without trying to close the associated JIRA.")
+ if asf_jira is not None:
+ continue_maybe("Would you like to update an associated JIRA?")
+ jira_comment = "Issue resolved by pull request %s\n[%s/%s]" % (
+ pr_num,
+ GITHUB_BASE,
+ pr_num,
+ )
+ resolve_jira_issues(title, merged_refs, jira_comment)
else:
- print("Could not find jira-python library. Run 'pip3 install jira' to
install.")
print("Exiting without trying to close the associated JIRA.")
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]