Skip to content

Commit 3f40fba

Browse files
authored
Merge pull request #90 from Renato66/feat/parse-body-and-title
Feat/parse body and title
2 parents 5fc2b85 + 8900fb3 commit 3f40fba

9 files changed

+98
-65
lines changed

action.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ inputs:
1010
required: true
1111
ignore-comments:
1212
description: 'ignore labels inside issue comments'
13-
default: true
13+
default: 'true'
14+
include-title:
15+
description: 'include title in labels search'
16+
default: 'true'
1417
labels-synonyms:
1518
description: 'text synonyms for labels'
1619
default: ''

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "auto-label",
3-
"version": "3.0.0",
3+
"version": "3.1.0",
44
"module": "src/index.ts",
55
"type": "module",
66
"scripts": {

src/domain/getConfigFile.ts

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export type Config = {
66
defaultLabels: string[]
77
labelsSynonyms: Record<string, string[]>
88
ignoreComments: boolean
9+
includeTitle: boolean
910
}
1011

1112
export const getConfigFile = (): Config => {
@@ -20,13 +21,15 @@ export const getConfigFile = (): Config => {
2021
{}
2122
)
2223
const ignoreComments = getInput('ignore-comments', true)
24+
const includeTitle = getInput('include-title', true)
2325
const config = getLabelConfigs(configPath)
2426

2527
return {
2628
labelsNotAllowed,
2729
defaultLabels,
2830
labelsSynonyms,
2931
ignoreComments,
32+
includeTitle,
3033
...config
3134
}
3235
}

src/domain/getLabelConfigs.ts

+11-15
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ const getFilePath = (configurationPath: string): string | undefined => {
3131
}
3232
}
3333

