From 059026e86ea02bae4001a269a011e6f0d7b764d0 Mon Sep 17 00:00:00 2001 From: Alexander Vogt Date: Thu, 2 May 2024 14:45:17 +0200 Subject: [PATCH 1/6] add workflow for closing issues on develop merge --- .github/workflows/closeDevIssues.yml | 21 ++++++ .github/workflows/scripts/closeDevIssues.py | 74 +++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 .github/workflows/closeDevIssues.yml create mode 100644 .github/workflows/scripts/closeDevIssues.py diff --git a/.github/workflows/closeDevIssues.yml b/.github/workflows/closeDevIssues.yml new file mode 100644 index 000000000..63c1f5d60 --- /dev/null +++ b/.github/workflows/closeDevIssues.yml @@ -0,0 +1,21 @@ +name: Close PR on develop merge + +on: + pull_request: + types: + - closed + +jobs: + close_issues: + if: github.event.pull_request.merged == true && github.base_ref == 'develop' + runs-on: ubuntu-latest + + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v4 + + - name: Run script + working-directory: .github/workflows/scripts + run: | + pip install requests + python closeDevIssues.py ${{ secrets.GITHUB_TOKEN }} ${{ github.event.pull_request.number }} \ No newline at end of file diff --git a/.github/workflows/scripts/closeDevIssues.py b/.github/workflows/scripts/closeDevIssues.py new file mode 100644 index 000000000..fee23ae5a --- /dev/null +++ b/.github/workflows/scripts/closeDevIssues.py @@ -0,0 +1,74 @@ +import requests +import re +import sys + +headers = {"Authorization": f"Bearer {sys.argv[1]}"} + +owner = "jplag" +repo = "JPlag" +pr_number = int(sys.argv[2]) + +query = f""" +{{ + repository(owner: "{owner}", name: "{repo}") {{ + pullRequest(number: {pr_number}) {{ + merged + baseRefName + body + closingIssuesReferences (first: 50) {{ + nodes {{ + number + }} + }} + }} + }} +}} +""" + +def run_query(query): # A simple function to use requests.post to make the API call. Note the json= section. + request = requests.post('https://api.github.com/graphql', json={'query': query}, headers=headers) + if request.status_code == 200: + return request.json() + else: + raise Exception("Query failed to run by returning code of {}. {}".format(request.status_code, query)) + + +closing_keywords = [ + 'closes', 'close', 'closed', 'fix', 'fixes', 'fixed', 'resolves', 'resolve', 'resolved' +] + +# checks all subsequeces of the pr body for closing keywords and extracts the coresponidng issue numbers +def subsequences_matching_regex(input_string, regex): + matches = [] + for i in range(len(input_string)): + for j in range(i+1, len(input_string)+1): + subsequence = input_string[i:j] + match = re.fullmatch(regex, subsequence) + if match: + matches.append(int(match.group(1))) + return matches + +# gets all issues linked to pr either via the closing keywords or the sidebar +def get_linked_issues(result): + closing_issues = [] + for keyword in closing_keywords: + closing_issues.extend(subsequences_matching_regex(result['body'].lower(), f'{keyword} #([0-9]+)')) + for k in result['closingIssuesReferences']['nodes']: + closing_issues.append(k['number']) + return list(set(closing_issues)) + +result = run_query(query)['data']['repository']['pullRequest'] +issues = get_linked_issues(result) + +def close_issue(issue_number): + requests.patch(f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}", json={"state": "closed"}, headers=headers) + +if result['baseRefName'] != "develop": + print("PR not merged to develop, not closing issues") +elif result['merged']: + print(f"Closing issues: {issues}") + for issue in issues: + close_issue(issue) + print(f"Closed issue {issue}") +else: + print("PR not merged, not closing issues") \ No newline at end of file From 347804d44ad3d1aed0c9c76efe22ff8022c81d66 Mon Sep 17 00:00:00 2001 From: Alex | Kronox <39801116+Kr0nox@users.noreply.github.com> Date: Thu, 2 May 2024 17:30:10 +0200 Subject: [PATCH 2/6] Change workflow name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Timur Sağlam --- .github/workflows/closeDevIssues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/closeDevIssues.yml b/.github/workflows/closeDevIssues.yml index 63c1f5d60..706915cdb 100644 --- a/.github/workflows/closeDevIssues.yml +++ b/.github/workflows/closeDevIssues.yml @@ -1,4 +1,4 @@ -name: Close PR on develop merge +name: Close linked issue on PR merge on: pull_request: From 23bc1351cf946a5ef2a736bbaeb6f2833bcdf7d3 Mon Sep 17 00:00:00 2001 From: Alexander Vogt Date: Thu, 2 May 2024 17:38:21 +0200 Subject: [PATCH 3/6] remove left over comment --- .github/workflows/scripts/closeDevIssues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scripts/closeDevIssues.py b/.github/workflows/scripts/closeDevIssues.py index fee23ae5a..fb8a3911c 100644 --- a/.github/workflows/scripts/closeDevIssues.py +++ b/.github/workflows/scripts/closeDevIssues.py @@ -25,7 +25,7 @@ }} """ -def run_query(query): # A simple function to use requests.post to make the API call. Note the json= section. +def run_query(query): request = requests.post('https://api.github.com/graphql', json={'query': query}, headers=headers) if request.status_code == 200: return request.json() From 5583bf97294937d8cc77fb98b1f649f7f53477ec Mon Sep 17 00:00:00 2001 From: Alexander Vogt Date: Thu, 2 May 2024 20:28:05 +0200 Subject: [PATCH 4/6] give repo name and owner as argument --- .github/workflows/closeDevIssues.yml | 2 +- .github/workflows/scripts/closeDevIssues.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/closeDevIssues.yml b/.github/workflows/closeDevIssues.yml index 63c1f5d60..944f00cff 100644 --- a/.github/workflows/closeDevIssues.yml +++ b/.github/workflows/closeDevIssues.yml @@ -18,4 +18,4 @@ jobs: working-directory: .github/workflows/scripts run: | pip install requests - python closeDevIssues.py ${{ secrets.GITHUB_TOKEN }} ${{ github.event.pull_request.number }} \ No newline at end of file + python closeDevIssues.py ${{ secrets.GITHUB_TOKEN }} jplag JPlag ${{ github.event.pull_request.number }} \ No newline at end of file diff --git a/.github/workflows/scripts/closeDevIssues.py b/.github/workflows/scripts/closeDevIssues.py index fb8a3911c..741036fdc 100644 --- a/.github/workflows/scripts/closeDevIssues.py +++ b/.github/workflows/scripts/closeDevIssues.py @@ -4,9 +4,9 @@ headers = {"Authorization": f"Bearer {sys.argv[1]}"} -owner = "jplag" -repo = "JPlag" -pr_number = int(sys.argv[2]) +owner = sys.argv[2] +repo = sys.argv[3] +pr_number = int(sys.argv[4]) query = f""" {{ From f5cea2d3ffcfe49aba4d6c17f3084173c52b8273 Mon Sep 17 00:00:00 2001 From: Alexander Vogt Date: Thu, 2 May 2024 20:28:48 +0200 Subject: [PATCH 5/6] add closing comment --- .github/workflows/scripts/closeDevIssues.py | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/scripts/closeDevIssues.py b/.github/workflows/scripts/closeDevIssues.py index 741036fdc..9a0c9a81f 100644 --- a/.github/workflows/scripts/closeDevIssues.py +++ b/.github/workflows/scripts/closeDevIssues.py @@ -61,6 +61,7 @@ def get_linked_issues(result): issues = get_linked_issues(result) def close_issue(issue_number): + requests.post(f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}/comments", json={"body": f"Closed by #{pr_number}"}, headers=headers) requests.patch(f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}", json={"state": "closed"}, headers=headers) if result['baseRefName'] != "develop": From 8335d97b8715542d5198c0305236e9d34d10a5fe Mon Sep 17 00:00:00 2001 From: Alex | Kronox <39801116+Kr0nox@users.noreply.github.com> Date: Fri, 3 May 2024 09:23:41 +0200 Subject: [PATCH 6/6] Fix closed issue text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Timur Sağlam --- .github/workflows/scripts/closeDevIssues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scripts/closeDevIssues.py b/.github/workflows/scripts/closeDevIssues.py index 9a0c9a81f..aea3871ba 100644 --- a/.github/workflows/scripts/closeDevIssues.py +++ b/.github/workflows/scripts/closeDevIssues.py @@ -61,7 +61,7 @@ def get_linked_issues(result): issues = get_linked_issues(result) def close_issue(issue_number): - requests.post(f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}/comments", json={"body": f"Closed by #{pr_number}"}, headers=headers) + requests.post(f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}/comments", json={"body": f"Closed by #{pr_number}."}, headers=headers) requests.patch(f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}", json={"state": "closed"}, headers=headers) if result['baseRefName'] != "develop":