Skip to content

Commit

Permalink
Add support for updating the same results comment
Browse files Browse the repository at this point in the history
  • Loading branch information
ncalteen committed Jan 17, 2025
1 parent 2c0a6a3 commit cd7b78b
Show file tree
Hide file tree
Showing 14 changed files with 4,536 additions and 343 deletions.
27 changes: 21 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@

Validate issue form submissions

> [!IMPORTANT]
>
> As of version `v2.0.0`, this action has been converted to ESM. Because of
> this, custom validation scripts must be provided in ESM syntax. If you are
> using CommonJS, you will need to convert your scripts to ESM. See
> [`team.js`](./.github/validator/team.js) for an example.
## Important Updates

- As of version `v3`, this action now requires `issues: write` permissions to
read and write issue comments. This is because the action now updates the
**same** comment instead of adding new ones.
- As of version `v2`, this action has been converted to ESM. Because of this,
custom validation scripts must be provided in ESM syntax. If you are using
CommonJS, you will need to convert your scripts to ESM. See
[`team.js`](./.github/validator/team.js) for an example.

## About

Expand Down Expand Up @@ -66,6 +69,12 @@ jobs:
name: Validate Issue
runs-on: ubuntu-latest

# These permissions are required to read custom validator scripts and
# write/update issue comments.
permissions:
contents: read
issues: write

steps:
# This is required to access the repository's files. Specifically, the
# issue forms template and the additional validation configuration.
Expand Down Expand Up @@ -117,6 +126,12 @@ jobs:
name: Validate Issue with Custom Logic
runs-on: ubuntu-latest

# These permissions are required to read custom validator scripts and
# write/update issue comments.
permissions:
contents: read
issues: write

steps:
# This is required to access the repository's files. Specifically, the
# issue forms template and the additional validation configuration.
Expand Down
3 changes: 2 additions & 1 deletion __fixtures__/octokit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ export const rest = {
get: jest.fn(),
listComments: jest.fn(),
removeLabel: jest.fn(),
update: jest.fn()
update: jest.fn(),
updateComment: jest.fn()
},
orgs: {
checkMembershipForUser: jest.fn()
Expand Down
48 changes: 48 additions & 0 deletions __tests__/comments.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { jest } from '@jest/globals'
import * as github from '../__fixtures__/github.js'
import * as octokit from '../__fixtures__/octokit.js'

jest.unstable_mockModule('@actions/github', () => github)
jest.unstable_mockModule('@octokit/rest', async () => {
class Octokit {
constructor() {
return octokit
}
}

return {
Octokit
}
})
jest.unstable_mockModule('../src/constants.js', () => ({
COMMENT_IDENTIFIER: '<!-- action-required -->'
}))

const { getCommentId } = await import('../src/comments.js')
const { Octokit } = await import('@octokit/rest')

const mocktokit = jest.mocked(new Octokit())

describe('getCommentId()', () => {
afterEach(() => {
jest.resetAllMocks()
})

it('Returns a comment ID', async () => {
mocktokit.paginate.mockResolvedValue([
{
id: 1,
body: 'This is a comment. <!-- action-required -->'
},
{
id: 2,
body: 'This is another comment.'
}
])

const result = await getCommentId('token', 'owner', 'repo', 1)

expect(mocktokit.paginate).toHaveBeenCalled()
expect(result).toBe(1)
})
})
48 changes: 48 additions & 0 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as octokit from '../__fixtures__/octokit.js'
const compileTemplateSpy = jest.fn()
const validateSpy = jest.fn()
const parseTemplateSpy = jest.fn()
const getCommentIdSpy = jest.fn()

jest.unstable_mockModule('@actions/core', () => core)
jest.unstable_mockModule('@octokit/rest', async () => {
Expand All @@ -29,6 +30,9 @@ jest.unstable_mockModule('../src/validate.js', () => ({
jest.unstable_mockModule('../src/utils/parse.js', () => ({
parseTemplate: parseTemplateSpy
}))
jest.unstable_mockModule('../src/comments.js', () => ({
getCommentId: getCommentIdSpy
}))

const main = await import('../src/main.js')
const { Octokit } = await import('@octokit/rest')
Expand Down Expand Up @@ -76,6 +80,7 @@ describe('main.ts', () => {

parseTemplateSpy.mockReturnValue(JSON.parse(parsedTemplate))
validateSpy.mockReturnValue([])
getCommentIdSpy.mockReturnValue(undefined)
})

afterEach(() => {
Expand Down Expand Up @@ -292,4 +297,47 @@ describe('main.ts', () => {
expect(compileTemplateSpy).not.toHaveBeenCalledWith()
expect(mocktokit.rest.issues.createComment).toHaveBeenCalled()
})

it('Updates an existing comment when add-comment is true', async () => {
getCommentIdSpy.mockReturnValue(1)

jest
.spyOn(fs, 'existsSync')
.mockImplementation((path: PathLike): boolean => {
switch (path) {
case `${process.cwd()}/.github/ISSUE_TEMPLATE/example-request.yml`:
return true
case `${process.cwd()}/.github/validator/success.mustache`:
return true
default:
return false
}
})

jest
.spyOn(fs, 'readFileSync')
.mockImplementation((path: PathOrFileDescriptor): string => {
switch (path) {
case `${process.cwd()}/.github/ISSUE_TEMPLATE/example-request.yml`:
return template
case `${process.cwd()}/.github/validator/success.mustache`:
return successMustache
default:
return ''
}
})

// Mock the validation errors.
jest.mocked(validateSpy).mockReturnValue([])

await main.run()

expect(compileTemplateSpy).toHaveBeenCalledWith(
`${process.cwd()}/.github/validator/success.mustache`,
{
issue: JSON.parse(parsedIssue)
}
)
expect(mocktokit.rest.issues.updateComment).toHaveBeenCalled()
})
})
8 changes: 8 additions & 0 deletions dist/comments.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dist/constants.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit cd7b78b

Please sign in to comment.