mirror of
https://github.com/ditkrg/todo-to-issue-action.git
synced 2026-01-22 22:06:43 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
f7cea8d10c
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
ko_fi: alstr18858
|
||||||
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -6,8 +6,10 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
steps:
|
steps:
|
||||||
- uses: "actions/checkout@v3"
|
- uses: "actions/checkout@v4"
|
||||||
- uses: "actions/setup-python@v4"
|
- uses: "actions/setup-python@v5"
|
||||||
|
with:
|
||||||
|
python-version: '3.12'
|
||||||
- name: "Install test dependencies"
|
- name: "Install test dependencies"
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
|
|||||||
4
.github/workflows/todo.yml
vendored
4
.github/workflows/todo.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
steps:
|
steps:
|
||||||
- uses: "actions/checkout@v3"
|
- uses: "actions/checkout@v4"
|
||||||
- name: "TODO to Issue"
|
- name: "TODO to Issue"
|
||||||
uses: "alstr/todo-to-issue-action@master"
|
uses: "alstr/todo-to-issue-action@master"
|
||||||
env:
|
env:
|
||||||
@ -21,5 +21,3 @@ jobs:
|
|||||||
${{ inputs.MANUAL_COMMIT_REF }}
|
${{ inputs.MANUAL_COMMIT_REF }}
|
||||||
MANUAL_BASE_REF:
|
MANUAL_BASE_REF:
|
||||||
${{ inputs.MANUAL_BASE_REF }}
|
${{ inputs.MANUAL_BASE_REF }}
|
||||||
with:
|
|
||||||
PROJECTS_SECRET: ${{ secrets.PROJECTS_SECRET }}
|
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -139,4 +139,5 @@ dmypy.json
|
|||||||
# Cython debug symbols
|
# Cython debug symbols
|
||||||
cython_debug/
|
cython_debug/
|
||||||
|
|
||||||
|
# JetBrains
|
||||||
|
.idea
|
||||||
@ -6,7 +6,7 @@ RUN pip install --target=/app requests
|
|||||||
RUN pip install --target=/app -U pip setuptools wheel
|
RUN pip install --target=/app -U pip setuptools wheel
|
||||||
RUN pip install --target=/app ruamel.yaml
|
RUN pip install --target=/app ruamel.yaml
|
||||||
|
|
||||||
FROM gcr.io/distroless/python3-debian10
|
FROM gcr.io/distroless/python3-debian12
|
||||||
COPY --from=builder /app /app
|
COPY --from=builder /app /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ENV PYTHONPATH /app
|
ENV PYTHONPATH /app
|
||||||
|
|||||||
595
README.md
595
README.md
@ -1,54 +1,87 @@
|
|||||||
# TODO to Issue Action
|
# TODO to Issue
|
||||||
|
|
||||||
This action will convert newly committed TODO comments to GitHub issues on push.
|
<p>
|
||||||
|
<a href="https://github.com/alstr/todo-to-issue-action/releases"><img alt="Latest release" src="https://img.shields.io/github/v/release/alstr/todo-to-issue-action"></a>
|
||||||
|
<a href="https://github.com/alstr/todo-to-issue-action/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22"><img alt="Issues labelled 'help wanted'" src="https://img.shields.io/github/issues/alstr/todo-to-issue-action/help%20wanted"></a>
|
||||||
|
<a href="https://github.com/alstr/todo-to-issue-action/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22"><img alt="Issues labelled 'good first issue'" src="https://img.shields.io/github/issues/alstr/todo-to-issue-action/good%20first%20issue"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
Optionally, issues can also be closed when the TODOs are removed in a future commit.
|
Action to create, update and close issues based on committed TODO comments.
|
||||||
|
|
||||||
Action supports:
|