34+
const compareArray = (arr?: string[]) => (Array.isArray(arr) ? arr : undefined)
35+
const compareBoolean = (bool?: boolean) =>
36+
typeof bool === 'boolean' ? bool : undefined
37+
const compareObject = (obj?: Record<string, string[]>) =>
38+
typeof obj === 'object' && !Array.isArray(obj) ? obj : undefined
39+
3440
export const getLabelConfigs = (configurationPath: string): Config | {} => {
3541
const filePath = getFilePath(configurationPath)
3642
if (!filePath) return {}
@@ -42,21 +48,11 @@ export const getLabelConfigs = (configurationPath: string): Config | {} => {
4248
try {
4349
const config = JSON5.parse(fileContent)
4450
const configObject = {
45-
defaultLabels: Array.isArray(config.defaultLabels)
46-
? config.defaultLabels
47-
: undefined,
48-
labelsNotAllowed: Array.isArray(config.labelsNotAllowed)
49-
? config.labelsNotAllowed
50-
: undefined,
51-
ignoreComments:
52-
typeof config.ignoreComments === 'boolean'
53-
? config.ignoreComments
54-
: undefined,
55-
labelsSynonyms:
56-
typeof config.labelsSynonyms === 'object' &&
57-
!Array.isArray(config.labelsSynonyms)
58-
? config.labelsSynonyms
59-
: undefined
51+
defaultLabels: compareArray(config.defaultLabels),
52+
labelsNotAllowed: compareArray(config.labelsNotAllowed),
53+
ignoreComments: compareBoolean(config.ignoreComments),
54+
includeTitle: compareBoolean(config.includeTitle),
55+
labelsSynonyms: compareObject(config.labelsSynonyms)
6056
}
6157
return Object.fromEntries(
6258
Object.entries(configObject).filter(

src/domain/parseText.spec.ts

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { expect, describe, test } from 'bun:test'
2+
import { parseText } from './parseText'
3+
4+
describe('getIssueLabels function', () => {
5+
test('should return just scoped body', () => {
6+
const body =
7+
'Body with labels <!-- AUTO-LABEL:START --> Label1 Label2 <!-- AUTO-LABEL:END -->'
8+
const result = parseText(body, '', false, false)
9+
10+
expect(result).toEqual(' --> Label1 Label2 <!-- ')
11+
})
12+
13+
test('should return just scoped body', () => {
14+
const body = 'Body with labels <!-- Label3 --> Label1 Label2'
15+
const result = parseText(body, '', true, false)
16+
17+
expect(result).toEqual('Body with labels Label1 Label2')
18+
})
19+
20+
test('should return just scoped body', () => {
21+
const body = 'Body with labels <!-- Label3 --> Label1 Label2'
22+
const result = parseText(body, 'Title', true, true)
23+
24+
expect(result).toEqual('Title Body with labels Label1 Label2')
25+
})
26+
})

src/domain/parseText.ts

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export const parseText = (
2+
body: string,
3+
title: string,
4+
ignoreComments?: boolean,
5+
includeTitle?: boolean
6+
): string => {
7+
let parsedBody = body
8+
if (parsedBody.includes('AUTO-LABEL:START')) {
9+
const [_ignore, ...bodySplit] = body.split('AUTO-LABEL:START')
10+
parsedBody = bodySplit
11+
.map((elem) => elem.split('AUTO-LABEL:END')[0])
12+
.join(' ')
13+
}
14+
15+
if (ignoreComments && parsedBody.includes('<!--')) {
16+
parsedBody = parsedBody.replace(/\<!--(.|\n)*?-->/g, '')
17+
}
18+
19+
const response = [parsedBody]
20+
21+
if (includeTitle) {
22+
response.unshift(title)
23+
}
24+
25+
return response.join(' ')
26+
}

src/runner.ts

+18-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { addLabels, getRepoLabels } from './service/github'
66
import { removeLabelsNotAllowed } from './domain/removeLabelsNotAllowed'
77
import { getIssueLabels } from './scraper/text'
88
import { getConfigFile } from './domain/getConfigFile'
9+
import { parseText } from './domain/parseText'
910

1011
export async function run() {
1112
try {
@@ -16,8 +17,13 @@ export async function run() {
1617
const token = core.getInput('repo-token', { required: true })
1718
const octokit = github.getOctokit(token)
1819
const issue = github.context.payload.issue!
19-
const { labelsNotAllowed, defaultLabels, labelsSynonyms, ignoreComments } =
20-
getConfigFile()
20+
const {
21+
labelsNotAllowed,
22+
defaultLabels,
23+
labelsSynonyms,
24+
ignoreComments,
25+
includeTitle
26+
} = getConfigFile()
2127
core.endGroup()
2228

2329
core.startGroup('Getting repository labels')
@@ -28,11 +34,19 @@ export async function run() {
2834
core.info(`Considered labels: ${filteredLabels.length}`)
2935
core.endGroup()
3036

37+
core.startGroup(`Parsing body${includeTitle ? 'and Title' : ''}`)
38+
const parsedBody = parseText(
39+
issue.body || '',
40+
issue.title || '',
41+
ignoreComments,
42+
includeTitle
43+
)
3144
core.startGroup('Getting repository labels')
45+
46+
core.startGroup('Looking for labels')
3247
const issueLabels: string[] = getIssueLabels(
33-
issue.body!,
48+
parsedBody,
3449
repoLabels,
35-
ignoreComments,
3650
defaultLabels,
3751
labelsSynonyms
3852
)

src/scraper/text.spec.ts

+5-16
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ describe('getIssueLabels function', () => {
77
'Body with labels <!-- AUTO-LABEL:START --> Label1 Label2 <!-- AUTO-LABEL:END -->'
88
const labels = ['Label1', 'Label2']
99

10-
const result = getIssueLabels(body, labels, false, [], {})
10+
const result = getIssueLabels(body, labels, [], {})
1111

1212
expect(result).toEqual(['Label1', 'Label2'])
1313
})
1414

1515
test('should handle no labels in body', () => {
1616
const body = 'No labels in this body'
1717
const labels = ['Label1', 'Label2']
18-
const result = getIssueLabels(body, labels, false, [], {})
18+
const result = getIssueLabels(body, labels, [], {})
1919

2020
expect(result).toEqual([])
2121
})
@@ -25,28 +25,17 @@ describe('getIssueLabels function', () => {
2525
const labels = ['Label1', 'Label2']
2626
const defaultLabels = ['DefaultLabel1', 'DefaultLabel2']
2727

28-
const result = getIssueLabels(body, labels, false, defaultLabels, {})
28+
const result = getIssueLabels(body, labels, defaultLabels, {})
2929

3030
expect(result).toEqual(['DefaultLabel1', 'DefaultLabel2'])
3131
})
3232

33-
test('should not add labels inside the comments section', () => {
34-
const body =
35-
'Body with labels: Label1 <!-- the label Label2 is mentioned in the body, but its commented and shouldn`t be tracked -->'
36-
const labels = ['Label1', 'Label2']
37-
38-
const result = getIssueLabels(body, labels, true, [], {})
39-
40-
expect(result).toEqual(['Label1'])
41-
})
42-
4333
test('should check if there is any synonym for the labels available', () => {
44-
const body =
45-
'Body with labels: Synonym1 <!-- the label Synonym2 is mentioned in the body, but its commented and shouldn`t be tracked -->'
34+
const body = 'Body with labels: Synonym1'
4635
const labels = ['Label1', 'Label2']
4736
const labelsSynonyms = { Label1: ['Synonym1'], Label2: ['Synonym2'] }
4837

49-
const result = getIssueLabels(body, labels, true, [], labelsSynonyms)
38+
const result = getIssueLabels(body, labels, [], labelsSynonyms)
5039

5140
expect(result).toEqual(['Label1'])
5241
})

src/scraper/text.ts

+4-28
Original file line numberDiff line numberDiff line change
@@ -39,42 +39,18 @@ const compareLabels = (
3939
return hasLabels
4040
}
4141

42-
const parseAutoLabel = (body: string): string => {
43-
const autoLabelRegex = new RegExp(
44-
/<!-- AUTO-LABEL:START -->(?<label>(\s*\w.+|\n)*?)\s*<!-- AUTO-LABEL:END -->/,
45-
'gm'
46-
)
47-
const autoLabels = body.match(autoLabelRegex)
48-
49-
if (!autoLabels) return body
50-
51-
const replaceAutoLabelByLabelValue = (autoLabel: string) =>
52-
autoLabel.replace(autoLabelRegex, '$1').trim()
53-
54-
return autoLabels.map(replaceAutoLabelByLabelValue).join(' ')
55-
}
56-
5742
export const getIssueLabels = (
58-
body: string,
43+
text: string,
5944
labels: string[],
60-
ignoreComments: boolean,
6145
defaultLabels: string[],
6246
labelsSynonyms: Record<string, string[]>
6347
): string[] => {
6448
const selectedLabels: string[] = []
6549
const hasLabels = compareLabels(labels, labelsSynonyms)
6650

67-
const parsedBody = parseAutoLabel(body)
51+
hasLabels(text).forEach((elem) => {
52+
selectedLabels.push(elem)
53+
})
6854

69-
if (ignoreComments) {
70-
const noCommentaryBody = parsedBody.replace(/\<!--(.|\n)*?-->/g, '')
71-
hasLabels(noCommentaryBody).map((elem) => {
72-
selectedLabels.push(elem)
73-
})
74-
} else {
75-
hasLabels(parsedBody).map((elem) => {
76-
selectedLabels.push(elem)
77-
})
78-
}
7955
return [...new Set([...selectedLabels, ...defaultLabels])]
8056
}

0 commit comments

Comments
 (0)