Skip to content

Commit

Permalink
Merge pull request #90 from Renato66/feat/parse-body-and-title
Browse files Browse the repository at this point in the history
Feat/parse body and title
  • Loading branch information
Renato66 authored Jul 19, 2024
2 parents 5fc2b85 + 8900fb3 commit 3f40fba
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 65 deletions.
5 changes: 4 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ inputs:
required: true
ignore-comments:
description: 'ignore labels inside issue comments'
default: true
default: 'true'
include-title:
description: 'include title in labels search'
default: 'true'
labels-synonyms:
description: 'text synonyms for labels'
default: ''
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "auto-label",
"version": "3.0.0",
"version": "3.1.0",
"module": "src/index.ts",
"type": "module",
"scripts": {
Expand Down
3 changes: 3 additions & 0 deletions src/domain/getConfigFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type Config = {
defaultLabels: string[]
labelsSynonyms: Record<string, string[]>
ignoreComments: boolean
includeTitle: boolean
}

export const getConfigFile = (): Config => {
Expand All @@ -20,13 +21,15 @@ export const getConfigFile = (): Config => {
{}
)
const ignoreComments = getInput('ignore-comments', true)
const includeTitle = getInput('include-title', true)
const config = getLabelConfigs(configPath)

return {
labelsNotAllowed,
defaultLabels,
labelsSynonyms,
ignoreComments,
includeTitle,
...config
}
}
26 changes: 11 additions & 15 deletions src/domain/getLabelConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ const getFilePath = (configurationPath: string): string | undefined => {
}
}

const compareArray = (arr?: string[]) => (Array.isArray(arr) ? arr : undefined)
const compareBoolean = (bool?: boolean) =>
typeof bool === 'boolean' ? bool : undefined
const compareObject = (obj?: Record<string, string[]>) =>
typeof obj === 'object' && !Array.isArray(obj) ? obj : undefined

