From e60417d3bcff7ae0bdd4acabc1453690cd073be7 Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Wed, 30 Jun 2021 14:53:19 +0800 Subject: [PATCH 01/10] release issue status --- scripts/release_issue_status/main.py | 147 ++++++++++++++++++ .../release_issue_status.yml | 46 ++++++ scripts/release_issue_status/requirement.txt | 2 + 3 files changed, 195 insertions(+) create mode 100644 scripts/release_issue_status/main.py create mode 100644 scripts/release_issue_status/release_issue_status.yml create mode 100644 scripts/release_issue_status/requirement.txt diff --git a/scripts/release_issue_status/main.py b/scripts/release_issue_status/main.py new file mode 100644 index 000000000000..7aaa9fc478c1 --- /dev/null +++ b/scripts/release_issue_status/main.py @@ -0,0 +1,147 @@ +from github import Github +import re +from datetime import date, datetime +import time +import os +import logging +import subprocess as sp + +_LOG = logging.getLogger() +_NULL = ' ' + + +def my_print(cmd): + _LOG.info('==' + cmd + ' ==\n') + + +def print_check(cmd): + my_print(cmd) + sp.check_call(cmd, shell=True) + + +class IssueStatus: + link = _NULL + author = _NULL + package = _NULL + create_date = 0.0 + delay_from_create_date = 0 + latest_update = 0.0 + delay_from_latest_update = 0 + status = 'confirm' + bot_advice = _NULL + comment_num = 0 + language = _NULL + author_latest_comment = _NULL + + def output(self): + return '{},{},{},{},{},{},{},{},{},{}\n'.format(self.language, self.link, self.author, + self.package, + str(date.fromtimestamp(self.create_date)), + self.delay_from_create_date, + str(date.fromtimestamp(self.latest_update)), + self.delay_from_latest_update, + self.status, self.bot_advice) + + +def _extract(str_list, key_word): + for item in str_list: + if re.fullmatch(key_word, item): + return item.strip() + return _NULL + + +def _time_format_transform(time_gmt): + return str(datetime.strptime(time_gmt, '%a, %d %b %Y %H:%M:%S GMT')) + + +def _judge_status(labels): + for label in labels: + if label.name == 'release': + return 'release' + return 'confirm' + + +def _extract_language(labels): + language = {'Python', 'JS', 'Go', 'Java', 'Ruby'} + label_set = {label.name for label in labels} + intersect = language.intersection(label_set) + return _NULL if not intersect else intersect.pop() + + +def _key_select(item): + return item.package + + +def _extract_author_latest_comment(comments): + q = [(comment.updated_at.timestamp(), comment.user.login) for comment in comments] + q.sort() + + return _NULL if not q else q[-1][1] + + +def main(): + # get latest issue status + g = Github(os.getenv('TOKEN')) # please fill user_token + repo = g.get_repo('Azure/sdk-release-request') + label1 = repo.get_label('ManagementPlane') + open_issues = repo.get_issues(state='open', labels=[label1]) + issue_status = [] + duplicated_issue = dict() + start_time = time.time() + for item in open_issues: + if not item.number: + continue + issue = IssueStatus() + issue.link = f'https://github.com/Azure/sdk-release-request/issues/{item.number}' + issue.author = item.user.login + issue.package = _extract(item.body.split('\n'), 'azure-.*') + issue.create_date = item.created_at.timestamp() + issue.delay_from_create_date = int((time.time() - item.created_at.timestamp()) / 3600 / 24) + issue.latest_update = item.updated_at.timestamp() + issue.delay_from_latest_update = int((time.time() - item.updated_at.timestamp()) / 3600 / 24) + issue.status = _judge_status(item.labels) + issue.comment_num = item.comments + issue.language = _extract_language(item.labels) + issue.author_latest_comment = _extract_author_latest_comment(item.get_comments()) + + issue_status.append(issue) + key = (issue.language, issue.package) + duplicated_issue[key] = duplicated_issue.get(key, 0) + 1 + + print('Have cost {} seconds'.format(int(time.time() - start_time))) + + # rule1: if status is 'release', need to release asap + # rule2: if latest comment is from author, need response asap + # rule3: if comment num is 0, it is new issue, better to deal with it asap + # rule4: if delay from latest update is over 7 days, better to deal with it soon. + # rule5: if delay from created date is over 30 days, better to close. + for item in issue_status: + if item.status == 'release': + item.bot_advice = 'better to release asap.' + elif item.author == item.author_latest_comment: + item.bot_advice = 'new comment for author.' + elif item.comment_num == 0: + item.bot_advice = 'new issue and better to confirm quickly.' + elif item.delay_from_latest_update >= 7: + item.bot_advice = 'delay for a long time and better to handle now.' + elif item.delay_from_create_date >= 30: + item.bot_advice = 'delay for a month and better to close.' + + # judge whether there is duplicated issue for same package + if item.package != _NULL and duplicated_issue.get((item.language, item.package)) > 1: + item.bot_advice = f'Warning:There is duplicated issue for {item.package}. ' + item.bot_advice + + with open('release_issue_status.csv', 'w') as file_out: + file_out.write('language,issue,author,package,created date,delay from created date,latest update time,' + 'delay from latest update,status,bot advice\n') + file_out.writelines([item.output() for item in sorted(issue_status, key=_key_select)]) + + # commit and push + print_check('git checkout storage-for-release-issue-status') + print_check('git add .') + print_check('git commit \"update release_issue_status \"') + print_check('git push -f origin HEAD') + + +if __name__ == '__main__': + main() diff --git a/scripts/release_issue_status/release_issue_status.yml b/scripts/release_issue_status/release_issue_status.yml new file mode 100644 index 000000000000..b1e43cde4622 --- /dev/null +++ b/scripts/release_issue_status/release_issue_status.yml @@ -0,0 +1,46 @@ +# Release status statistics + +name: ReleaseIssueStatus + +trigger: + branches: + exclude: + - '*' + + +jobs: +- job: ReleaseIssueStatus + displayName: ReleaseIssueStatus Python 3.8 + timeoutInMinutes: 30 + strategy: + maxParallel: 1 + pool: + vmImage: 'ubuntu-20.04' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.8' + addToPath: true + architecture: 'x64' + - bash: | + script_path=$(pwd)/scripts/release_issue_status + cd .. + git config --global user.email "ReleaseIssueStatus" + git config --global user.name "ReleaseIssueStatus" + + # clone(REPO: https://github.com/Azure/azure-sdk-for-python.git, USR_NAME: Azure, USR_TOKEN: xxxxxxxxxxxxx) + mkdir azure-sdk-for-python + git clone ${REPO:0:8}$(USR_NAME):$(USR_TOKEN)@${REPO:8} $(pwd)/azure-sdk-for-python + + # create virtual env + python -m venv venv-sdk + source venv-sdk/bin/activate + output_path=$(pwd)/venv-sdk + pip install -r $script_path/requirement.txt + + # import env variable + export TOKEN=$(USR_TOKEN) + + # run + cd azure-sdk-for-python/scripts/release_issue_status + python $script_path/main.py diff --git a/scripts/release_issue_status/requirement.txt b/scripts/release_issue_status/requirement.txt new file mode 100644 index 000000000000..71bcbea22eb1 --- /dev/null +++ b/scripts/release_issue_status/requirement.txt @@ -0,0 +1,2 @@ +PyGithub +datetime \ No newline at end of file From fc265c8a50f5c573102b498a6afa7138c57fd17b Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Wed, 30 Jun 2021 15:06:23 +0800 Subject: [PATCH 02/10] fix directory --- scripts/release_issue_status/main.py | 2 +- scripts/release_issue_status/release_issue_status.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/release_issue_status/main.py b/scripts/release_issue_status/main.py index 7aaa9fc478c1..c00dfbe66b3a 100644 --- a/scripts/release_issue_status/main.py +++ b/scripts/release_issue_status/main.py @@ -131,7 +131,7 @@ def main(): if item.package != _NULL and duplicated_issue.get((item.language, item.package)) > 1: item.bot_advice = f'Warning:There is duplicated issue for {item.package}. ' + item.bot_advice - with open('release_issue_status.csv', 'w') as file_out: + with open('scripts/release_issue_status/release_issue_status.csv', 'w') as file_out: file_out.write('language,issue,author,package,created date,delay from created date,latest update time,' 'delay from latest update,status,bot advice\n') file_out.writelines([item.output() for item in sorted(issue_status, key=_key_select)]) diff --git a/scripts/release_issue_status/release_issue_status.yml b/scripts/release_issue_status/release_issue_status.yml index b1e43cde4622..77861ef3da8d 100644 --- a/scripts/release_issue_status/release_issue_status.yml +++ b/scripts/release_issue_status/release_issue_status.yml @@ -13,7 +13,7 @@ jobs: displayName: ReleaseIssueStatus Python 3.8 timeoutInMinutes: 30 strategy: - maxParallel: 1 + maxParallel: 3 pool: vmImage: 'ubuntu-20.04' steps: @@ -42,5 +42,5 @@ jobs: export TOKEN=$(USR_TOKEN) # run - cd azure-sdk-for-python/scripts/release_issue_status + cd azure-sdk-for-python python $script_path/main.py From fd3103b9ab8f2c29dbfcbd7b81c80a700eb422be Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Wed, 30 Jun 2021 15:25:21 +0800 Subject: [PATCH 03/10] debug --- scripts/release_issue_status/main.py | 9 ++------- .../release_issue_status/release_issue_status.yml | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/scripts/release_issue_status/main.py b/scripts/release_issue_status/main.py index c00dfbe66b3a..e63abd4c639d 100644 --- a/scripts/release_issue_status/main.py +++ b/scripts/release_issue_status/main.py @@ -131,17 +131,12 @@ def main(): if item.package != _NULL and duplicated_issue.get((item.language, item.package)) > 1: item.bot_advice = f'Warning:There is duplicated issue for {item.package}. ' + item.bot_advice - with open('scripts/release_issue_status/release_issue_status.csv', 'w') as file_out: + # output result + with open('release_issue_status.csv', 'w') as file_out: file_out.write('language,issue,author,package,created date,delay from created date,latest update time,' 'delay from latest update,status,bot advice\n') file_out.writelines([item.output() for item in sorted(issue_status, key=_key_select)]) - # commit and push - print_check('git checkout storage-for-release-issue-status') - print_check('git add .') - print_check('git commit \"update release_issue_status \"') - print_check('git push -f origin HEAD') - if __name__ == '__main__': main() diff --git a/scripts/release_issue_status/release_issue_status.yml b/scripts/release_issue_status/release_issue_status.yml index 77861ef3da8d..d55a6849b31b 100644 --- a/scripts/release_issue_status/release_issue_status.yml +++ b/scripts/release_issue_status/release_issue_status.yml @@ -41,6 +41,19 @@ jobs: # import env variable export TOKEN=$(USR_TOKEN) - # run + # checkout the target branch cd azure-sdk-for-python + git checkout storage-for-release-issue-status + + echo '0000000' + echo | git status + echo '1111111111' + echo | ls + + # run python $script_path/main.py + + # commit and push + git add . + git commit "update release_issue_status" + git push -f origin HEAD From fb7c3faeeaf70cd76cafca50d35456b012745694 Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Wed, 30 Jun 2021 15:51:31 +0800 Subject: [PATCH 04/10] debug --- scripts/release_issue_status/release_issue_status.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/release_issue_status/release_issue_status.yml b/scripts/release_issue_status/release_issue_status.yml index d55a6849b31b..d298b9b977b6 100644 --- a/scripts/release_issue_status/release_issue_status.yml +++ b/scripts/release_issue_status/release_issue_status.yml @@ -31,6 +31,7 @@ jobs: # clone(REPO: https://github.com/Azure/azure-sdk-for-python.git, USR_NAME: Azure, USR_TOKEN: xxxxxxxxxxxxx) mkdir azure-sdk-for-python git clone ${REPO:0:8}$(USR_NAME):$(USR_TOKEN)@${REPO:8} $(pwd)/azure-sdk-for-python + echo ${REPO:0:8}$(USR_NAME):$(USR_TOKEN)@${REPO:8} $(pwd)/azure-sdk-for-python # create virtual env python -m venv venv-sdk From 70e7b0499cb1233b5b7ae9e09f6c83ff26e2da67 Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Wed, 30 Jun 2021 16:09:09 +0800 Subject: [PATCH 05/10] update git repo --- .../release_issue_status.yml | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/scripts/release_issue_status/release_issue_status.yml b/scripts/release_issue_status/release_issue_status.yml index d298b9b977b6..835b53d9ca8e 100644 --- a/scripts/release_issue_status/release_issue_status.yml +++ b/scripts/release_issue_status/release_issue_status.yml @@ -29,32 +29,25 @@ jobs: git config --global user.name "ReleaseIssueStatus" # clone(REPO: https://github.com/Azure/azure-sdk-for-python.git, USR_NAME: Azure, USR_TOKEN: xxxxxxxxxxxxx) - mkdir azure-sdk-for-python - git clone ${REPO:0:8}$(USR_NAME):$(USR_TOKEN)@${REPO:8} $(pwd)/azure-sdk-for-python - echo ${REPO:0:8}$(USR_NAME):$(USR_TOKEN)@${REPO:8} $(pwd)/azure-sdk-for-python + mkdir file-storage + git clone ${REPO:0:8}$(USR_NAME):$(USR_TOKEN)@${REPO:8} $(pwd)/file-storage # create virtual env python -m venv venv-sdk source venv-sdk/bin/activate - output_path=$(pwd)/venv-sdk pip install -r $script_path/requirement.txt # import env variable export TOKEN=$(USR_TOKEN) # checkout the target branch - cd azure-sdk-for-python - git checkout storage-for-release-issue-status - - echo '0000000' - echo | git status - echo '1111111111' - echo | ls + cd file-storage + git checkout release-issue-status # run python $script_path/main.py # commit and push git add . - git commit "update release_issue_status" + git commit -m "update release_issue_status.csv" git push -f origin HEAD From 03998b52afd0080b0ac4c43cb3d44dc3e9eab7d7 Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Thu, 1 Jul 2021 14:55:51 +0800 Subject: [PATCH 06/10] add storage account --- scripts/release_issue_status/main.py | 15 ++++++++++++++- scripts/release_issue_status/requirement.txt | 3 ++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/scripts/release_issue_status/main.py b/scripts/release_issue_status/main.py index e63abd4c639d..3aa7d52de674 100644 --- a/scripts/release_issue_status/main.py +++ b/scripts/release_issue_status/main.py @@ -5,9 +5,11 @@ import os import logging import subprocess as sp +from azure.storage.blob import BlobClient _LOG = logging.getLogger() _NULL = ' ' +_FILE_OUT = 'release_issue_status.csv' def my_print(cmd): @@ -132,11 +134,22 @@ def main(): item.bot_advice = f'Warning:There is duplicated issue for {item.package}. ' + item.bot_advice # output result - with open('release_issue_status.csv', 'w') as file_out: + with open(_FILE_OUT, 'w') as file_out: file_out.write('language,issue,author,package,created date,delay from created date,latest update time,' 'delay from latest update,status,bot advice\n') file_out.writelines([item.output() for item in sorted(issue_status, key=_key_select)]) + # commit to github + print_check('git add .') + print_check('git commit -m \"update excel\"') + print_check('git push -f origin HEAD') + + # upload to storage account(it is created in advance) + blob = BlobClient.from_connection_string(conn_str=os.getenv('CONN_STR'), container_name=os.getenv('FILE'), + blob_name=_FILE_OUT) + with open(_FILE_OUT, 'rb') as data: + blob.upload_blob(data, overwrite=True) + if __name__ == '__main__': main() diff --git a/scripts/release_issue_status/requirement.txt b/scripts/release_issue_status/requirement.txt index 71bcbea22eb1..13781556dd42 100644 --- a/scripts/release_issue_status/requirement.txt +++ b/scripts/release_issue_status/requirement.txt @@ -1,2 +1,3 @@ PyGithub -datetime \ No newline at end of file +datetime +azure.storage.blob==12.8.1 \ No newline at end of file From 046f371be383dd6712a58f662a0a3a829bf14c24 Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Thu, 1 Jul 2021 14:58:56 +0800 Subject: [PATCH 07/10] delete surplus git commit --- scripts/release_issue_status/release_issue_status.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/scripts/release_issue_status/release_issue_status.yml b/scripts/release_issue_status/release_issue_status.yml index 835b53d9ca8e..0c7f5de77fdb 100644 --- a/scripts/release_issue_status/release_issue_status.yml +++ b/scripts/release_issue_status/release_issue_status.yml @@ -45,9 +45,4 @@ jobs: git checkout release-issue-status # run - python $script_path/main.py - - # commit and push - git add . - git commit -m "update release_issue_status.csv" - git push -f origin HEAD + python $script_path/main.py \ No newline at end of file From e1a5421c334f0e1d0486e926c8d9ef9aba89adba Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Thu, 1 Jul 2021 15:04:15 +0800 Subject: [PATCH 08/10] add env var --- scripts/release_issue_status/release_issue_status.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/release_issue_status/release_issue_status.yml b/scripts/release_issue_status/release_issue_status.yml index 0c7f5de77fdb..c6b2fbf79cbf 100644 --- a/scripts/release_issue_status/release_issue_status.yml +++ b/scripts/release_issue_status/release_issue_status.yml @@ -32,6 +32,10 @@ jobs: mkdir file-storage git clone ${REPO:0:8}$(USR_NAME):$(USR_TOKEN)@${REPO:8} $(pwd)/file-storage + # import env variable + export CONN_STR=$(ENV_CONN_STR) + export FILE=$(ENV_FILE) + # create virtual env python -m venv venv-sdk source venv-sdk/bin/activate From ed2cebe2fc973c8f8e87a83b36ed2e18cf6de30c Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Thu, 1 Jul 2021 15:10:40 +0800 Subject: [PATCH 09/10] debug --- scripts/release_issue_status/release_issue_status.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/release_issue_status/release_issue_status.yml b/scripts/release_issue_status/release_issue_status.yml index c6b2fbf79cbf..5046963bbc1b 100644 --- a/scripts/release_issue_status/release_issue_status.yml +++ b/scripts/release_issue_status/release_issue_status.yml @@ -35,15 +35,17 @@ jobs: # import env variable export CONN_STR=$(ENV_CONN_STR) export FILE=$(ENV_FILE) + export TOKEN=$(USR_TOKEN) + + echo 00000000 + echo $CONN_STR + echo $FILE # create virtual env python -m venv venv-sdk source venv-sdk/bin/activate pip install -r $script_path/requirement.txt - # import env variable - export TOKEN=$(USR_TOKEN) - # checkout the target branch cd file-storage git checkout release-issue-status From d972ea5a3a5774ba501487d566c4ea2404433711 Mon Sep 17 00:00:00 2001 From: msyyc <70930885+msyyc@users.noreply.github.com> Date: Thu, 1 Jul 2021 15:29:54 +0800 Subject: [PATCH 10/10] code format --- scripts/release_issue_status/main.py | 12 +++++------- .../release_issue_status/release_issue_status.yml | 4 ---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/scripts/release_issue_status/main.py b/scripts/release_issue_status/main.py index 3aa7d52de674..abd579b1b204 100644 --- a/scripts/release_issue_status/main.py +++ b/scripts/release_issue_status/main.py @@ -1,19 +1,17 @@ -from github import Github -import re -from datetime import date, datetime import time import os -import logging +import re +from github import Github +from datetime import date, datetime import subprocess as sp from azure.storage.blob import BlobClient -_LOG = logging.getLogger() _NULL = ' ' _FILE_OUT = 'release_issue_status.csv' def my_print(cmd): - _LOG.info('==' + cmd + ' ==\n') + print('==' + cmd + ' ==\n') def print_check(cmd): @@ -110,7 +108,7 @@ def main(): key = (issue.language, issue.package) duplicated_issue[key] = duplicated_issue.get(key, 0) + 1 - print('Have cost {} seconds'.format(int(time.time() - start_time))) + my_print('Have cost {} seconds'.format(int(time.time() - start_time))) # rule1: if status is 'release', need to release asap # rule2: if latest comment is from author, need response asap diff --git a/scripts/release_issue_status/release_issue_status.yml b/scripts/release_issue_status/release_issue_status.yml index 5046963bbc1b..3d4fd02b66ad 100644 --- a/scripts/release_issue_status/release_issue_status.yml +++ b/scripts/release_issue_status/release_issue_status.yml @@ -37,10 +37,6 @@ jobs: export FILE=$(ENV_FILE) export TOKEN=$(USR_TOKEN) - echo 00000000 - echo $CONN_STR - echo $FILE - # create virtual env python -m venv venv-sdk source venv-sdk/bin/activate