|
||||||
|
|
||||||
* Multiple, customizable comments identifiers (FIXME, etc.),
|
Features:
|
||||||
* Configurable auto-labeling,
|
|
||||||
* Assignees,
|
* Multiple, customisable comment identifiers (`FIXME`, etc.)
|
||||||
* Milestones,
|
* Configurable auto-labeling
|
||||||
* Projects (classic).
|
* Assignees
|
||||||
|
* Milestones
|
||||||
|
* Projects
|
||||||
|
|
||||||
`todo-to-issue` works with almost any programming language.
|
`todo-to-issue` works with almost any programming language.
|
||||||
|
|
||||||
|
## What's New
|
||||||
|
|
||||||
|
v5 is the biggest release yet:
|
||||||
|
|
||||||
|
* TODO reference handling
|
||||||
|
* Issue URL insertion
|
||||||
|
* Update and comment on existing issues
|
||||||
|
* Support for v2 projects
|
||||||
|
* Assign milestones by name
|
||||||
|
* Improved issue formatting
|
||||||
|
* Link issues to PRs
|
||||||
|
|
||||||
|
See [Upgrading](#upgrading) for breaking changes.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Simply add a comment starting with TODO (or any other comment identifiers configured), followed by a colon and/or space.
|
Simply add a line or block comment starting with TODO (or any other comment identifiers configured), followed by a colon and/or space.
|
||||||
|
|
||||||
Here's an example for Python creating an issue named after the TODO _description_:
|
Here's an example for Python creating an issue named after the TODO _description_:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def hello_world():
|
def hello_world():
|
||||||
# TODO Come up with a more imaginative greeting
|
# TODO: Come up with a more imaginative greeting
|
||||||
print('Hello world!')
|
print('Hello world!')
|
||||||
```
|
```
|
||||||
|
|
||||||
_Multiline_ TODOs are supported, with additional lines inserted into the issue body:
|
_Multiline_ TODOs are supported, with additional lines inserted into the issue body:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def hello_world():
|
def hello_world():
|
||||||
# TODO: Come up with a more imaginative greeting
|
# TODO: Come up with a more imaginative greeting
|
||||||
# Everyone uses hello world and it's boring.
|
# Everyone uses hello world and it's boring.
|
||||||
print('Hello world!')
|
print('Hello world!')
|
||||||
```
|
```
|
||||||
|
|
||||||
As per the [Google Style Guide](https://google.github.io/styleguide/cppguide.html#TODO_Comments), you can provide a _reference_ after the TODO identifier. This will be included in the issue title for searchability.
|
As per the [Google Style Guide](https://google.github.io/styleguide/cppguide.html#TODO_Comments), you can provide a _reference_ after the TODO identifier:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def hello_world():
|
def hello_world():
|
||||||
# TODO(alstr) Come up with a more imaginative greeting
|
# TODO(@alstr): Come up with a more imaginative greeting
|
||||||
# Everyone uses hello world and it's boring.
|
# This will assign the issue to alstr.
|
||||||
print('Hello world!')
|
print('Hello world!')
|
||||||
|
|
||||||
|
# TODO(!urgent): This is wrong
|
||||||
|
# This will add an 'urgent' label.
|
||||||
|
assert 1 + 1 == 3
|
||||||
|
|
||||||
|
# TODO(#99): We need error handling here
|
||||||
|
# This will add the comment to the existing issue 99.
|
||||||
|
greeting_time = datetime.fromisoformat(date_string)
|
||||||
|
|
||||||
|
# TODO(language): Localise this string
|
||||||
|
# This will prepend the reference to the issue title
|
||||||
|
dialogue = "TODO or not TODO, that is the question."
|
||||||
```
|
```
|
||||||
|
|
||||||
Don't include parentheses within the reference itself.
|
Only one reference can be provided. Should you wish to further configure the issue, you can do so via
|
||||||
|
[TODO Options](#todo-options).
|
||||||
|
|
||||||
## TODO Options
|
## TODO Options
|
||||||
|
|
||||||
A range of options can also be provided to apply to the new issue.
|
A range of options can also be provided to apply to the issue, in addition to any reference supplied.
|
||||||
|
|
||||||
Options follow the `name: value` syntax.
|
Options follow the `name: value` syntax.
|
||||||
Unless otherwise specified, options should be on their own line, below the initial TODO declaration and 'body'.
|
Unless otherwise specified, options should be on their own line, below the initial TODO declaration and 'body'.
|
||||||
@ -58,11 +91,11 @@ Unless otherwise specified, options should be on their own line, below the initi
|
|||||||
Comma-separated list of usernames to assign to the issue:
|
Comma-separated list of usernames to assign to the issue:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def hello_world():
|
def hello_world():
|
||||||
# TODO(alstr): Come up with a more imaginative greeting
|
# TODO: Come up with a more imaginative greeting
|
||||||
# Everyone uses hello world and it's boring.
|
# Everyone uses hello world and it's boring.
|
||||||
# assignees: alstr, bouteillerAlan, hbjydev
|
# assignees: alstr, bouteillerAlan, hbjydev
|
||||||
print('Hello world!')
|
print('Hello world!')
|
||||||
```
|
```
|
||||||
|
|
||||||
### Labels
|
### Labels
|
||||||
@ -70,171 +103,315 @@ Comma-separated list of usernames to assign to the issue:
|
|||||||
Comma-separated list of labels to add to the issue:
|
Comma-separated list of labels to add to the issue:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def hello_world():
|
def hello_world():
|
||||||
# TODO(alstr): Come up with a more imaginative greeting
|
# TODO: Come up with a more imaginative greeting
|
||||||
# Everyone uses hello world and it's boring.
|
# Everyone uses hello world and it's boring.
|
||||||
# labels: enhancement, help wanted
|
# labels: enhancement, help wanted
|
||||||
print('Hello world!')
|
print('Hello world!')
|
||||||
```
|
```
|
||||||
|
|
||||||
If any of the labels do not already exist, they will be created.
|
If any of the labels do not already exist, they will be created.
|
||||||
|
|
||||||
The `todo` label is automatically added to issues to help the action efficiently retrieve them in the future.
|
|
||||||
|
|
||||||
### Milestone
|
### Milestone
|
||||||
|
|
||||||
Milestone `ID` to assign to the issue:
|
Milestone name to assign to the issue:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def hello_world():
|
def hello_world():
|
||||||
# TODO(alstr): Come up with a more imaginative greeting
|
# TODO: Come up with a more imaginative greeting
|
||||||
# Everyone uses hello world and it's boring.
|
# Everyone uses hello world and it's boring.
|
||||||
# milestone: 1
|
# milestone: v3.0
|
||||||
print('Hello world!')
|
print('Hello world!')
|
||||||
```
|
```
|
||||||
|
|
||||||
Only a single milestone can be specified and it must already exist.
|
Only a single milestone can be specified. If the milestone does not exist, it will be created.
|
||||||
|
|
||||||
### Projects
|
|
||||||
|
|
||||||
_Please note, the action currently only supports classic user and organisation projects, and not 'new' projects._
|
|
||||||
|
|
||||||
With some additional setup, you can assign the created issues a status (column) within user or organisation projects.
|
|
||||||
|
|
||||||
By default, the action cannot access your projects. To enable it, you must:
|
|
||||||
|
|
||||||
* [Create a Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token),
|
|
||||||
* [Create an encrypted secret in your repo settings](https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository), with the value set to the Personal Access Token,
|
|
||||||
* Assign the secret in the workflow file like `PROJECTS_SECRET: ${{ secrets.PROJECTS_SECRET }}`. _Do not enter the raw secret_.
|
|
||||||
|
|
||||||
Projects are identified by their `full project name and issue status` (column) reference with the `<user or org name>/project name/status name` syntax.
|
|
||||||
|
|
||||||
* To assign to a _user project_, use the `user projects:` option.
|
|
||||||
* To assign to an _organisation project_, use `org projects:` option.
|
|
||||||
|
|
||||||
```python
|
|
||||||
def hello_world():
|
|
||||||
# TODO Come up with a more imaginative greeting
|
|
||||||
# Everyone uses hello world and it's boring.
|
|
||||||
# user projects: alstr/Test User Project/To Do
|
|
||||||
# org projects: alstrorg/Test Org Project/To Do
|
|
||||||
print('Hello world!')
|
|
||||||
```
|
|
||||||
|
|
||||||
You can assign issues to multiple projects separating them with commas, i.e. `user projects: alstr/Test User Project 1/To Do, alstr/Test User Project 2/Tasks`.
|
|
||||||
|
|
||||||
You can also specify `default projects` in the same way by defining `USER_PROJECTS` or `ORG_PROJECTS` in your workflow file.
|
|
||||||
These will be applied automatically to every issue, but will be overrode by any specified within the TODO.
|
|
||||||
|
|
||||||
## Supported Languages
|
## Supported Languages
|
||||||
|
|
||||||
- ABAP
|
- ABAP
|
||||||
- ABAP CDS
|
- ABAP CDS
|
||||||
- AutoHotkey
|
- Agda
|
||||||
- C
|
- AutoHotkey
|
||||||
- C++
|
- C
|
||||||
- C#
|
- C++
|
||||||
- CSS
|
- C#
|
||||||
- Crystal
|
- CSS
|
||||||
- Clojure
|
- Crystal
|
||||||
- Dart
|
- Clojure
|
||||||
- Elixir
|
- Cuda
|
||||||
- GDScript
|
- Dart
|
||||||
- Go
|
- Elixir
|
||||||
- Handlebars
|
- GDScript
|
||||||
- HCL
|
- Go
|
||||||
- Haskell
|
- Handlebars
|
||||||
- HTML
|
- HCL
|
||||||
- Java
|
- Haskell
|
||||||
- JavaScript
|
- HTML
|
||||||
- JSON5
|
- Java
|
||||||
- JSON with Comments
|
- JavaScript
|
||||||
- Julia
|
- JSON5
|
||||||
- Kotlin
|
- JSON with Comments
|
||||||
- Less
|
- Julia
|
||||||
- Markdown
|
- Kotlin
|
||||||
- Nix
|
- Less
|
||||||
- Objective-C
|
- Liquid
|
||||||
- Org Mode
|
- Makefile
|
||||||
- PHP
|
- Markdown
|
||||||
- Python
|
- Nix
|
||||||
- R
|
- Objective-C
|
||||||
- Razor
|
- Org Mode
|
||||||
- RMarkdown
|
- PHP
|
||||||
- Ruby
|
- Python
|
||||||
- Rust
|
- PureScript
|
||||||
- Sass
|
- R
|
||||||
- Scala
|
- Razor
|
||||||
- SCSS
|
- RMarkdown
|
||||||
- Shell
|
- Ruby
|
||||||
- SQL
|
- Rust
|
||||||
- Starlark
|
- Sass
|
||||||
- Swift
|
- Scala
|
||||||
- TeX
|
- SCSS
|
||||||
- TSX
|
- Shell
|
||||||
- Twig
|
- SQL
|
||||||
- TypeScript
|
- Starlark
|
||||||
- Visual Basic for Applications (VBA)
|
- Swift
|
||||||
- Vue
|
- TeX
|
||||||
- XML
|
- TSX
|
||||||
- YAML
|
- Twig
|
||||||
|
- TypeScript
|
||||||
|
- Visual Basic for Applications (VBA)
|
||||||
|
- Vue
|
||||||
|
- XML
|
||||||
|
- YAML
|
||||||
|
|
||||||
New languages can easily be added to the `syntax.json` file, used by the action to identify TODO comments.
|
New languages can easily be added to the `syntax.json` file used by the action to identify TODO comments.
|
||||||
|
|
||||||
When adding languages, follow the structure of existing entries, and use the language name defined by GitHub in [`languages.yml`](https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml).
|
PRs adding new languages are welcome and appreciated. See [Contributing](#contributing--issues).
|
||||||
|
|
||||||
Of course, PRs adding new languages are welcome and appreciated. Please add a test for your language in order for your PR to be accepted. See [Contributing](#contributing--issues).
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
Create a `workflow.yml` file in your `.github/workflows` directory like:
|
In the repo where you want the action to run, go to `Settings -> Actions (General) -> Workflow permissions` and enable
|
||||||
|
"Read and write permissions".
|
||||||
|
|
||||||
|
Next, create a `workflow.yml` file in your `.github/workflows` directory:
|
||||||
|
|
||||||
```yml
|
```yml
|
||||||
name: "Run TODO to Issue"
|
name: "Run TODO to Issue"
|
||||||
on: ["push"]
|
on: [ "push" ]
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
steps:
|
steps:
|
||||||
- uses: "actions/checkout@v3"
|
- uses: "actions/checkout@v4"
|
||||||
- name: "TODO to Issue"
|
- name: "TODO to Issue"
|
||||||
uses: "alstr/todo-to-issue-action@v4"
|
uses: "alstr/todo-to-issue-action@v5"
|
||||||
```
|
```
|
||||||
|
|
||||||
See [Github's workflow syntax](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions) for further details on this file.
|
### URL Insertion
|
||||||
|
|
||||||
The workflow file takes the following optional inputs:
|
The action can insert the URL for a created issue back into the associated TODO.
|
||||||
|
|
||||||
| Input | Required | Description |
|
This allows for tighter integration between issues and TODOs, enables updating issues by editing TODOs, and improves the
|
||||||
| ---------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
accuracy of the action when closing TODOs.
|
||||||
| `CLOSE_ISSUES` | No | Optional boolean input that specifies whether to attempt to close an issue when a TODO is removed. Default: `true`. |
|
|
||||||
| `AUTO_P` | No | Optional boolean input that specifies whether to format each line in multiline TODOs as a new paragraph. Default: `true`. |
|
|
||||||
| `IGNORE` | No | Optional string input that provides comma-delimited regular expressions that match files in the repo that we should not scan for TODOs. By default, we will scan all files. |
|
|
||||||
| `AUTO_ASSIGN` | No | Optional boolean input that specifies whether to assign the newly created issue to the user who triggered the action. If users are manually assigned to an issue, this setting is ignored. Default: `false`. |
|
|
||||||
| `ISSUE_TEMPLATE` | No | You can override the default issue template by providing your own here. Markdown is supported, and you can inject the issue title, body, code URL and snippet. Example: `"This is my issue title: **{{ title }}**\n\nThis is my issue body: **{{ body }}**\n\nThis is my code URL: **{{ url }}**\n\nThis is my snippet:\n\n{{ snippet }}"` |
|
|
||||||
| `IDENTIFIERS` | No | A list of dictionaries specifying the identifiers for the action to recognise. `TODO` is the default, but you can override this here, and specify default labels to be applied when creating issues for each identifier. JSON string must be valid with double quoted keys/values and itself single-quoted (or double-quoted and escaped). Example: `'[{"name": "TODO", "labels": ["help wanted"]}, {"name": "FIXME", "labels": ["bug"]}]'` (`labels` should be an empty list if no default labels are wanted) |
|
|
||||||
|
|
||||||
These can be specified using `with` parameter in the workflow file, as below:
|
A new feature in v5, it is disabled by default. To enable URL insertion, some extra config is required:
|
||||||
|
|
||||||
```yml
|
```yml
|
||||||
name: "Run TODO to Issue"
|
name: "Run TODO to Issue"
|
||||||
on: ["push"]
|
on: [ "push" ]
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
steps:
|
steps:
|
||||||
- uses: "actions/checkout@v3"
|
- uses: "actions/checkout@v4"
|
||||||
- name: "TODO to Issue"
|
- name: "TODO to Issue"
|
||||||
uses: "alstr/todo-to-issue-action@v4"
|
uses: "alstr/todo-to-issue-action@v5"
|
||||||
with:
|
with:
|
||||||
AUTO_ASSIGN: true
|
INSERT_ISSUE_URLS: "true"
|
||||||
|
- name: Set Git user
|
||||||
|
run: |
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
- name: Commit and Push Changes
|
||||||
|
run: |
|
||||||
|
git add .
|
||||||
|
git commit -m "Automatically added GitHub issue links to TODOs"
|
||||||
|
git push origin main
|
||||||
```
|
```
|
||||||
|
|
||||||
### Considerations
|
You will probably also want to use the setting `CLOSE_ISSUES: "true"`, to allow issues to be closed when a TODO is
|
||||||
|
removed.
|
||||||
|
|
||||||
- TODOs are found by analysing the difference between the new commit and its previous one (i.e., the diff). That means that if this action is implemented during development, any existing TODOs will not be detected. For them to be detected, you would have to remove them, commit, put them back, and commit again, or [run the action manually](#running-the-action-manually).
|
Please note, URL insertion works best with line comments, as it has to insert a line into the file. If using block
|
||||||
- Should you change the TODO text, this will currently create a new issue.
|
comments, you should put the start and end tags on their own lines. This may be improved in the future.
|
||||||
- Closing TODOs is still somewhat experimental.
|
|
||||||
|
This feature is not perfect. Please make sure you're comfortable with that before enabling.
|
||||||
|
|
||||||
|
### Projects
|
||||||
|
|
||||||
|
You can configure the action to add newly created issues to a specified v2 project (i.e., not a classic project).
|
||||||
|
|
||||||
|
The action does not have sufficient permissions by default, so you will need to create a new Personal Access Token with
|
||||||
|
the `repo` and `project` scopes.
|
||||||
|
|
||||||
|
Then, in your repo, go to `Settings -> Secrets and variables (Actions) -> Secrets`, and enter the value as a new
|
||||||
|
repository secret with the name `PROJECTS_SECRET`.
|
||||||
|
|
||||||
|
Finally, add the following to the workflow file, under `with`:
|
||||||
|
```
|
||||||
|
PROJECT: "user/alstr/test"
|
||||||
|
PROJECTS_SECRET: "${{ secrets.PROJECTS_SECRET }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `PROJECT` is a string of the form `account_type/owner/project_name`. Valid values for `account_type` are `user` or `organization`.
|
||||||
|
|
||||||
|
All newly created issues will then be automatically added to the specified project.
|
||||||
|
|
||||||
|
### Custom Languages
|
||||||
|
|
||||||
|
If you want to add language definitions that are not currently supported, or overwrite existing ones, you can do so
|
||||||
|
using the `LANGUAGES` input.
|
||||||
|
|
||||||
|
Just create a file that contains an array of languages, each with the following properties:
|
||||||
|
|
||||||
|
| Property | Description |
|
||||||
|
|------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| language | The unique name of the language |
|
||||||
|
| extensions | A list of file extensions for the custom language |
|
||||||
|
| markers | A list of objects (see example below) to declare the comment markers. Make sure to escape all special Markdown characters with a double backslash. |
|
||||||
|
|
||||||
|
For example, here is a language declaration file for Java:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"language": "Java",
|
||||||
|
"extensions": [
|
||||||
|
".java"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"pattern": "//"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"pattern": {
|
||||||
|
"start": "/\\*",
|
||||||
|
"end": "\\*/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, add the file to the `LANGUAGES` property in your workflow file.
|
||||||
|
|
||||||
|
**Using a Local File:**
|
||||||
|
|
||||||
|
`LANGUAGES: "path/to/my/file.json"`
|
||||||
|
|
||||||
|
**Using a Remote File:**
|
||||||
|
|
||||||
|
`LANGUAGES: "https://myserver.com/path/to/my/file.json"`
|
||||||
|
|
||||||
|
Multiple paths can be provided by entering a comma-delimited string.
|
||||||
|
|
||||||
|
### All Settings
|
||||||
|
|
||||||
|
The workflow file takes the following optional inputs, specified under the `with` parameter:
|
||||||
|
|
||||||
|
#### AUTO_ASSIGN
|
||||||
|
|
||||||
|
Automatically assign new issues to the user who triggered the action.
|
||||||
|
|
||||||
|
Default: `False`
|
||||||
|
|
||||||
|
#### AUTO_P
|
||||||
|
|
||||||
|
For multiline TODOs, format each line as a new paragraph when creating the issue.
|
||||||
|
|
||||||
|
Default: `True`
|
||||||
|
|
||||||
|
#### CLOSE_ISSUES
|
||||||
|
|
||||||
|
Whether to close an issue when a TODO is removed. If enabling this, also enabling `INSERT_ISSUE_URLS` is recommended
|
||||||
|
for improved accuracy.
|
||||||
|
|
||||||
|
Default: `False`
|
||||||
|
|
||||||
|
#### ESCAPE
|
||||||
|
|
||||||
|
Escape all special Markdown characters.
|
||||||
|
|
||||||
|
Default: `True`
|
||||||
|
|
||||||
|
#### GITHUB_URL
|
||||||
|
|
||||||
|
Base URL of GitHub API. In most cases you will not need to change this.
|
||||||
|
|
||||||
|
Default: `${{ github.api_url }}`
|
||||||
|
|
||||||
|
#### IDENTIFIERS
|
||||||
|
|
||||||
|
List of custom identifier dictionaries. Use this to add support for `FIXME` and other identifiers, and assign default
|
||||||
|
labels.
|
||||||
|
|
||||||
|
Default: `[{"name": "TODO", "labels": []}]`
|
||||||
|
|
||||||
|
#### INSERT_ISSUE_URLS
|
||||||
|
|
||||||
|
Whether to insert the URL for a new issue back into the associated TODO.
|
||||||
|
|
||||||
|
See [URL Insertion](#url-insertion).
|
||||||
|
|
||||||
|
Default: `False`
|
||||||
|
|
||||||
|
#### IGNORE
|
||||||
|
|
||||||
|
A collection of comma-delimited regular expressions that match files that should be ignored when searching for TODOs.
|
||||||
|
|
||||||
|
#### ISSUE_TEMPLATE
|
||||||
|
|
||||||
|
Custom template used to format new issues. This is a string that accepts Markdown, linebreaks and the following
|
||||||
|
placeholders:
|
||||||
|
|
||||||
|
* `{{ title }}`: issue title
|
||||||
|
* `{{ body }}`: issue body
|
||||||
|
* `{{ url }}`: URL to the line
|
||||||
|
* `{{ snippet }}`: code snippet of the relevant section
|
||||||
|
|
||||||
|
If not specified the standard template is used, containing the issue body (if a multiline TODO), URL and snippet.
|
||||||
|
|
||||||
|
#### LANGUAGES
|
||||||
|
|
||||||
|
A collection of comma-delimited URLs or local paths (starting from the current working directory of the action)
|
||||||
|
for custom languages.
|
||||||
|
|
||||||
|
See [Custom Languages](#custom-languages).
|
||||||
|
|
||||||
|
#### NO_STANDARD
|
||||||
|
|
||||||
|
Exclude loading the default `syntax.json` and `languages.yml` files.
|
||||||
|
|
||||||
|
Default: `False`
|
||||||
|
|
||||||
|
#### PROJECT
|
||||||
|
|
||||||
|
A string specifying a v2 project where issues should be added.
|
||||||
|
|
||||||
|
Use the format `account_type/owner/project_name`. Valid values for `account_type` are `user` or `organization`.
|
||||||
|
|
||||||
|
See [Projects](#projects).
|
||||||
|
|
||||||
|
#### PROJECTS_SECRET
|
||||||
|
|
||||||
|
A Personal Access Token with the `repo` and `project` scopes, required for enabling support for projects.
|
||||||
|
|
||||||
|
It should be of the form `${{ secrets.PROJECTS_SECRET }}`. Do not enter actual secret.
|
||||||
|
|
||||||
|
See [Projects](#projects).
|
||||||
|
|
||||||
## Running the action manually
|
## Running the action manually
|
||||||
|
|
||||||
@ -245,51 +422,70 @@ You can run the action manually by adding support for the `workflow_dispatch` ev
|
|||||||
```yaml
|
```yaml
|
||||||
name: "Run TODO to Issue"
|
name: "Run TODO to Issue"
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
MANUAL_COMMIT_REF:
|
MANUAL_COMMIT_REF:
|
||||||
description: "The SHA of the commit to get the diff for"
|
description: "The SHA of the commit to get the diff for"
|
||||||
required: true
|
required: true
|
||||||
MANUAL_BASE_REF:
|
MANUAL_BASE_REF:
|
||||||
description: "By default, the commit entered above is compared to the one directly before it; to go back further, enter an earlier SHA here"
|
description: "By default, the commit entered above is compared to the one directly before it; to go back further, enter an earlier SHA here"
|
||||||
required: false
|
required: false
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
steps:
|
steps:
|
||||||
- uses: "actions/checkout@v3"
|
- uses: "actions/checkout@v4"
|
||||||
- name: "TODO to Issue"
|
- name: "TODO to Issue"
|
||||||
uses: "alstr/todo-to-issue-action@master"
|
uses: "alstr/todo-to-issue-action@v5"
|
||||||
env:
|
env:
|
||||||
MANUAL_COMMIT_REF: ${{ inputs.MANUAL_COMMIT_REF }}
|
MANUAL_COMMIT_REF: ${{ inputs.MANUAL_COMMIT_REF }}
|
||||||
MANUAL_BASE_REF: ${{ inputs.MANUAL_BASE_REF }}
|
MANUAL_BASE_REF: ${{ inputs.MANUAL_BASE_REF }}
|
||||||
```
|
```
|
||||||
|
|
||||||
Head to the Actions section of your repo, select the workflow and then 'Run workflow'.
|
Head to the actions section of your repo, select the workflow and then 'Run workflow'.
|
||||||
|
|
||||||
You can run the workflow for a single commit by entering the commit SHA in the first box. In this case, the action will compare the commit to the one directly before it.
|
You can run the workflow for a single commit by entering the commit SHA in the first box. In this case, the action will
|
||||||
|
compare the commit to the one directly before it.
|
||||||
|
|
||||||
You can also compare a broader range of commits. For that, also enter the 'from'/base commit SHA in the second box.
|
You can also compare a broader range of commits. For that, also enter the 'from' or base commit SHA in the second box.
|
||||||
|
|
||||||
|
## Upgrading
|
||||||
|
|
||||||
|
If upgrading from v4 to v5, please note the following:
|
||||||
|
|
||||||
|
* Milestones are now specified by name, not ID.
|
||||||
|
* Support for classic projects has been removed, together with the `user_projects:` and `org_projects:` options,
|
||||||
|
and `USER_PROJECTS` and `ORG_PROJECTS` workflow settings.
|
||||||
|
* The `todo` label is no longer set on created issues.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### No issues have been created
|
### No issues have been created
|
||||||
|
|
||||||
- Make sure your file language is in `syntax.json`.
|
- Make sure your file language is in `syntax.json`.
|
||||||
- The action will not recognise existing TODOs that have already been pushed, unless you [run the action manually](#running-the-action-manually).
|
- TODOs are found by analysing the difference between the new commit and its previous one (i.e., the diff). This means
|
||||||
- If a similar TODO appears in the diff as both an addition and deletion, it is assumed to have been moved, so is ignored.
|
that if this action is implemented during development, any existing TODOs will not be detected. For them to be
|
||||||
- If your workflow is executed but no issue is generated, check your repo permissions by navigating to `Settings -> Actions (General) -> Workflow permissions` and enable "Read and write permissions".
|
detected, you would have to re-commit them, or [run the action manually](#running-the-action-manually).
|
||||||
|
- If your workflow is executed but no issue is generated, check your repo permissions by navigating to
|
||||||
|
`Settings -> Actions (General) -> Workflow permissions` and enable "Read and write permissions".
|
||||||
|
|
||||||
### Multiple issues have been created
|
### Multiple issues have been created
|
||||||
|
|
||||||
Issues are created whenever the action runs and finds a newly added TODO in the diff. Rebasing may cause a TODO to show up in a diff multiple times. This is an acknowledged issue, but you may have some luck by adjusting your workflow file.
|
Issues are created whenever the action runs and finds a newly added TODO in the diff. This can lead to duplicate
|
||||||
|
issues if a diff is processed multiple times.
|
||||||
|
|
||||||
|
Enabling [URL Insertion](#url-insertion) can help with the detection of existing issues.
|
||||||
|
|
||||||
## Contributing & Issues
|
## Contributing & Issues
|
||||||
|
|
||||||
If you do encounter any problems, please file an issue or submit a PR. Everyone is welcome and encouraged to contribute.
|
If encounter any problems, please file an issue or submit a PR. Everyone is welcome and encouraged to contribute.
|
||||||
|
|
||||||
**If submitting a request to add a new language, please ensure you add the appropriate tests covering your language. In the interests of stability, PRs without tests cannot be considered.**
|
**If submitting a request to add a new language, please ensure you add the appropriate tests covering your language.
|
||||||
|
In the interests of stability, PRs without tests cannot be considered.**
|
||||||
|
|
||||||
|
When adding languages, follow the structure of existing entries, and use the language name defined by
|
||||||
|
[GitHub's `languages.yml`](https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml) file.
|
||||||
|
|
||||||
## Running tests locally
|
## Running tests locally
|
||||||
|
|
||||||
@ -301,18 +497,25 @@ python -m unittest
|
|||||||
|
|
||||||
## Customising
|
## Customising
|
||||||
|
|
||||||
If you want to fork this action to customise its behaviour, there are a few steps you should take to ensure your changes run:
|
If you want to fork this action to customise its behaviour, there are a few steps you should take to ensure your changes
|
||||||
|
run:
|
||||||
|
|
||||||
- In `workflow.yml`, set `uses: ` to your action.
|
- In `workflow.yml`, set `uses: ` to your action.
|
||||||
- In `action.yml`, set `image: ` to `Dockerfile`, rather than the prebuilt image.
|
- In `action.yml`, set `image: ` to `Dockerfile`, rather than the prebuilt image.
|
||||||
- If customising `syntax.json`, you will want to update the URL in `main.py` to target your version of the file.
|
- If customising `syntax.json`, you will want to update the URL in `main.py` to target your version of the file.
|
||||||
|
|
||||||
## Thanks
|
## Thanks
|
||||||
|
|
||||||
The action was developed for the GitHub Hackathon. Whilst every effort is made to ensure it works, it comes with no guarantee.
|
The action was originally developed for the GitHub Hackathon in 2020. Whilst every effort is made to ensure it works,
|
||||||
|
it comes with no guarantee.
|
||||||
|
|
||||||
Thanks to Jacob Tomlinson for [his handy overview of GitHub Actions](https://www.jacobtomlinson.co.uk/posts/2019/creating-github-actions-in-python/).
|
Thanks to GitHub's [linguist repo](https://github.com/github/linguist/) for the [`languages.yml`](https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml) file used by the app to look up file extensions
|
||||||
|
and determine the correct highlighting to apply to code snippets.
|
||||||
Thanks to GitHub's [linguist repo](https://github.com/github/linguist/) for the [`languages.yml`](https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml) file used by the app to look up file extensions and determine the correct highlighting to apply to code snippets.
|
|
||||||
|
|
||||||
Thanks to all those who have [contributed](https://github.com/alstr/todo-to-issue-action/graphs/contributors) to the further development of this action.
|
Thanks to all those who have [contributed](https://github.com/alstr/todo-to-issue-action/graphs/contributors) to the further development of this action.
|
||||||
|
|
||||||
|
## Supporting the Project
|
||||||
|
|
||||||
|
If you’ve found this action helpful and it has made your workflow easier, please consider buying a coffee to help keep it going. Thank you in advance!
|
||||||
|
|
||||||
|
[](https://ko-fi.com/alstr18858)
|
||||||
|
|||||||
40
action.yml
40
action.yml
@ -3,7 +3,7 @@ description: 'Converts IDE TODO comments to GitHub issues'
|
|||||||
author: 'Alastair Mooney'
|
author: 'Alastair Mooney'
|
||||||
runs:
|
runs:
|
||||||
using: 'docker'
|
using: 'docker'
|
||||||
image: 'docker://ghcr.io/alstr/todo-to-issue-action:v4.10.1'
|
image: 'docker://ghcr.io/alstr/todo-to-issue-action:v5.0'
|
||||||
branding:
|
branding:
|
||||||
icon: 'check-square'
|
icon: 'check-square'
|
||||||
color: 'orange'
|
color: 'orange'
|
||||||
@ -17,7 +17,7 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: '${{ github.event.before || github.base_ref }}'
|
default: '${{ github.event.before || github.base_ref }}'
|
||||||
COMMITS:
|
COMMITS:
|
||||||
description: 'An array of commit objects describing the pushed commits'
|
description: 'An array of commit objects describing the pushed commits (automatically set)'
|
||||||
required: false
|
required: false
|
||||||
default: '${{ toJSON(github.event.commits) }}'
|
default: '${{ toJSON(github.event.commits) }}'
|
||||||
DIFF_URL:
|
DIFF_URL:
|
||||||
@ -32,29 +32,20 @@ inputs:
|
|||||||
description: 'The GitHub access token to allow us to retrieve, create and update issues (automatically set)'
|
description: 'The GitHub access token to allow us to retrieve, create and update issues (automatically set)'
|
||||||
required: false
|
required: false
|
||||||
default: ${{ github.token }}
|
default: ${{ github.token }}
|
||||||
LABEL:
|
|
||||||
description: 'The label that will be used to identify TODO comments (deprecated)'
|
|
||||||
required: false
|
|
||||||
COMMENT_MARKER:
|
|
||||||
description: 'The marker used to signify a line comment in your code (deprecated)'
|
|
||||||
required: false
|
|
||||||
CLOSE_ISSUES:
|
CLOSE_ISSUES:
|
||||||
description: 'Optional input that specifies whether to attempt to close an issue when a TODO is removed'
|
description: 'Optional input specifying whether to attempt to close an issue when a TODO is removed'
|
||||||
required: false
|
required: false
|
||||||
default: true
|
default: true
|
||||||
AUTO_P:
|
AUTO_P:
|
||||||
description: 'For multiline TODOs, format each line as a new paragraph when creating the issue'
|
description: 'For multiline TODOs, format each line as a new paragraph when creating the issue'
|
||||||
required: false
|
required: false
|
||||||
default: true
|
default: true
|
||||||
|
PROJECT:
|
||||||
|
description: "User or organization project to link issues to, format 'project_type/owner/project_name'"
|
||||||
|
required: false
|
||||||
PROJECTS_SECRET:
|
PROJECTS_SECRET:
|
||||||
description: 'Encrypted secret corresponding to your personal access token (do not enter the actual secret)'
|
description: 'Encrypted secret corresponding to your personal access token (do not enter the actual secret)'
|
||||||
required: false
|
required: false
|
||||||
USER_PROJECTS:
|
|
||||||
description: 'Default user projects'
|
|
||||||
required: false
|
|
||||||
ORG_PROJECTS:
|
|
||||||
description: 'Default organisation projects'
|
|
||||||
required: false
|
|
||||||
IGNORE:
|
IGNORE:
|
||||||
description: 'A collection of comma-delimited regular expression that matches files that should be ignored when searching for TODOs'
|
description: 'A collection of comma-delimited regular expression that matches files that should be ignored when searching for TODOs'
|
||||||
required: false
|
required: false
|
||||||
@ -63,7 +54,7 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
ACTOR:
|
ACTOR:
|
||||||
description: 'The username of the person who triggered the action'
|
description: 'The username of the person who triggered the action (automatically set)'
|
||||||
required: false
|
required: false
|
||||||
default: '${{ github.actor }}'
|
default: '${{ github.actor }}'
|
||||||
ISSUE_TEMPLATE:
|
ISSUE_TEMPLATE:
|
||||||
@ -75,4 +66,19 @@ inputs:
|
|||||||
GITHUB_URL:
|
GITHUB_URL:
|
||||||
description: 'Base url of GitHub API'
|
description: 'Base url of GitHub API'
|
||||||
required: false
|
required: false
|
||||||
default: ${{ github.api_url }}
|
default: ${{ github.api_url }}
|
||||||
|
ESCAPE:
|
||||||
|
description: 'Escape all special Markdown characters'
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
LANGUAGES:
|
||||||
|
description: 'A collection of comma-delimited URLs or local paths for custom language files'
|
||||||
|
required: false
|
||||||
|
NO_STANDARD:
|
||||||
|
description: "Exclude loading the default 'syntax.json' and 'languages.yml' files from the repository"
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
INSERT_ISSUE_URLS:
|
||||||
|
description: 'Whether the action should insert the URL for a newly-created issue into the associated TODO comment'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
BIN
diagram.png
Normal file
BIN
diagram.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 301 KiB |
@ -1,15 +1,3 @@
|
|||||||
attrs==22.1.0
|
requests==2.32.3
|
||||||
certifi==2022.12.07
|
ruamel.yaml==0.18.6
|
||||||
charset-normalizer==2.0.7
|
pytest==8.3.3
|
||||||
exceptiongroup==1.0.0
|
|
||||||
idna==3.3
|
|
||||||
iniconfig==1.1.1
|
|
||||||
packaging==21.3
|
|
||||||
pluggy==1.0.0
|
|
||||||
pyparsing==3.0.9
|
|
||||||
pytest==7.2.0
|
|
||||||
requests==2.26.0
|
|
||||||
ruamel.yaml==0.17.17
|
|
||||||
ruamel.yaml.clib==0.2.6
|
|
||||||
tomli==2.0.1
|
|
||||||
urllib3==1.26.7
|
|
||||||
96
syntax.json
96
syntax.json
@ -242,6 +242,13 @@
|
|||||||
"start": "/\\*",
|
"start": "/\\*",
|
||||||
"end": "\\*/"
|
"end": "\\*/"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"pattern": {
|
||||||
|
"start": "{/\\*",
|
||||||
|
"end": "\\*/}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -357,6 +364,22 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"language": "PureScript",
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"pattern": "--"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"pattern": {
|
||||||
|
"start": "{-",
|
||||||
|
"end": "-}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"language": "Haskell",
|
"language": "Haskell",
|
||||||
"markers": [
|
"markers": [
|
||||||
@ -429,6 +452,22 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"language": "MDX",
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"pattern": {
|
||||||
|
"start": "{/\\*",
|
||||||
|
"end": "\\*/}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"pattern": "- \\[ \\]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"language": "RMarkdown",
|
"language": "RMarkdown",
|
||||||
"markers": [
|
"markers": [
|
||||||
@ -741,5 +780,62 @@
|
|||||||
"pattern": "'"
|
"pattern": "'"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "Cuda",
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"pattern": "//"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"pattern": {
|
||||||
|
"start": "/\\*",
|
||||||
|
"end": "\\*/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "Makefile",
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"pattern": "#"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "Liquid",
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"pattern": "#"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"pattern": {
|
||||||
|
"start": "{% comment %}",
|
||||||
|
"end": "{% endcomment %}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "Agda",
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"pattern": "--"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"pattern": {
|
||||||
|
"start": "{-",
|
||||||
|
"end": "-}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
40
tests/custom_languages.json
Normal file
40
tests/custom_languages.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"language": "ILS",
|
||||||
|
"extensions": [
|
||||||
|
".ils"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"pattern": "//"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"pattern": {
|
||||||
|
"start": "/\\*",
|
||||||
|
"end": "\\*/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "Java",
|
||||||
|
"extensions": [
|
||||||
|
".java2"
|
||||||
|
],
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"pattern": "////"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"pattern": {
|
||||||
|
"start": "+=",
|
||||||
|
"end": "=+"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -153,12 +153,17 @@ index 0000000..7cccc5b
|
|||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/src/tests/example_file.jl
|
+++ b/src/tests/example_file.jl
|
||||||
@@ -0,0 +1,2 @@
|
@@ -0,0 +1,2 @@
|
||||||
- # TODO: Hopefully this comment turns into an issue
|
- #TODO: Hopefully this comment turns into an issue
|
||||||
|
- # TODO: Hopefully this comment also turns into an issue
|
||||||
- print("Hello World")
|
- print("Hello World")
|
||||||
- #= TODO: Multiline comments
|
- #= TODO: Multiline comments
|
||||||
- also need to be turned into task, and hopefully
|
- also need to be turned into task, and hopefully
|
||||||
- kept together as one.
|
- kept together as one.
|
||||||
- =#
|
- =#
|
||||||
|
- #=TODO: Another copied multiline comment
|
||||||
|
- also need to be turned into task, and hopefully
|
||||||
|
- kept together as one.
|
||||||
|
- =#
|
||||||
diff --git a/tests/defs.bzl b/tests/defs.bzl
|
diff --git a/tests/defs.bzl b/tests/defs.bzl
|
||||||
index 525e25d..ba4e68d 100644
|
index 525e25d..ba4e68d 100644
|
||||||
--- a/tests/defs.bzl
|
--- a/tests/defs.bzl
|
||||||
@ -384,11 +389,106 @@ index 6b0c6cf..b37e70a 100644
|
|||||||
-' TODO: remove feature to prevent legal issues
|
-' TODO: remove feature to prevent legal issues
|
||||||
-Public Sub Plagiarize()
|
-Public Sub Plagiarize()
|
||||||
+Public Sub MakeOriginalIdea()
|
+Public Sub MakeOriginalIdea()
|
||||||
diff --git a/tests/example.sht b/tests/example.sht
|
diff --git a/tests/example.cu b/tests/example.cu
|
||||||
index 6b0c6cf..b37e70a 100644
|
index 0000000..a6c6cb0
|
||||||
--- a/tests/example.sht
|
--- /dev/null
|
||||||
+++ b/tests/example.sht
|
+++ b/tests/example.cu
|
||||||
@@ -1,2 +1,1 @@
|
@@ -1,9 +1,5 @@
|
||||||
-' TODO: switch to tea
|
-// TODO rename this function
|
||||||
-Public Sub MakeCoffee()
|
__global__ void test() {
|
||||||
+Public Sub MakeTea()
|
- /*
|
||||||
|
- TODO fill this with something useful
|
||||||
|
- */
|
||||||
|
}
|
||||||
|
diff --git a/tests/Makefile b/tests/Makefile
|
||||||
|
index 2996176..7545ccf 100644
|
||||||
|
--- a/tests/Makefile
|
||||||
|
+++ b/tests/Makefile
|
||||||
|
@@ -1,12 +1,9 @@
|
||||||
|
-# TODO change name.
|
||||||
|
NAME = asm
|
||||||
|
|
||||||
|
-# TODO source files must be explicitly named.
|
||||||
|
SRC = $(shell find mandatory/src -name "*.asm")
|
||||||
|
OBJ = $(patsubst src/%.asm, obj/%.o, $(SRC))
|
||||||
|
.PHONY: all
|
||||||
|
all: $(NAME)
|
||||||
|
$(NAME): $(OBJ)
|
||||||
|
- # TODO create the directory.
|
||||||
|
$(AR) rc $@ $(OBJ)
|
||||||
|
|
||||||
|
diff --git a/tests/example_file.liquid b/tests/example_file.liquid
|
||||||
|
index 0000000..7cccc5b 100644
|
||||||
|
--- a/tests/example_file.liquid
|
||||||
|
+++ b/tests/example_file.liquid
|
||||||
|
@@ -1,6 +0,0 @@
|
||||||
|
-{% comment %} TODO: remove loop logic {% endcomment %}
|
||||||
|
{% for i in (1..3) -%}
|
||||||
|
- # TODO: Do math here!
|
||||||
|
- # labels: help wanted
|
||||||
|
{{ i }}
|
||||||
|
{% endfor %}
|
||||||
|
-{% comment %}
|
||||||
|
-TODO: Render Liquid file
|
||||||
|
{% assign featured_product = all_products["product_handle"] %}
|
||||||
|
{% render "product", product: featured_product %}
|
||||||
|
-{% endcomment %}
|
||||||
|
diff --git a/tests/example_file.tsx b/tests/example_file.tsx
|
||||||
|
index 0000000..7cccc5b 100644
|
||||||
|
--- a/tests/example_file.tsx
|
||||||
|
+++ b/tests/example_file.tsx
|
||||||
|
@@ -1,7 +1,3 @@
|
||||||
|
-// TODO: rename component
|
||||||
|
-export default async function Component() {
|
||||||
|
+export default async function MyComponent() {
|
||||||
|
- /* TODO: Use state here
|
||||||
|
- labels: client */
|
||||||
|
+ const [data, setData] = useState<string>("");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
- {/*
|
||||||
|
- TODO: use styled component library
|
||||||
|
- */}
|
||||||
|
+ <StyledComponent>{data}</StyledComponent>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
diff --git a/src/Swarm/Game/example.purs b/src/Swarm/Game/example.purs
|
||||||
|
index 525e25d..ba4e68d 100644
|
||||||
|
--- a/src/Swarm/Game/example.purs
|
||||||
|
+++ b/src/Swarm/Game/example.purs
|
||||||
|
@@ -1,14 +0,0 @@
|
||||||
|
--- | Standard devices that are always installed.
|
||||||
|
---
|
||||||
|
--- TODO: Remove standard devices
|
||||||
|
--- In the future, make a way to build these and just start the base
|
||||||
|
--- out with a large supply of each?
|
||||||
|
--- labels: redesign
|
||||||
|
-stdDeviceList =
|
||||||
|
- ["treads", "grabber", "solar panel", "scanner", "plasma cutter"]
|
||||||
|
-
|
||||||
|
-{- | Very complicated function.
|
||||||
|
-
|
||||||
|
-TODO: Create an issue for TODO
|
||||||
|
--}
|
||||||
|
-sum a b = a + b
|
||||||
|
diff --git a/src/Swarm/Game/example.agda b/src/Swarm/Game/example.agda
|
||||||
|
index 525e25d..ba4e68d 100644
|
||||||
|
--- a/src/Swarm/Game/example.agda
|
||||||
|
+++ b/src/Swarm/Game/example.agda
|
||||||
|
@@ -1,14 +0,0 @@
|
||||||
|
--- | Standard devices that are always installed.
|
||||||
|
---
|
||||||
|
--- TODO: Remove standard devices
|
||||||
|
--- In the future, make a way to build these and just start the base
|
||||||
|
--- out with a large supply of each?
|
||||||
|
--- labels: redesign
|
||||||
|
-stdDeviceList =
|
||||||
|
- ["treads", "grabber", "solar panel", "scanner", "plasma cutter"]
|
||||||
|
-
|
||||||
|
-{- | Very complicated function.
|
||||||
|
-
|
||||||
|
-TODO: Create an issue for TODO
|
||||||
|
--}
|
||||||
|
-sum a b = a + b
|
||||||
|
|||||||
19
tests/test_escape.diff
Normal file
19
tests/test_escape.diff
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
diff --git a/tests/ExampleFile.java b/tests/ExampleFile.java
|
||||||
|
index d340f6a..29b54da 100644
|
||||||
|
--- a/tests/ExampleFile.java
|
||||||
|
+++ b/tests/ExampleFile.java
|
||||||
|
@@ -0,0 +1,13 @@
|
||||||
|
+package com.mydomain.myapp;
|
||||||
|
+
|
||||||
|
+public class JavaTests {
|
||||||
|
+ // TODO: Some Java
|
||||||
|
+ // # Some title
|
||||||
|
+ // <SomeTag>
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ TODO: Definitely some Java
|
||||||
|
+ # Another title
|
||||||
|
+ <AnotherTag>
|
||||||
|
+ */
|
||||||
|
+}
|
||||||
|
\ No newline at end of file
|
||||||
@ -201,6 +201,20 @@ index 0000000..525e25d
|
|||||||
+ # This function should probably do something more interesting
|
+ # This function should probably do something more interesting
|
||||||
+ # labels: help wanted
|
+ # labels: help wanted
|
||||||
+ pass
|
+ pass
|
||||||
|
diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..525e25d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/BUILD.bazel
|
||||||
|
@@ -0,0 +1,23 @@
|
||||||
|
+def hello_world():
|
||||||
|
+ # TODO: Come up with a more imaginative greeting
|
||||||
|
+ print('Hello world')
|
||||||
|
+
|
||||||
|
+ # TODO: Do more stuff
|
||||||
|
+ # This function should probably do something more interesting
|
||||||
|
+ # labels: help wanted
|
||||||
|
+ pass
|
||||||
diff --git a/tests/example_file.ahk b/src/tests/example_file.ahk
|
diff --git a/tests/example_file.ahk b/src/tests/example_file.ahk
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..7cccc5b
|
index 0000000..7cccc5b
|
||||||
@ -424,10 +438,111 @@ index 6b0c6cf..b37e70a 100644
|
|||||||
@@ -1,1 +1,2 @@
|
@@ -1,1 +1,2 @@
|
||||||
+' TODO: remove feature to prevent legal issues
|
+' TODO: remove feature to prevent legal issues
|
||||||
Public Sub Plagiarize()
|
Public Sub Plagiarize()
|
||||||
diff --git a/tests/example.sht b/tests/example.sht
|
diff --git a/tests/example.cu b/tests/example.cu
|
||||||
index 6b0c6cf..b37e70a 100644
|
new file mode 100644
|
||||||
--- a/tests/example.sht
|
index 0000000..a6c6cb0
|
||||||
+++ b/tests/example.sht
|
--- /dev/null
|
||||||
@@ -1,1 +1,2 @@
|
+++ b/tests/example.cu
|
||||||
+' TODO: switch to tea
|
@@ -1,3 +1,11 @@
|
||||||
Public Sub MakeCoffee()
|
+
|
||||||
|
+// TODO rename this function
|
||||||
|
+__global__ void test() {
|
||||||
|
+ /*
|
||||||
|
+ TODO fill this with something useful
|
||||||
|
+ */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
diff --git a/tests/Makefile b/tests/Makefile
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..2996176
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/Makefile
|
||||||
|
@@ -0,0 +1,12 @@
|
||||||
|
+# TODO change name.
|
||||||
|
+NAME = asm
|
||||||
|
+
|
||||||
|
+# TODO source files must be explicitly named.
|
||||||
|
+SRC = $(shell find mandatory/src -name "*.asm")
|
||||||
|
+OBJ = $(patsubst src/%.asm, obj/%.o, $(SRC))
|
||||||
|
+.PHONY: all
|
||||||
|
+all: $(NAME)
|
||||||
|
+$(NAME): $(OBJ)
|
||||||
|
+ # TODO create the directory.
|
||||||
|
+ $(AR) rc $@ $(OBJ)
|
||||||
|
+
|
||||||
|
diff --git a/tests/example_file.liquid b/tests/example_file.liquid
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..7cccc5b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/example_file.liquid
|
||||||
|
@@ -0,0 +1,11 @@
|
||||||
|
+{% comment %} TODO: remove loop logic {% endcomment %}
|
||||||
|
+{% for i in (1..3) -%}
|
||||||
|
+ # TODO: Do math here!
|
||||||
|
+ # labels: help wanted
|
||||||
|
+ {{ i }}
|
||||||
|
+{% endfor %}
|
||||||
|
+{% comment %}
|
||||||
|
+TODO: Render Liquid file
|
||||||
|
+{% assign featured_product = all_products["product_handle"] %}
|
||||||
|
+{% render "product", product: featured_product %}
|
||||||
|
+{% endcomment %}
|
||||||
|
diff --git a/tests/example_file.tsx b/tests/example_file.tsx
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..7cccc5b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/example_file.tsx
|
||||||
|
@@ -0,0 +1,13 @@
|
||||||
|
+// TODO: rename component
|
||||||
|
+export default async function Component() {
|
||||||
|
+ /* TODO: Use state here
|
||||||
|
+ labels: client */
|
||||||
|
+
|
||||||
|
+ return (
|
||||||
|
+ <div>
|
||||||
|
+ {/*
|
||||||
|
+ TODO: use styled component library
|
||||||
|
+ */}
|
||||||
|
+ </div>
|
||||||
|
+ );
|
||||||
|
+}
|
||||||
|
diff --git a/src/Swarm/Game/example.purs b/src/Swarm/Game/example.purs
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0ce9b1a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/Swarm/Game/example.purs
|
||||||
|
@@ -0,0 +1,14 @@
|
||||||
|
+-- | Standard devices that are always installed.
|
||||||
|
+--
|
||||||
|
+-- TODO: Remove standard devices
|
||||||
|
+-- In the future, make a way to build these and just start the base
|
||||||
|
+-- out with a large supply of each?
|
||||||
|
+-- labels: redesign
|
||||||
|
+stdDeviceList =
|
||||||
|
+ ["treads", "grabber", "solar panel", "scanner", "plasma cutter"]
|
||||||
|
+
|
||||||
|
+{- | Very complicated function.
|
||||||
|
+
|
||||||
|
+TODO: Create an issue for TODO
|
||||||
|
+-}
|
||||||
|
+sum a b = a + b
|
||||||
|
diff --git a/src/Swarm/Game/example.agda b/src/Swarm/Game/example.agda
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0ce9b1a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/Swarm/Game/example.agda
|
||||||
|
@@ -0,0 +1,14 @@
|
||||||
|
+-- | Standard devices that are always installed.
|
||||||
|
+--
|
||||||
|
+-- TODO: Remove standard devices
|
||||||
|
+-- In the future, make a way to build these and just start the base
|
||||||
|
+-- out with a large supply of each?
|
||||||
|
+-- labels: redesign
|
||||||
|
+stdDeviceList =
|
||||||
|
+ ["treads", "grabber", "solar panel", "scanner", "plasma cutter"]
|
||||||
|
+
|
||||||
|
+{- | Very complicated function.
|
||||||
|
+
|
||||||
|
+TODO: Create an issue for TODO
|
||||||
|
+-}
|
||||||
|
+sum a b = a + b
|
||||||
|
|||||||
@ -23,8 +23,8 @@ class NewIssueTests(unittest.TestCase):
|
|||||||
self.raw_issues = parser.parse(diff_file)
|
self.raw_issues = parser.parse(diff_file)
|
||||||
|
|
||||||
def test_python_issues(self):
|
def test_python_issues(self):
|
||||||
# Includes 2 tests for Starlark.
|
# Includes 4 tests for Starlark.
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'python'), 6)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'python'), 8)
|
||||||
|
|
||||||
def test_yaml_issues(self):
|
def test_yaml_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'yaml'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'yaml'), 2)
|
||||||
@ -35,11 +35,9 @@ class NewIssueTests(unittest.TestCase):
|
|||||||
def test_java_issues(self):
|
def test_java_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'java'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'java'), 2)
|
||||||
|
|
||||||
def test_json_with_comments_issues(self):
|
def test_javascript_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'javascript'), 2)
|
# Includes 1 test for JSON with Comments, 1 test for JSON5, 3 tests for TSX.
|
||||||
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'javascript'), 5)
|
||||||
def test_json5_issues(self):
|
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'javascript'), 2)
|
|
||||||
|
|
||||||
def test_ruby_issues(self):
|
def test_ruby_issues(self):
|
||||||
# Includes 2 tests for Crystal.
|
# Includes 2 tests for Crystal.
|
||||||
@ -58,7 +56,7 @@ class NewIssueTests(unittest.TestCase):
|
|||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'julia'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'julia'), 2)
|
||||||
|
|
||||||
def test_starlark_issues(self):
|
def test_starlark_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'python'), 6)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'python'), 8)
|
||||||
|
|
||||||
def test_autohotkey_issues(self):
|
def test_autohotkey_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'autohotkey'), 1)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'autohotkey'), 1)
|
||||||
@ -75,6 +73,9 @@ class NewIssueTests(unittest.TestCase):
|
|||||||
def test_twig_issues(self):
|
def test_twig_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'twig'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'twig'), 2)
|
||||||
|
|
||||||
|
def test_makefile_issues(self):
|
||||||
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'makefile'), 3)
|
||||||
|
|
||||||
def test_md_issues(self):
|
def test_md_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'markdown'), 8)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'markdown'), 8)
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ class NewIssueTests(unittest.TestCase):
|
|||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'r'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'r'), 2)
|
||||||
|
|
||||||
def test_haskell_issues(self):
|
def test_haskell_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'haskell'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'haskell'), 4)
|
||||||
|
|
||||||
def test_clojure_issues(self):
|
def test_clojure_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'clojure'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'clojure'), 2)
|
||||||
@ -93,6 +94,11 @@ class NewIssueTests(unittest.TestCase):
|
|||||||
def test_xaml_issues(self):
|
def test_xaml_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'xml'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'xml'), 2)
|
||||||
|
|
||||||
|
def test_c_cpp_like_issues(self):
|
||||||
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'c_cpp'), 2)
|
||||||
|
|
||||||
|
def test_liquid_issues(self):
|
||||||
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'liquid'), 3)
|
||||||
|
|
||||||
class ClosedIssueTests(unittest.TestCase):
|
class ClosedIssueTests(unittest.TestCase):
|
||||||
# Check for removed TODOs across the files specified.
|
# Check for removed TODOs across the files specified.
|
||||||
@ -130,16 +136,14 @@ class ClosedIssueTests(unittest.TestCase):
|
|||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'tex'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'tex'), 2)
|
||||||
|
|
||||||
def test_julia_issues(self):
|
def test_julia_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'julia'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'julia'), 4)
|
||||||
|
|
||||||
def test_starlark_issues(self):
|
def test_starlark_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'python'), 5)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'python'), 5)
|
||||||
|
|
||||||
def test_json_with_comments_issues(self):
|
def test_javascript_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'javascript'), 2)
|
# Includes 1 test for JSON with Comments, 1 test for JSON5, 3 tests for TSX.
|
||||||
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'javascript'), 5)
|
||||||
def test_json5_issues(self):
|
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'javascript'), 2)
|
|
||||||
|
|
||||||
def test_autohotkey_issues(self):
|
def test_autohotkey_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'autohotkey'), 1)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'autohotkey'), 1)
|
||||||
@ -156,6 +160,9 @@ class ClosedIssueTests(unittest.TestCase):
|
|||||||
def test_twig_issues(self):
|
def test_twig_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'twig'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'twig'), 2)
|
||||||
|
|
||||||
|
def test_makefile_issues(self):
|
||||||
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'makefile'), 3)
|
||||||
|
|
||||||
def test_md_issues(self):
|
def test_md_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'markdown'), 8)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'markdown'), 8)
|
||||||
|
|
||||||
@ -163,7 +170,7 @@ class ClosedIssueTests(unittest.TestCase):
|
|||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'r'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'r'), 2)
|
||||||
|
|
||||||
def test_haskell_issues(self):
|
def test_haskell_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'haskell'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'haskell'), 4)
|
||||||
|
|
||||||
def test_clojure_issues(self):
|
def test_clojure_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'clojure'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'clojure'), 2)
|
||||||
@ -173,6 +180,13 @@ class ClosedIssueTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_xaml_issues(self):
|
def test_xaml_issues(self):
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'xml'), 2)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'xml'), 2)
|
||||||
|
|
||||||
|
def test_c_cpp_like_issues(self):
|
||||||
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'c_cpp'), 2)
|
||||||
|
|
||||||
|
def test_liquid_issues(self):
|
||||||
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'liquid'), 3)
|
||||||
|
|
||||||
|
|
||||||
class IgnorePatternTests(unittest.TestCase):
|
class IgnorePatternTests(unittest.TestCase):
|
||||||
|
|
||||||
@ -205,3 +219,71 @@ class IgnorePatternTests(unittest.TestCase):
|
|||||||
# Includes 2 tests for Crystal.
|
# Includes 2 tests for Crystal.
|
||||||
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'ruby'), 5)
|
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'ruby'), 5)
|
||||||
os.environ['INPUT_IGNORE'] = ''
|
os.environ['INPUT_IGNORE'] = ''
|
||||||
|
|
||||||
|
|
||||||
|
class EscapeMarkdownTest(unittest.TestCase):
|
||||||
|
def test_simple_escape(self):
|
||||||
|
os.environ['INPUT_ESCAPE'] = 'true'
|
||||||
|
parser = TodoParser()
|
||||||
|
with open('syntax.json', 'r') as syntax_json:
|
||||||
|
parser.syntax_dict = json.load(syntax_json)
|
||||||
|
diff_file = open('tests/test_escape.diff', 'r')
|
||||||
|
|
||||||
|
# I had no other idea to make these checks dynamic.
|
||||||
|
self.raw_issues = parser.parse(diff_file)
|
||||||
|
self.assertEqual(len(self.raw_issues), 2)
|
||||||
|
|
||||||
|
issue = self.raw_issues[0]
|
||||||
|
self.assertEqual(len(issue.body), 2)
|
||||||
|
self.assertEqual(issue.body[0], '\\# Some title')
|
||||||
|
self.assertEqual(issue.body[1], '\\<SomeTag\\>')
|
||||||
|
|
||||||
|
issue = self.raw_issues[1]
|
||||||
|
self.assertEqual(len(issue.body), 2)
|
||||||
|
self.assertEqual(issue.body[0], '\\# Another title')
|
||||||
|
self.assertEqual(issue.body[1], '\\<AnotherTag\\>')
|
||||||
|
|
||||||
|
|
||||||
|
class CustomLanguageTest(unittest.TestCase):
|
||||||
|
def test_custom_lang_load(self):
|
||||||
|
os.environ['INPUT_LANGUAGES'] = 'tests/custom_languages.json'
|
||||||
|
parser = TodoParser()
|
||||||
|
# Test if the custom language ILS is actually loaded into the system
|
||||||
|
self.assertIsNotNone(parser.languages_dict['ILS'])
|
||||||
|
self.assertEqual(self.count_syntax(parser, 'ILS'), 1)
|
||||||
|
|
||||||
|
def test_custom_lang_not_dupplicate(self):
|
||||||
|
os.environ['INPUT_LANGUAGES'] = 'tests/custom_languages.json'
|
||||||
|
parser = TodoParser()
|
||||||
|
|
||||||
|
# Test if a custom language can overwrite the rules of an existing one
|
||||||
|
self.assertEqual(self.count_syntax(parser, 'Java'), 1)
|
||||||
|
for syntax in parser.syntax_dict:
|
||||||
|
if syntax['language'] == 'Java':
|
||||||
|
self.assertEqual(len(syntax['markers']), 2)
|
||||||
|
self.assertEqual(syntax['markers'][0]['pattern'], "////")
|
||||||
|
self.assertEqual(syntax['markers'][1]['pattern']['start'], '+=')
|
||||||
|
self.assertEqual(syntax['markers'][1]['pattern']['end'], '=+')
|
||||||
|
break
|
||||||
|
|
||||||
|
self.assertIsNotNone(parser.languages_dict['Java'])
|
||||||
|
self.assertEqual(len(parser.languages_dict['Java']['extensions']), 1)
|
||||||
|
self.assertEqual(parser.languages_dict['Java']['extensions'][0], ".java2")
|
||||||
|
|
||||||
|
def test_url_load(self):
|
||||||
|
os.environ['INPUT_LANGUAGES'] = 'https://raw.githubusercontent.com/alstr/todo-to-issue-action/master/tests/custom_languages.json'
|
||||||
|
os.environ['INPUT_NO_STANDARD'] = 'true'
|
||||||
|
parser = TodoParser()
|
||||||
|
|
||||||
|
self.assertEqual(len(parser.languages_dict), 2)
|
||||||
|
self.assertEqual(len(parser.syntax_dict), 2)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def count_syntax(parser: TodoParser, name: str):
|
||||||
|
counter = 0
|
||||||
|
|
||||||
|
for syntax in parser.syntax_dict:
|
||||||
|
if syntax['language'] == name:
|
||||||
|
counter = counter + 1
|
||||||
|
|
||||||
|
return counter
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user