export const getLabelConfigs = (configurationPath: string): Config | {} => {
const filePath = getFilePath(configurationPath)
if (!filePath) return {}
Expand All @@ -42,21 +48,11 @@ export const getLabelConfigs = (configurationPath: string): Config | {} => {
try {
const config = JSON5.parse(fileContent)
const configObject = {
defaultLabels: Array.isArray(config.defaultLabels)
? config.defaultLabels
: undefined,
labelsNotAllowed: Array.isArray(config.labelsNotAllowed)
? config.labelsNotAllowed
: undefined,
ignoreComments:
typeof config.ignoreComments === 'boolean'
? config.ignoreComments
: undefined,
labelsSynonyms:
typeof config.labelsSynonyms === 'object' &&
!Array.isArray(config.labelsSynonyms)
? config.labelsSynonyms
: undefined
defaultLabels: compareArray(config.defaultLabels),
labelsNotAllowed: compareArray(config.labelsNotAllowed),
ignoreComments: compareBoolean(config.ignoreComments),
includeTitle: compareBoolean(config.includeTitle),
labelsSynonyms: compareObject(config.labelsSynonyms)
}
return Object.fromEntries(
Object.entries(configObject).filter(
Expand Down
26 changes: 26 additions & 0 deletions src/domain/parseText.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { expect, describe, test } from 'bun:test'
import { parseText } from './parseText'

describe('getIssueLabels function', () => {
test('should return just scoped body', () => {
const body =
'Body with labels <!-- AUTO-LABEL:START --> Label1 Label2 <!-- AUTO-LABEL:END -->'
const result = parseText(body, '', false, false)

expect(result).toEqual(' --> Label1 Label2 <!-- ')
})

test('should return just scoped body', () => {
const body = 'Body with labels <!-- Label3 --> Label1 Label2'
const result = parseText(body, '', true, false)

expect(result).toEqual('Body with labels Label1 Label2')
})

test('should return just scoped body', () => {
const body = 'Body with labels <!-- Label3 --> Label1 Label2'
const result = parseText(body, 'Title', true, true)

expect(result).toEqual('Title Body with labels Label1 Label2')
})
})
26 changes: 26 additions & 0 deletions src/domain/parseText.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export const parseText = (
body: string,
title: string,
ignoreComments?: boolean,
includeTitle?: boolean
): string => {
let parsedBody = body
if (parsedBody.includes('AUTO-LABEL:START')) {
const [_ignore, ...bodySplit] = body.split('AUTO-LABEL:START')
parsedBody = bodySplit
.map((elem) => elem.split('AUTO-LABEL:END')[0])
.join(' ')
}

if (ignoreComments && parsedBody.includes('<!--')) {
parsedBody = parsedBody.replace(/\<!--(.|\n)*?-->/g, '')
}

const response = [parsedBody]

if (includeTitle) {
response.unshift(title)
}

return response.join(' ')
}
22 changes: 18 additions & 4 deletions src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { addLabels, getRepoLabels } from './service/github'
import { removeLabelsNotAllowed } from './domain/removeLabelsNotAllowed'
import { getIssueLabels } from './scraper/text'
import { getConfigFile } from './domain/getConfigFile'
import { parseText } from './domain/parseText'

export async function run() {
try {
Expand All @@ -16,8 +17,13 @@ export async function run() {
const token = core.getInput('repo-token', { required: true })
const octokit = github.getOctokit(token)
const issue = github.context.payload.issue!
const { labelsNotAllowed, defaultLabels, labelsSynonyms, ignoreComments } =
getConfigFile()
const {
labelsNotAllowed,
defaultLabels,
labelsSynonyms,
ignoreComments,
includeTitle
} = getConfigFile()
core.endGroup()

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

core.startGroup(`Parsing body${includeTitle ? 'and Title' : ''}`)
const parsedBody = parseText(
issue.body || '',
issue.title || '',
ignoreComments,
includeTitle
)
core.startGroup('Getting repository labels')

core.startGroup('Looking for labels')
const issueLabels: string[] = getIssueLabels(
issue.body!,
parsedBody,
repoLabels,
ignoreComments,
defaultLabels,
labelsSynonyms
)
Expand Down
21 changes: 5 additions & 16 deletions src/scraper/text.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ describe('getIssueLabels function', () => {
'Body with labels <!-- AUTO-LABEL:START --> Label1 Label2 <!-- AUTO-LABEL:END -->'
const labels = ['Label1', 'Label2']

const result = getIssueLabels(body, labels, false, [], {})
const result = getIssueLabels(body, labels, [], {})

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

test('should handle no labels in body', () => {
const body = 'No labels in this body'
const labels = ['Label1', 'Label2']
const result = getIssueLabels(body, labels, false, [], {})
const result = getIssueLabels(body, labels, [], {})

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

const result = getIssueLabels(body, labels, false, defaultLabels, {})
const result = getIssueLabels(body, labels, defaultLabels, {})

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

test('should not add labels inside the comments section', () => {
const body =
'Body with labels: Label1 <!-- the label Label2 is mentioned in the body, but its commented and shouldn`t be tracked -->'
const labels = ['Label1', 'Label2']

const result = getIssueLabels(body, labels, true, [], {})

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

test('should check if there is any synonym for the labels available', () => {
const body =
'Body with labels: Synonym1 <!-- the label Synonym2 is mentioned in the body, but its commented and shouldn`t be tracked -->'
const body = 'Body with labels: Synonym1'
const labels = ['Label1', 'Label2']
const labelsSynonyms = { Label1: ['Synonym1'], Label2: ['Synonym2'] }

const result = getIssueLabels(body, labels, true, [], labelsSynonyms)
const result = getIssueLabels(body, labels, [], labelsSynonyms)

expect(result).toEqual(['Label1'])
})
Expand Down
32 changes: 4 additions & 28 deletions src/scraper/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,42 +39,18 @@ const compareLabels = (
return hasLabels
}

const parseAutoLabel = (body: string): string => {
const autoLabelRegex = new RegExp(
/<!-- AUTO-LABEL:START -->(?<label>(\s*\w.+|\n)*?)\s*<!-- AUTO-LABEL:END -->/,
'gm'
)
const autoLabels = body.match(autoLabelRegex)

if (!autoLabels) return body

const replaceAutoLabelByLabelValue = (autoLabel: string) =>
autoLabel.replace(autoLabelRegex, '$1').trim()

return autoLabels.map(replaceAutoLabelByLabelValue).join(' ')
}

export const getIssueLabels = (
body: string,
text: string,
labels: string[],
ignoreComments: boolean,
defaultLabels: string[],
labelsSynonyms: Record<string, string[]>
): string[] => {
const selectedLabels: string[] = []
const hasLabels = compareLabels(labels, labelsSynonyms)

const parsedBody = parseAutoLabel(body)
hasLabels(text).forEach((elem) => {
selectedLabels.push(elem)
})

if (ignoreComments) {
const noCommentaryBody = parsedBody.replace(/\<!--(.|\n)*?-->/g, '')
hasLabels(noCommentaryBody).map((elem) => {
selectedLabels.push(elem)
})
} else {
hasLabels(parsedBody).map((elem) => {
selectedLabels.push(elem)
})
}
return [...new Set([...selectedLabels, ...defaultLabels])]
}

0 comments on commit 3f40fba

Please sign in to comment.