Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom ignore matcher #7

Merged
merged 5 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ You can configure the action further by providing inputs:
comment. Use `{todo}` to insert the Todo content
- `custom_todo_matcher`: (**optional**) Add custom comment indicators to match
TODOs. Default matches `//`, `*` and `#` followed by `TODO` or `FIXME`.
- `custom_ignore_matcher`: (**optional**) Add custom regex to ignore TODOs that
match in the same line. Example: Setting
`custom_ignore_matcher: "/.*ignore.*/"` will ignore TODOs like
`// TODO ignore`.

```yaml
steps:
Expand Down
63 changes: 63 additions & 0 deletions __test__/todo-finder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,66 @@ describe('custom todo matcher', () => {
expect(fileTodos).toEqual(expectedTodos)
})
})

describe('custom ignore matcher', () => {
it('should ignore matches', () => {
const customIgnoreMatcher = 'comment'
const fileTodos = findTodos(
testData.mixedTodoDiff,
[],
undefined,
customIgnoreMatcher
)

const expectedTodos: Todo[] = [
{
filename: 'README.md',
line: 31,
content: 'TODO here',
isAdded: true
},
{
filename: 'lib/second.js',
line: 26,
content: 'TODO - upper case with much space',
isAdded: true
},
{
filename: 'lib/second.js',
line: 27,
content: 'todo - lower case with space',
isAdded: true
},
{
filename: 'lib/second.js',
line: 28,
content: 'todo - lower case no space',
isAdded: true
}
]

const expectedIgnoredTodos: Todo[] = [
{
filename: 'lib/first.js',
line: 21,
content: 'TODO removed comment',
isAdded: false
},
{
filename: 'lib/second.js',
line: 30,
content: 'todo comment',
isAdded: true
},
{
filename: 'lib/second.js',
line: 33,
content: 'todo - In comment block',
isAdded: true
}
]

expect(fileTodos).toEqual(expectedTodos)
expect(fileTodos).not.toContain(expectedIgnoredTodos)
})
})
26 changes: 16 additions & 10 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29330,6 +29330,7 @@ function run() {
const commentBodyTemplate = core.getInput('comment_body');
const commentCheckboxTemplate = core.getInput('comment_checkbox');
const customTodoMatcher = core.getInput('custom_todo_matcher');
const customIgnoreMather = core.getInput('custom_ignore_matcher');
const octokit = github.getOctokit(token);
const botName = 'github-actions[bot]';
const pr = github.context.payload.pull_request;
Expand All @@ -29348,7 +29349,7 @@ function run() {
}
else if (commentOnTodo) {
const prDiff = yield getPrDiff(octokit, pr.base.sha, pr.head.sha);
const todos = (0, todo_finder_1.findTodos)(prDiff, excludePatterns, customTodoMatcher);
const todos = (0, todo_finder_1.findTodos)(prDiff, excludePatterns, customTodoMatcher, customIgnoreMather);
console.log('Todos:', JSON.stringify(todos));
yield commentPr(octokit, pr.number, botName, todos, commentBodyTemplate, commentCheckboxTemplate);
}
Expand Down Expand Up @@ -29508,7 +29509,7 @@ function getTodosForDiff(pat, owner, repo, base, head) {
basehead: `${base}...${head}`
});
const prDiff = ((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.files) || [];
const todos = (0, todo_finder_1.findTodos)(prDiff, [], '{}');
const todos = (0, todo_finder_1.findTodos)(prDiff, [], '{}', '');
console.log('Todos:', JSON.stringify(todos));
});
}
Expand All @@ -29525,7 +29526,7 @@ exports.getTodosForDiff = getTodosForDiff;
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.findTodos = void 0;
const minimatch_1 = __nccwpck_require__(4501);
function findTodos(prDiff, exclude = [], customTodoMatcherString = '{}') {
function findTodos(prDiff, exclude = [], customTodoMatcherString = '{}', customIgnoreMatcherString = '') {
// Find first number in string
const firstAddedLineRegex = /\+(\d+)/;
const firstRemovedLineRegex = /-(\d+)/;
Expand Down Expand Up @@ -29579,7 +29580,7 @@ function findTodos(prDiff, exclude = [], customTodoMatcherString = '{}') {
for (const line of lines) {
const isAdded = line.startsWith('+');
const isDeleted = line.startsWith('-');
const todo = getTodoIfFound(line, customMatcher);
const todo = getTodoIfFound(line, customMatcher, customIgnoreMatcherString);
if (isDeleted) {
if (todo !== undefined) {
todos.push({
Expand Down Expand Up @@ -29624,16 +29625,16 @@ function getTodoMatcherForFile(filename, customTodoMatcherString) {
}
return customMatcher;
}
function getTodoIfFound(line, customMatcher = []) {
const regex = new RegExp(buildTodoMatcher(customMatcher), 'i');
function getTodoIfFound(line, customMatcher = [], customIgnoreMatcher) {
const regex = new RegExp(buildTodoMatcher(customMatcher, customIgnoreMatcher), 'i');
const match = line.match(regex);
if (match === undefined || match === null || (match === null || match === void 0 ? void 0 : match.length) === 0)
return;
// remove html closing comment tag if present
const todo = match[1].replace('-->', '').trim();
return todo;
}
function buildTodoMatcher(customMatcher) {
function buildTodoMatcher(customMatcher, customIgnoreMatcher) {
let todoMatcher;
if (customMatcher.length === 0) {
// default todo matcher
Expand All @@ -29657,7 +29658,7 @@ function buildTodoMatcher(customMatcher) {
'$',
'.'
];
const escapedPatterns = todoMatcher.map(pattern => {
const escapePattern = (pattern) => {
let escapedPattern = '';
for (const char of pattern) {
if (needToEscape.includes(char)) {
Expand All @@ -29668,8 +29669,13 @@ function buildTodoMatcher(customMatcher) {
}
}
return escapedPattern;
});
const regex = `(?:${escapedPatterns.join('|')}).*?(TODO.*|FIXME.*)`;
};
const escapedTodoPatterns = todoMatcher.map(matcher => escapePattern(matcher));
const escapedIgnorePatterns = escapePattern(customIgnoreMatcher);
const ignoreRegex = customIgnoreMatcher
? `(?!.*${escapedIgnorePatterns}.*)`
: '';
const regex = `(?:${escapedTodoPatterns.join('|')})${ignoreRegex}.*?(TODO.*|FIXME.*)`;
return regex;
}

Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export async function run(): Promise<void> {
const commentBodyTemplate = core.getInput('comment_body')
const commentCheckboxTemplate = core.getInput('comment_checkbox')
const customTodoMatcher = core.getInput('custom_todo_matcher')
const customIgnoreMather = core.getInput('custom_ignore_matcher')

const octokit = github.getOctokit(token)
const botName = 'github-actions[bot]'
Expand All @@ -38,7 +39,12 @@ export async function run(): Promise<void> {
} else if (commentOnTodo) {
const prDiff = await getPrDiff(octokit, pr.base.sha, pr.head.sha)

const todos = findTodos(prDiff, excludePatterns, customTodoMatcher)
const todos = findTodos(
prDiff,
excludePatterns,
customTodoMatcher,
customIgnoreMather
)
console.log('Todos:', JSON.stringify(todos))
await commentPr(
octokit,
Expand Down Expand Up @@ -239,6 +245,6 @@ export async function getTodosForDiff(

const prDiff = response?.data?.files || []

const todos = findTodos(prDiff, [], '{}')
const todos = findTodos(prDiff, [], '{}', '')
console.log('Todos:', JSON.stringify(todos))
}
35 changes: 27 additions & 8 deletions src/todo-finder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { minimatch } from 'minimatch'
export function findTodos(
prDiff: PrDiff,
exclude: string[] = [],
customTodoMatcherString = '{}'
customTodoMatcherString = '{}',
customIgnoreMatcherString = ''
): Todo[] {
// Find first number in string
const firstAddedLineRegex = /\+(\d+)/
Expand Down Expand Up @@ -81,7 +82,11 @@ export function findTodos(
const isAdded = line.startsWith('+')
const isDeleted = line.startsWith('-')

const todo = getTodoIfFound(line, customMatcher)
const todo = getTodoIfFound(
line,
customMatcher,
customIgnoreMatcherString
)

if (isDeleted) {
if (todo !== undefined) {
Expand Down Expand Up @@ -133,17 +138,24 @@ function getTodoMatcherForFile(

function getTodoIfFound(
line: string,
customMatcher: string[] = []
customMatcher: string[] = [],
customIgnoreMatcher: string
): string | undefined {
const regex = new RegExp(buildTodoMatcher(customMatcher), 'i')
const regex = new RegExp(
buildTodoMatcher(customMatcher, customIgnoreMatcher),
'i'
)
const match = line.match(regex)
if (match === undefined || match === null || match?.length === 0) return
// remove html closing comment tag if present
const todo = match[1].replace('-->', '').trim()
return todo
}

function buildTodoMatcher(customMatcher: string[]): string {
function buildTodoMatcher(
customMatcher: string[],
customIgnoreMatcher: string
): string {
let todoMatcher: string[]
if (customMatcher.length === 0) {
// default todo matcher
Expand All @@ -168,7 +180,7 @@ function buildTodoMatcher(customMatcher: string[]): string {
'.'
]

const escapedPatterns = todoMatcher.map(pattern => {
const escapePattern = (pattern: string): string => {
let escapedPattern = ''
for (const char of pattern) {
if (needToEscape.includes(char)) {
Expand All @@ -178,8 +190,15 @@ function buildTodoMatcher(customMatcher: string[]): string {
}
}
return escapedPattern
})
}

const escapedTodoPatterns = todoMatcher.map(matcher => escapePattern(matcher))
const escapedIgnorePatterns = escapePattern(customIgnoreMatcher)

const ignoreRegex = customIgnoreMatcher
? `(?!.*${escapedIgnorePatterns}.*)`
: ''

const regex = `(?:${escapedPatterns.join('|')}).*?(TODO.*|FIXME.*)`
const regex = `(?:${escapedTodoPatterns.join('|')})${ignoreRegex}.*?(TODO.*|FIXME.*)`
return regex
}