From fffda0037146f1289abb04672485bf750cbcfa75 Mon Sep 17 00:00:00 2001 From: alstr Date: Sat, 29 Aug 2020 12:30:39 +0100 Subject: [PATCH] Add option to disable closing issues --- README.md | 32 ++++++++++++++++++++----- action.yml | 7 ++++-- main.py | 70 ++++++++++++++++++++++++++++-------------------------- 3 files changed, 67 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 0686eea..1e5bfa2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This action will convert your `# TODO` comments to GitHub issues when a new commit is pushed. -The new issue will contain a link to the line in the file containing the TODO, together with a code snippet. The action performs a `GET` request to retrieve GitHub's [`languages.yml` file](https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml) file to apply highlighting to the snippet. +The new issue will contain a link to the line in the file containing the TODO, together with a code snippet and any defined labels. The action performs a `GET` request to retrieve GitHub's [`languages.yml` file](https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml) file to apply highlighting to the snippet. It will also close an issue when a `# TODO` is removed in a pushed commit. A comment will be posted with the ref of the commit that it was closed by. @@ -16,6 +16,7 @@ The `# TODO` comment is commonly used in Python, but this can be customised to w - [Examples](#examples) - [Adding TODOs](#adding-todos) - [Multiline TODOs](#multiline-todos) + - [Dynamic Labels](#dynamic-labels) - [Removing TODOs](#removing-todos) - [Updating TODOs](#updating-todos) - [Existing TODOs](#existing-todos) @@ -28,7 +29,7 @@ Create a workflow file in your .github/workflows directory as follows: ### workflow.yaml -Latest version is `v1.3-beta`. +Latest version is `v2.0`. name: "Workflow" on: ["push"] @@ -38,7 +39,7 @@ Latest version is `v1.3-beta`. steps: - uses: "actions/checkout@master" - name: "TODO to Issue" - uses: "alstr/todo-to-issue-action@v1.3-beta" + uses: "alstr/todo-to-issue-action@v2.0" with: REPO: ${{ github.repository }} BEFORE: ${{ github.event.before }} @@ -58,8 +59,9 @@ Latest version is `v1.3-beta`. | `BEFORE` | The SHA of the last pushed commit (automatically set) | | `SHA` | The SHA of the latest commit (automatically set) | | `TOKEN` | The GitHub access token to allow us to retrieve, create and update issues (automatically set) | -| `LABEL` | The label that will be used to identify TODO comments (by default this is `# TODO` for Python) | -| `COMMENT_MARKER` | The marker used to signify a line comment in your code (by default this is `#` for Python) | +| `LABEL` | The label that will be used to identify TODO comments (e.g. `# TODO` for Python) | +| `COMMENT_MARKER` | The marker used to signify a line comment in your code (e.g. `#` for Python) | +| `CLOSE_ISSUES` | Optional input that specifies whether to attempt to close an issue when a TODO is removed (default: "true") | ## Examples @@ -92,12 +94,30 @@ The extra line(s) will be posted in the body of the issue. The `COMMENT_MARKER` input must be set to the correct syntax (e.g. `#` for Python). +### Dynamic Labels + + def hello_world(): + # TODO Come up with a more imaginative greeting + # Everyone uses hello world and it's boring. + # labels: enhancement, help_wanted + print('Hello world!') + +You can specify the labels to add to your issue in the TODO body. + +The labels should be on their own line below the initial TODO declaration. + +Include the `labels:` prefix, then a list of comma-separated label titles. + +The `todo` label is automatically added to issues to help the action efficiently retrieve them in the future. + ### Removing TODOs def hello_world(): print('Hello world!') -Removing the `# TODO` comment will close the issue on push. This is still an experimental feature. +Removing the `# TODO` comment will close the issue on push. + +This is still an experimental feature. By default it is enabled, but if you want to disable it, you can set `CLOSE_ISSUES` to `false` as described in [workflow.yaml](#workflowyaml). ### Updating TODOs diff --git a/action.yml b/action.yml index c2b21be..dc89843 100644 --- a/action.yml +++ b/action.yml @@ -21,8 +21,11 @@ inputs: description: "The GitHub access token to allow us to retrieve, create and update issues (automatically set)" required: true LABEL: - description: "The label that will be used to identify TODO comments (by default this is # TODO for Python)" + description: "The label that will be used to identify TODO comments (e.g. # TODO for Python)" required: true COMMENT_MARKER: - description: "The marker used to signify a line comment in your code (by default this is # for Python)" + description: "The marker used to signify a line comment in your code (e.g. # for Python)" required: true + CLOSE_ISSUES: + description: "Optional input that specifies whether to attempt to close an issue when a TODO is removed (default: true)" + required: false diff --git a/main.py b/main.py index 7725690..78b165d 100644 --- a/main.py +++ b/main.py @@ -20,6 +20,7 @@ def main(): comment_marker = os.getenv('INPUT_COMMENT_MARKER') label = os.getenv('INPUT_LABEL') token = os.getenv('INPUT_TOKEN') + close_issues = os.getenv('INPUT_CLOSE_ISSUES', 'true') == 'true' # Load a file so we can see what language each file is written in and apply highlighting later. languages_url = 'https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml' @@ -225,41 +226,42 @@ def main(): sleep(1) print('Creating issues complete') - # Close issues for removed TODOs. - print('Start closing issues') - for i, closed_issue in enumerate(closed_issues): - title = closed_issue - matched = 0 - issue_number = None - # Compare the title of each closed issue with each issue in the issues list. - for current_issue in current_issues: - if current_issue['body'].startswith(title): - matched += 1 - # If there are multiple issues with similar titles, don't try and close any. - if matched > 1: - print(f'Skipping issue {i + 1} of {len(closed_issues)} (multiple matches)') - break - issue_number = current_issue['number'] - else: - if issue_number is None: - continue - # The titles match, so we will try and close the issue. - update_issue_url = f'{base_url}{repo}/issues/{issue_number}' - body = {'state': 'closed'} - requests.patch(update_issue_url, headers=issue_headers, data=json.dumps(body)) - - issue_comment_url = f'{base_url}{repo}/issues/{issue_number}/comments' - body = {'body': f'Closed in {sha}'} - update_issue_request = requests.post(issue_comment_url, headers=issue_headers, - data=json.dumps(body)) - print(f'Closing issue {i + 1} of {len(closed_issues)}') - if update_issue_request.status_code == 201: - print('Issue closed') + # Close issues for removed TODOs if this is enabled. + if close_issues: + print('Start closing issues') + for i, closed_issue in enumerate(closed_issues): + title = closed_issue + matched = 0 + issue_number = None + # Compare the title of each closed issue with each issue in the issues list. + for current_issue in current_issues: + if current_issue['body'].startswith(title): + matched += 1 + # If there are multiple issues with similar titles, don't try and close any. + if matched > 1: + print(f'Skipping issue {i + 1} of {len(closed_issues)} (multiple matches)') + break + issue_number = current_issue['number'] else: - print('Issue could not be closed') - # Don't update too many issues too quickly. - sleep(1) - print('Closing issues complete') + if issue_number is None: + continue + # The titles match, so we will try and close the issue. + update_issue_url = f'{base_url}{repo}/issues/{issue_number}' + body = {'state': 'closed'} + requests.patch(update_issue_url, headers=issue_headers, data=json.dumps(body)) + + issue_comment_url = f'{base_url}{repo}/issues/{issue_number}/comments' + body = {'body': f'Closed in {sha}'} + update_issue_request = requests.post(issue_comment_url, headers=issue_headers, + data=json.dumps(body)) + print(f'Closing issue {i + 1} of {len(closed_issues)}') + if update_issue_request.status_code == 201: + print('Issue closed') + else: + print('Issue could not be closed') + # Don't update too many issues too quickly. + sleep(1) + print('Closing issues complete') if __name__ == "__main__":