mirror of
https://github.com/mshick/add-pr-comment.git
synced 2025-12-31 22:29:45 +11:00
Compare commits
17 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd126dd8c2 | ||
|
|
30602c8f56 | ||
|
|
f24a409f6b | ||
|
|
b8f338c590 | ||
|
|
74e66d7778 | ||
|
|
8fedd701c5 | ||
|
|
7c0890544f | ||
|
|
12282e9c93 | ||
|
|
918f138773 | ||
|
|
84c8c4f13e | ||
|
|
445c144052 | ||
|
|
ff82b38f95 | ||
|
|
25e7c93662 | ||
|
|
09331f990d | ||
|
|
06b07c2e70 | ||
|
|
f8c324a9fc | ||
|
|
5cc4621415 |
20 changed files with 696 additions and 158 deletions
|
|
@ -50,6 +50,15 @@
|
|||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "twang817",
|
||||
"name": "Tommy Wang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/766820?v=4",
|
||||
"profile": "http://www.august8.net",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
|
|
|||
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
|
|
@ -73,4 +73,14 @@ jobs:
|
|||
message: |
|
||||
**Hello**
|
||||
🌏
|
||||
!
|
||||
!
|
||||
|
||||
- uses: ./
|
||||
with:
|
||||
message-id: text
|
||||
find: |
|
||||
Hello
|
||||
🌏
|
||||
replace: |
|
||||
Goodnight
|
||||
🌕
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
v16
|
||||
v20
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Michael Shick
|
||||
Copyright (c) 2024 Michael Shick
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
135
README.md
135
README.md
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
|
||||
[](#contributors-)
|
||||
[](#contributors-)
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
|
|
@ -88,6 +88,8 @@ jobs:
|
|||
| update-only | with | Only update the comment if it already exists. | no | false |
|
||||
| GITHUB_TOKEN | env | Valid GitHub token, can alternatively be defined in the env. | no | |
|
||||
| preformatted | with | Treat message text as pre-formatted and place it in a codeblock | no | |
|
||||
| find | with | Patterns to find in an existing message and replace with either `replace` text or a resolved `message`. See [Find-and-Replace](#find-and-replace) for more detail. | no | |
|
||||
| replace | with | Strings to replace a found pattern with. Each new line is a new replacement, or if you only have one pattern, you can replace with a multiline string. | no | |
|
||||
|
||||
## Advanced Uses
|
||||
|
||||
|
|
@ -170,6 +172,136 @@ jobs:
|
|||
message-part-*.txt
|
||||
```
|
||||
|
||||
### Find-and-Replace
|
||||
|
||||
Patterns can be matched and replaced to update comments. This could be useful
|
||||
for some situations, for instance, updating a checklist comment.
|
||||
|
||||
Find is a regular expression passed to the [RegExp() constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp). You can also
|
||||
include modifiers to override the default `gi`.
|
||||
|
||||
**Example**
|
||||
|
||||
Original message:
|
||||
|
||||
```
|
||||
[ ] Hello
|
||||
[ ] World
|
||||
```
|
||||
|
||||
Action:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
pr:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: mshick/add-pr-comment@v2
|
||||
if: always()
|
||||
with:
|
||||
find: |
|
||||
\n\\[ \\]
|
||||
replace: |
|
||||
[X]
|
||||
```
|
||||
|
||||
Final message:
|
||||
|
||||
```
|
||||
[X] Hello
|
||||
[X] World
|
||||
```
|
||||
|
||||
Multiple find and replaces can be used:
|
||||
|
||||
**Example**
|
||||
|
||||
Original message:
|
||||
|
||||
```
|
||||
hello world!
|
||||
```
|
||||
|
||||
Action:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
pr:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: mshick/add-pr-comment@v2
|
||||
if: always()
|
||||
with:
|
||||
find: |
|
||||
hello
|
||||
world
|
||||
replace: |
|
||||
goodnight
|
||||
moon
|
||||
```
|
||||
|
||||
Final message:
|
||||
|
||||
```
|
||||
goodnight moon!
|
||||
```
|
||||
|
||||
It defaults to your resolved message (either from `message` or `message-path`) to
|
||||
do a replacement:
|
||||
|
||||
**Example**
|
||||
|
||||
Original message:
|
||||
|
||||
```
|
||||
hello
|
||||
|
||||
<< FILE_CONTENTS >>
|
||||
|
||||
world
|
||||
```
|
||||
|
||||
Action:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
pr:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: mshick/add-pr-comment@v2
|
||||
if: always()
|
||||
with:
|
||||
message-path: |
|
||||
message.txt
|
||||
find: |
|
||||
<< FILE_CONTENTS >>
|
||||
```
|
||||
|
||||
Final message:
|
||||
|
||||
```
|
||||
hello
|
||||
|
||||
secret message from message.txt
|
||||
|
||||
world
|
||||
```
|
||||
|
||||
### Bring your own issues
|
||||
|
||||
You can set an issue id explicitly. Helpful for cases where you want to post
|
||||
|
|
@ -219,6 +351,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vincent-joignie-dd"><img src="https://avatars.githubusercontent.com/u/103102299?v=4?s=100" width="100px;" alt="vincent-joignie-dd"/><br /><sub><b>vincent-joignie-dd</b></sub></a><br /><a href="https://github.com/mshick/add-pr-comment/commits?author=vincent-joignie-dd" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://ahanoff.dev"><img src="https://avatars.githubusercontent.com/u/2371703?v=4?s=100" width="100px;" alt="Akhan Zhakiyanov"/><br /><sub><b>Akhan Zhakiyanov</b></sub></a><br /><a href="https://github.com/mshick/add-pr-comment/commits?author=ahanoff" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ahatzz11"><img src="https://avatars.githubusercontent.com/u/6256032?v=4?s=100" width="100px;" alt="Alex Hatzenbuhler"/><br /><sub><b>Alex Hatzenbuhler</b></sub></a><br /><a href="https://github.com/mshick/add-pr-comment/commits?author=ahatzz11" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.august8.net"><img src="https://avatars.githubusercontent.com/u/766820?v=4?s=100" width="100px;" alt="Tommy Wang"/><br /><sub><b>Tommy Wang</b></sub></a><br /><a href="https://github.com/mshick/add-pr-comment/commits?author=twang817" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ type Inputs = {
|
|||
'repo-token': string
|
||||
'message-id': string
|
||||
'allow-repeats': string
|
||||
'message-pattern'?: string
|
||||
'message-success'?: string
|
||||
'message-failure'?: string
|
||||
'message-cancelled'?: string
|
||||
|
|
@ -95,55 +96,80 @@ const handlers = [
|
|||
|
||||
const server = setupServer(...handlers)
|
||||
|
||||
beforeAll(() => {
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {})
|
||||
server.listen({ onUnhandledRequest: 'error' })
|
||||
})
|
||||
afterAll(() => server.close())
|
||||
|
||||
beforeEach(() => {
|
||||
inputs = { ...defaultInputs }
|
||||
issueNumber = defaultIssueNumber
|
||||
messagePayload = undefined
|
||||
|
||||
vi.resetModules()
|
||||
|
||||
github.context.sha = commitSha
|
||||
|
||||
// https://developer.github.com/webhooks/event-payloads/#issues
|
||||
github.context.payload = {
|
||||
pull_request: {
|
||||
number: issueNumber,
|
||||
},
|
||||
repository: {
|
||||
full_name: `${inputs['repo-owner']}/${inputs['repo-name']}`,
|
||||
name: 'bar',
|
||||
owner: {
|
||||
login: 'bar',
|
||||
},
|
||||
},
|
||||
} as WebhookPayload
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks()
|
||||
server.resetHandlers()
|
||||
})
|
||||
|
||||
const getInput = (name: string, options?: core.InputOptions) => {
|
||||
const value = inputs[name] ?? ''
|
||||
|
||||
if (options?.required && value === undefined) {
|
||||
throw new Error(`${name} is required`)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
function getMultilineInput(name, options) {
|
||||
const inputs = getInput(name, options)
|
||||
.split('\n')
|
||||
.filter((x) => x !== '')
|
||||
|
||||
if (options && options.trimWhitespace === false) {
|
||||
return inputs
|
||||
}
|
||||
|
||||
return inputs.map((input) => input.trim())
|
||||
}
|
||||
|
||||
function getBooleanInput(name, options) {
|
||||
const trueValue = ['true', 'True', 'TRUE']
|
||||
const falseValue = ['false', 'False', 'FALSE']
|
||||
const val = getInput(name, options)
|
||||
if (trueValue.includes(val)) return true
|
||||
if (falseValue.includes(val)) return false
|
||||
throw new TypeError(
|
||||
`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` +
|
||||
`Support boolean input list: \`true | True | TRUE | false | False | FALSE\``,
|
||||
)
|
||||
}
|
||||
|
||||
vi.mocked(core.getInput).mockImplementation(getInput)
|
||||
vi.mocked(core.getMultilineInput).mockImplementation(getMultilineInput)
|
||||
vi.mocked(core.getBooleanInput).mockImplementation(getBooleanInput)
|
||||
|
||||
describe('add-pr-comment action', () => {
|
||||
beforeAll(() => {
|
||||
// vi.spyOn(console, 'log').mockImplementation(() => {})
|
||||
// vi.spyOn(core, 'debug').mockImplementation(() => {})
|
||||
// vi.spyOn(core, 'info').mockImplementation(() => {})
|
||||
// vi.spyOn(core, 'warning').mockImplementation(() => {})
|
||||
server.listen({ onUnhandledRequest: 'error' })
|
||||
})
|
||||
afterAll(() => server.close())
|
||||
|
||||
beforeEach(() => {
|
||||
inputs = { ...defaultInputs }
|
||||
issueNumber = defaultIssueNumber
|
||||
messagePayload = undefined
|
||||
|
||||
vi.resetModules()
|
||||
|
||||
github.context.sha = commitSha
|
||||
|
||||
// https://developer.github.com/webhooks/event-payloads/#issues
|
||||
github.context.payload = {
|
||||
pull_request: {
|
||||
number: issueNumber,
|
||||
},
|
||||
repository: {
|
||||
full_name: `${inputs['repo-owner']}/${inputs['repo-name']}`,
|
||||
name: 'bar',
|
||||
owner: {
|
||||
login: 'bar',
|
||||
},
|
||||
},
|
||||
} as WebhookPayload
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks()
|
||||
server.resetHandlers()
|
||||
})
|
||||
|
||||
vi.mocked(core.getInput).mockImplementation((name: string, options?: core.InputOptions) => {
|
||||
const value = inputs[name] ?? ''
|
||||
|
||||
if (options?.required && value === undefined) {
|
||||
throw new Error(`${name} is required`)
|
||||
}
|
||||
|
||||
return value
|
||||
})
|
||||
|
||||
it('creates a comment with message text', async () => {
|
||||
inputs.message = simpleMessage
|
||||
inputs['allow-repeats'] = 'true'
|
||||
|
|
@ -271,7 +297,7 @@ describe('add-pr-comment action', () => {
|
|||
|
||||
it('creates a message when the message id does not exist', async () => {
|
||||
inputs.message = simpleMessage
|
||||
inputs['allow-repeats'] = 'false'
|
||||
|
||||
inputs['message-id'] = 'custom-id'
|
||||
|
||||
const replyBody = [
|
||||
|
|
@ -289,7 +315,6 @@ describe('add-pr-comment action', () => {
|
|||
|
||||
it('identifies an existing message by id and updates it', async () => {
|
||||
inputs.message = simpleMessage
|
||||
inputs['allow-repeats'] = 'false'
|
||||
|
||||
const commentId = 123
|
||||
|
||||
|
|
@ -313,7 +338,7 @@ describe('add-pr-comment action', () => {
|
|||
|
||||
it('overrides the default message with a success message on success', async () => {
|
||||
inputs.message = simpleMessage
|
||||
inputs['allow-repeats'] = 'false'
|
||||
|
||||
inputs['message-success'] = '666'
|
||||
inputs.status = 'success'
|
||||
|
||||
|
|
@ -334,7 +359,7 @@ describe('add-pr-comment action', () => {
|
|||
|
||||
it('overrides the default message with a failure message on failure', async () => {
|
||||
inputs.message = simpleMessage
|
||||
inputs['allow-repeats'] = 'false'
|
||||
|
||||
inputs['message-failure'] = '666'
|
||||
inputs.status = 'failure'
|
||||
|
||||
|
|
@ -355,7 +380,7 @@ describe('add-pr-comment action', () => {
|
|||
|
||||
it('overrides the default message with a cancelled message on cancelled', async () => {
|
||||
inputs.message = simpleMessage
|
||||
inputs['allow-repeats'] = 'false'
|
||||
|
||||
inputs['message-cancelled'] = '666'
|
||||
inputs.status = 'cancelled'
|
||||
|
||||
|
|
@ -376,7 +401,7 @@ describe('add-pr-comment action', () => {
|
|||
|
||||
it('overrides the default message with a skipped message on skipped', async () => {
|
||||
inputs.message = simpleMessage
|
||||
inputs['allow-repeats'] = 'false'
|
||||
|
||||
inputs['message-skipped'] = '666'
|
||||
inputs.status = 'skipped'
|
||||
|
||||
|
|
@ -408,3 +433,198 @@ describe('add-pr-comment action', () => {
|
|||
expect(core.setOutput).toHaveBeenCalledWith('comment-id', postIssueCommentsResponse.id)
|
||||
})
|
||||
})
|
||||
|
||||
describe('find and replace', () => {
|
||||
it('can find and replace text in an existing comment', async () => {
|
||||
inputs['find'] = 'world'
|
||||
inputs['replace'] = 'mars'
|
||||
|
||||
const commentId = 123
|
||||
|
||||
const replyBody = [
|
||||
{
|
||||
id: commentId,
|
||||
body: `<!-- add-pr-comment:${inputs['message-id']} -->\n\n${simpleMessage}`,
|
||||
},
|
||||
]
|
||||
|
||||
getIssueCommentsResponse = replyBody
|
||||
postIssueCommentsResponse = {
|
||||
id: commentId,
|
||||
}
|
||||
|
||||
await run()
|
||||
|
||||
expect(`<!-- add-pr-comment:add-pr-comment -->\n\nhello mars`).toEqual(messagePayload?.body)
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-updated', 'true')
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-id', commentId)
|
||||
})
|
||||
|
||||
it('can multiple find and replace text in an existing comment', async () => {
|
||||
inputs['find'] = 'hello\nworld'
|
||||
inputs['replace'] = 'goodbye\nmars'
|
||||
|
||||
const body = `<!-- add-pr-comment:${inputs['message-id']} -->\n\nhello\nworld`
|
||||
|
||||
const commentId = 123
|
||||
|
||||
const replyBody = [
|
||||
{
|
||||
id: commentId,
|
||||
body,
|
||||
},
|
||||
]
|
||||
|
||||
getIssueCommentsResponse = replyBody
|
||||
postIssueCommentsResponse = {
|
||||
id: commentId,
|
||||
}
|
||||
|
||||
await run()
|
||||
|
||||
expect(`<!-- add-pr-comment:add-pr-comment -->\n\ngoodbye\nmars`).toEqual(messagePayload?.body)
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-updated', 'true')
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-id', commentId)
|
||||
})
|
||||
|
||||
it('can multiple find and replace text using a message', async () => {
|
||||
inputs['find'] = 'hello\nworld'
|
||||
inputs['message'] = 'mars'
|
||||
|
||||
const body = `<!-- add-pr-comment:${inputs['message-id']} -->\n\nhello\nworld`
|
||||
|
||||
const commentId = 123
|
||||
|
||||
const replyBody = [
|
||||
{
|
||||
id: commentId,
|
||||
body,
|
||||
},
|
||||
]
|
||||
|
||||
getIssueCommentsResponse = replyBody
|
||||
postIssueCommentsResponse = {
|
||||
id: commentId,
|
||||
}
|
||||
|
||||
await run()
|
||||
|
||||
expect(`<!-- add-pr-comment:add-pr-comment -->\n\nmars\nmars`).toEqual(messagePayload?.body)
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-updated', 'true')
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-id', commentId)
|
||||
})
|
||||
|
||||
it('can multiple find and replace a single pattern with a multiline replacement', async () => {
|
||||
inputs['find'] = 'hello'
|
||||
inputs['message'] = 'h\ne\nl\nl\no'
|
||||
|
||||
const body = `<!-- add-pr-comment:${inputs['message-id']} -->\n\nhello\nworld`
|
||||
|
||||
const commentId = 123
|
||||
|
||||
const replyBody = [
|
||||
{
|
||||
id: commentId,
|
||||
body,
|
||||
},
|
||||
]
|
||||
|
||||
getIssueCommentsResponse = replyBody
|
||||
postIssueCommentsResponse = {
|
||||
id: commentId,
|
||||
}
|
||||
|
||||
await run()
|
||||
|
||||
expect(`<!-- add-pr-comment:add-pr-comment -->\n\nh\ne\nl\nl\no\nworld`).toEqual(
|
||||
messagePayload?.body,
|
||||
)
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-updated', 'true')
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-id', commentId)
|
||||
})
|
||||
|
||||
it('can multiple find and replace text using a message-path', async () => {
|
||||
inputs['find'] = '<< FILE_CONTENTS >>'
|
||||
inputs['message-path'] = messagePath1Fixture
|
||||
|
||||
const body = `<!-- add-pr-comment:${inputs['message-id']} -->\n\nhello\n<< FILE_CONTENTS >>\nworld`
|
||||
|
||||
const commentId = 123
|
||||
|
||||
const replyBody = [
|
||||
{
|
||||
id: commentId,
|
||||
body,
|
||||
},
|
||||
]
|
||||
|
||||
getIssueCommentsResponse = replyBody
|
||||
postIssueCommentsResponse = {
|
||||
id: commentId,
|
||||
}
|
||||
|
||||
await run()
|
||||
|
||||
expect(
|
||||
`<!-- add-pr-comment:add-pr-comment -->\n\nhello\n${messagePath1FixturePayload}\nworld`,
|
||||
).toEqual(messagePayload?.body)
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-updated', 'true')
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-id', commentId)
|
||||
})
|
||||
|
||||
it('can find and replace patterns and use alternative modifiers', async () => {
|
||||
inputs['find'] = '(o|l)/g'
|
||||
inputs['replace'] = 'YY'
|
||||
|
||||
const body = `<!-- add-pr-comment:${inputs['message-id']} -->\n\nHELLO\nworld`
|
||||
|
||||
const commentId = 123
|
||||
|
||||
const replyBody = [
|
||||
{
|
||||
id: commentId,
|
||||
body,
|
||||
},
|
||||
]
|
||||
|
||||
getIssueCommentsResponse = replyBody
|
||||
postIssueCommentsResponse = {
|
||||
id: commentId,
|
||||
}
|
||||
|
||||
await run()
|
||||
|
||||
expect(`<!-- add-pr-comment:add-pr-comment -->\n\nHELLO\nwYYrYYd`).toEqual(messagePayload?.body)
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-updated', 'true')
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-id', commentId)
|
||||
})
|
||||
|
||||
it('can check some boxes with find and replace', async () => {
|
||||
inputs['find'] = '\n\\[ \\]'
|
||||
inputs['replace'] = '[X]'
|
||||
|
||||
const body = `<!-- add-pr-comment:${inputs['message-id']} -->\n\n[ ] Hello\n[ ] World`
|
||||
|
||||
const commentId = 123
|
||||
|
||||
const replyBody = [
|
||||
{
|
||||
id: commentId,
|
||||
body,
|
||||
},
|
||||
]
|
||||
|
||||
getIssueCommentsResponse = replyBody
|
||||
postIssueCommentsResponse = {
|
||||
id: commentId,
|
||||
}
|
||||
|
||||
await run()
|
||||
|
||||
expect(`<!-- add-pr-comment:add-pr-comment -->\n\n[X] Hello\n[X] World`).toEqual(
|
||||
messagePayload?.body,
|
||||
)
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-updated', 'true')
|
||||
expect(core.setOutput).toHaveBeenCalledWith('comment-id', commentId)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -58,7 +58,11 @@ inputs:
|
|||
required: false
|
||||
preformatted:
|
||||
description: "Treat message text (from a file or input) as pre-formatted and place it in a codeblock."
|
||||
required: false
|
||||
required: false
|
||||
find:
|
||||
description: "A regular expression to find for replacement. Multiple lines become individual regular expressions."
|
||||
replace:
|
||||
description: "A replacement to use, overrides the message. Multple lines can replace same-indexed find patterns."
|
||||
outputs:
|
||||
comment-created:
|
||||
description: "Whether a comment was created."
|
||||
|
|
@ -70,5 +74,5 @@ branding:
|
|||
icon: message-circle
|
||||
color: purple
|
||||
runs:
|
||||
using: "node16"
|
||||
using: "node20"
|
||||
main: "dist/index.js"
|
||||
|
|
|
|||
88
dist/index.js
vendored
88
dist/index.js
vendored
|
|
@ -7,8 +7,8 @@ require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.createComment = exports.deleteComment = exports.updateComment = exports.getExistingCommentId = void 0;
|
||||
async function getExistingCommentId(octokit, owner, repo, issueNumber, messageId) {
|
||||
exports.createComment = exports.deleteComment = exports.updateComment = exports.getExistingComment = void 0;
|
||||
async function getExistingComment(octokit, owner, repo, issueNumber, messageId) {
|
||||
const parameters = {
|
||||
owner,
|
||||
repo,
|
||||
|
|
@ -25,9 +25,13 @@ async function getExistingCommentId(octokit, owner, repo, issueNumber, messageId
|
|||
break;
|
||||
}
|
||||
}
|
||||
return found === null || found === void 0 ? void 0 : found.id;
|
||||
if (found) {
|
||||
const { id, body } = found;
|
||||
return { id, body };
|
||||
}
|
||||
return;
|
||||
}
|
||||
exports.getExistingCommentId = getExistingCommentId;
|
||||
exports.getExistingComment = getExistingComment;
|
||||
async function updateComment(octokit, owner, repo, existingCommentId, body) {
|
||||
const updatedComment = await octokit.rest.issues.updateComment({
|
||||
comment_id: existingCommentId,
|
||||
|
|
@ -100,6 +104,8 @@ async function getInputs() {
|
|||
const messageId = messageIdInput === '' ? 'add-pr-comment' : `add-pr-comment:${messageIdInput}`;
|
||||
const messageInput = core.getInput('message', { required: false });
|
||||
const messagePath = core.getInput('message-path', { required: false });
|
||||
const messageFind = core.getMultilineInput('find', { required: false });
|
||||
const messageReplace = core.getMultilineInput('replace', { required: false });
|
||||
const repoOwner = core.getInput('repo-owner', { required: true });
|
||||
const repoName = core.getInput('repo-name', { required: true });
|
||||
const repoToken = core.getInput('repo-token', { required: true });
|
||||
|
|
@ -129,6 +135,8 @@ async function getInputs() {
|
|||
messageCancelled,
|
||||
messageSkipped,
|
||||
messagePath,
|
||||
messageFind,
|
||||
messageReplace,
|
||||
preformatted,
|
||||
proxyUrl,
|
||||
pullRequestNumber: (_b = payload.pull_request) === null || _b === void 0 ? void 0 : _b.number,
|
||||
|
|
@ -265,9 +273,9 @@ const message_1 = __nccwpck_require__(3307);
|
|||
const proxy_1 = __nccwpck_require__(8689);
|
||||
const run = async () => {
|
||||
try {
|
||||
const { allowRepeats, messagePath, messageInput, messageId, refreshMessagePosition, repoToken, proxyUrl, issue, pullRequestNumber, commitSha, repo, owner, updateOnly, messageCancelled, messageFailure, messageSuccess, messageSkipped, preformatted, status, } = await (0, config_1.getInputs)();
|
||||
const { allowRepeats, messagePath, messageInput, messageId, refreshMessagePosition, repoToken, proxyUrl, issue, pullRequestNumber, commitSha, repo, owner, updateOnly, messageCancelled, messageFailure, messageSuccess, messageSkipped, preformatted, status, messageFind, messageReplace, } = await (0, config_1.getInputs)();
|
||||
const octokit = github.getOctokit(repoToken);
|
||||
const message = await (0, message_1.getMessage)({
|
||||
let message = await (0, message_1.getMessage)({
|
||||
messagePath,
|
||||
messageInput,
|
||||
messageSkipped,
|
||||
|
|
@ -293,25 +301,31 @@ const run = async () => {
|
|||
core.setOutput('comment-created', 'false');
|
||||
return;
|
||||
}
|
||||
let existingCommentId;
|
||||
let existingComment;
|
||||
if (!allowRepeats) {
|
||||
core.debug('repeat comments are disallowed, checking for existing');
|
||||
existingCommentId = await (0, comments_1.getExistingCommentId)(octokit, owner, repo, issueNumber, messageId);
|
||||
if (existingCommentId) {
|
||||
core.debug(`existing comment found with id: ${existingCommentId}`);
|
||||
existingComment = await (0, comments_1.getExistingComment)(octokit, owner, repo, issueNumber, messageId);
|
||||
if (existingComment) {
|
||||
core.debug(`existing comment found with id: ${existingComment.id}`);
|
||||
}
|
||||
}
|
||||
// if no existing comment and updateOnly is true, exit
|
||||
if (!existingCommentId && updateOnly) {
|
||||
if (!existingComment && updateOnly) {
|
||||
core.info('no existing comment found and update-only is true, exiting');
|
||||
core.setOutput('comment-created', 'false');
|
||||
return;
|
||||
}
|
||||
let comment;
|
||||
const body = `${messageId}\n\n${message}`;
|
||||
if ((messageFind === null || messageFind === void 0 ? void 0 : messageFind.length) && ((messageReplace === null || messageReplace === void 0 ? void 0 : messageReplace.length) || message) && (existingComment === null || existingComment === void 0 ? void 0 : existingComment.body)) {
|
||||
message = (0, message_1.findAndReplaceInMessage)(messageFind, (messageReplace === null || messageReplace === void 0 ? void 0 : messageReplace.length) ? messageReplace : [message], (0, message_1.removeMessageHeader)(existingComment.body));
|
||||
}
|
||||
if (!message) {
|
||||
throw new Error('no message, check your message inputs');
|
||||
}
|
||||
const body = (0, message_1.addMessageHeader)(messageId, message);
|
||||
if (proxyUrl) {
|
||||
comment = await (0, proxy_1.createCommentProxy)({
|
||||
commentId: existingCommentId,
|
||||
commentId: existingComment === null || existingComment === void 0 ? void 0 : existingComment.id,
|
||||
owner,
|
||||
repo,
|
||||
issueNumber,
|
||||
|
|
@ -319,15 +333,15 @@ const run = async () => {
|
|||
repoToken,
|
||||
proxyUrl,
|
||||
});
|
||||
core.setOutput(existingCommentId ? 'comment-updated' : 'comment-created', 'true');
|
||||
core.setOutput((existingComment === null || existingComment === void 0 ? void 0 : existingComment.id) ? 'comment-updated' : 'comment-created', 'true');
|
||||
}
|
||||
else if (existingCommentId) {
|
||||
else if (existingComment === null || existingComment === void 0 ? void 0 : existingComment.id) {
|
||||
if (refreshMessagePosition) {
|
||||
await (0, comments_1.deleteComment)(octokit, owner, repo, existingCommentId, body);
|
||||
await (0, comments_1.deleteComment)(octokit, owner, repo, existingComment.id, body);
|
||||
comment = await (0, comments_1.createComment)(octokit, owner, repo, issueNumber, body);
|
||||
}
|
||||
else {
|
||||
comment = await (0, comments_1.updateComment)(octokit, owner, repo, existingCommentId, body);
|
||||
comment = await (0, comments_1.updateComment)(octokit, owner, repo, existingComment.id, body);
|
||||
}
|
||||
core.setOutput('comment-updated', 'true');
|
||||
}
|
||||
|
|
@ -371,7 +385,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getMessageFromPath = exports.getMessage = void 0;
|
||||
exports.findAndReplaceInMessage = exports.removeMessageHeader = exports.addMessageHeader = exports.getMessageFromPath = exports.getMessage = void 0;
|
||||
const promises_1 = __importDefault(__nccwpck_require__(3977));
|
||||
const files_1 = __nccwpck_require__(1743);
|
||||
async function getMessage({ messageInput, messagePath, messageCancelled, messageSkipped, messageFailure, messageSuccess, preformatted, status, }) {
|
||||
|
|
@ -396,13 +410,10 @@ async function getMessage({ messageInput, messagePath, messageCancelled, message
|
|||
message = messageInput;
|
||||
}
|
||||
}
|
||||
if (!message) {
|
||||
throw new Error('no message, check your message inputs');
|
||||
}
|
||||
if (preformatted) {
|
||||
message = `\`\`\`\n${message}\n\`\`\``;
|
||||
}
|
||||
return message;
|
||||
return message !== null && message !== void 0 ? message : '';
|
||||
}
|
||||
exports.getMessage = getMessage;
|
||||
async function getMessageFromPath(searchPath) {
|
||||
|
|
@ -417,6 +428,39 @@ async function getMessageFromPath(searchPath) {
|
|||
return message;
|
||||
}
|
||||
exports.getMessageFromPath = getMessageFromPath;
|
||||
function addMessageHeader(messageId, message) {
|
||||
return `${messageId}\n\n${message}`;
|
||||
}
|
||||
exports.addMessageHeader = addMessageHeader;
|
||||
function removeMessageHeader(message) {
|
||||
return message.split('\n').slice(2).join('\n');
|
||||
}
|
||||
exports.removeMessageHeader = removeMessageHeader;
|
||||
function splitFind(find) {
|
||||
const matches = find.match(/\/((i|g|m|s|u|y){1,6})$/);
|
||||
if (!matches) {
|
||||
return {
|
||||
regExp: find,
|
||||
modifiers: 'gi',
|
||||
};
|
||||
}
|
||||
const [, modifiers] = matches;
|
||||
const regExp = find.replace(modifiers, '').slice(0, -1);
|
||||
return {
|
||||
regExp,
|
||||
modifiers,
|
||||
};
|
||||
}
|
||||
function findAndReplaceInMessage(find, replace, original) {
|
||||
var _a;
|
||||
let message = original;
|
||||
for (const [i, f] of find.entries()) {
|
||||
const { regExp, modifiers } = splitFind(f);
|
||||
message = message.replace(new RegExp(regExp, modifiers), (_a = replace[i]) !== null && _a !== void 0 ? _a : replace.join('\n'));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
exports.findAndReplaceInMessage = findAndReplaceInMessage;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
|
|
|||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createComment = exports.deleteComment = exports.updateComment = exports.getExistingCommentId = void 0;
|
||||
async function getExistingCommentId(octokit, owner, repo, issueNumber, messageId) {
|
||||
exports.createComment = exports.deleteComment = exports.updateComment = exports.getExistingComment = void 0;
|
||||
async function getExistingComment(octokit, owner, repo, issueNumber, messageId) {
|
||||
const parameters = {
|
||||
owner,
|
||||
repo,
|
||||
|
|
@ -18,9 +18,13 @@ async function getExistingCommentId(octokit, owner, repo, issueNumber, messageId
|
|||
break;
|
||||
}
|
||||
}
|
||||
return found === null || found === void 0 ? void 0 : found.id;
|
||||
if (found) {
|
||||
const { id, body } = found;
|
||||
return { id, body };
|
||||
}
|
||||
return;
|
||||
}
|
||||
exports.getExistingCommentId = getExistingCommentId;
|
||||
exports.getExistingComment = getExistingComment;
|
||||
async function updateComment(octokit, owner, repo, existingCommentId, body) {
|
||||
const updatedComment = await octokit.rest.issues.updateComment({
|
||||
comment_id: existingCommentId,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ async function getInputs() {
|
|||
const messageId = messageIdInput === '' ? 'add-pr-comment' : `add-pr-comment:${messageIdInput}`;
|
||||
const messageInput = core.getInput('message', { required: false });
|
||||
const messagePath = core.getInput('message-path', { required: false });
|
||||
const messageFind = core.getMultilineInput('find', { required: false });
|
||||
const messageReplace = core.getMultilineInput('replace', { required: false });
|
||||
const repoOwner = core.getInput('repo-owner', { required: true });
|
||||
const repoName = core.getInput('repo-name', { required: true });
|
||||
const repoToken = core.getInput('repo-token', { required: true });
|
||||
|
|
@ -61,6 +63,8 @@ async function getInputs() {
|
|||
messageCancelled,
|
||||
messageSkipped,
|
||||
messagePath,
|
||||
messageFind,
|
||||
messageReplace,
|
||||
preformatted,
|
||||
proxyUrl,
|
||||
pullRequestNumber: (_b = payload.pull_request) === null || _b === void 0 ? void 0 : _b.number,
|
||||
|
|
|
|||
32
lib/main.js
32
lib/main.js
|
|
@ -32,9 +32,9 @@ const message_1 = require("./message");
|
|||
const proxy_1 = require("./proxy");
|
||||
const run = async () => {
|
||||
try {
|
||||
const { allowRepeats, messagePath, messageInput, messageId, refreshMessagePosition, repoToken, proxyUrl, issue, pullRequestNumber, commitSha, repo, owner, updateOnly, messageCancelled, messageFailure, messageSuccess, messageSkipped, preformatted, status, } = await (0, config_1.getInputs)();
|
||||
const { allowRepeats, messagePath, messageInput, messageId, refreshMessagePosition, repoToken, proxyUrl, issue, pullRequestNumber, commitSha, repo, owner, updateOnly, messageCancelled, messageFailure, messageSuccess, messageSkipped, preformatted, status, messageFind, messageReplace, } = await (0, config_1.getInputs)();
|
||||
const octokit = github.getOctokit(repoToken);
|
||||
const message = await (0, message_1.getMessage)({
|
||||
let message = await (0, message_1.getMessage)({
|
||||
messagePath,
|
||||
messageInput,
|
||||
messageSkipped,
|
||||
|
|
@ -60,25 +60,31 @@ const run = async () => {
|
|||
core.setOutput('comment-created', 'false');
|
||||
return;
|
||||
}
|
||||
let existingCommentId;
|
||||
let existingComment;
|
||||
if (!allowRepeats) {
|
||||
core.debug('repeat comments are disallowed, checking for existing');
|
||||
existingCommentId = await (0, comments_1.getExistingCommentId)(octokit, owner, repo, issueNumber, messageId);
|
||||
if (existingCommentId) {
|
||||
core.debug(`existing comment found with id: ${existingCommentId}`);
|
||||
existingComment = await (0, comments_1.getExistingComment)(octokit, owner, repo, issueNumber, messageId);
|
||||
if (existingComment) {
|
||||
core.debug(`existing comment found with id: ${existingComment.id}`);
|
||||
}
|
||||
}
|
||||
// if no existing comment and updateOnly is true, exit
|
||||
if (!existingCommentId && updateOnly) {
|
||||
if (!existingComment && updateOnly) {
|
||||
core.info('no existing comment found and update-only is true, exiting');
|
||||
core.setOutput('comment-created', 'false');
|
||||
return;
|
||||
}
|
||||
let comment;
|
||||
const body = `${messageId}\n\n${message}`;
|
||||
if ((messageFind === null || messageFind === void 0 ? void 0 : messageFind.length) && ((messageReplace === null || messageReplace === void 0 ? void 0 : messageReplace.length) || message) && (existingComment === null || existingComment === void 0 ? void 0 : existingComment.body)) {
|
||||
message = (0, message_1.findAndReplaceInMessage)(messageFind, (messageReplace === null || messageReplace === void 0 ? void 0 : messageReplace.length) ? messageReplace : [message], (0, message_1.removeMessageHeader)(existingComment.body));
|
||||
}
|
||||
if (!message) {
|
||||
throw new Error('no message, check your message inputs');
|
||||
}
|
||||
const body = (0, message_1.addMessageHeader)(messageId, message);
|
||||
if (proxyUrl) {
|
||||
comment = await (0, proxy_1.createCommentProxy)({
|
||||
commentId: existingCommentId,
|
||||
commentId: existingComment === null || existingComment === void 0 ? void 0 : existingComment.id,
|
||||
owner,
|
||||
repo,
|
||||
issueNumber,
|
||||
|
|
@ -86,15 +92,15 @@ const run = async () => {
|
|||
repoToken,
|
||||
proxyUrl,
|
||||
});
|
||||
core.setOutput(existingCommentId ? 'comment-updated' : 'comment-created', 'true');
|
||||
core.setOutput((existingComment === null || existingComment === void 0 ? void 0 : existingComment.id) ? 'comment-updated' : 'comment-created', 'true');
|
||||
}
|
||||
else if (existingCommentId) {
|
||||
else if (existingComment === null || existingComment === void 0 ? void 0 : existingComment.id) {
|
||||
if (refreshMessagePosition) {
|
||||
await (0, comments_1.deleteComment)(octokit, owner, repo, existingCommentId, body);
|
||||
await (0, comments_1.deleteComment)(octokit, owner, repo, existingComment.id, body);
|
||||
comment = await (0, comments_1.createComment)(octokit, owner, repo, issueNumber, body);
|
||||
}
|
||||
else {
|
||||
comment = await (0, comments_1.updateComment)(octokit, owner, repo, existingCommentId, body);
|
||||
comment = await (0, comments_1.updateComment)(octokit, owner, repo, existingComment.id, body);
|
||||
}
|
||||
core.setOutput('comment-updated', 'true');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getMessageFromPath = exports.getMessage = void 0;
|
||||
exports.findAndReplaceInMessage = exports.removeMessageHeader = exports.addMessageHeader = exports.getMessageFromPath = exports.getMessage = void 0;
|
||||
const promises_1 = __importDefault(require("node:fs/promises"));
|
||||
const files_1 = require("./files");
|
||||
async function getMessage({ messageInput, messagePath, messageCancelled, messageSkipped, messageFailure, messageSuccess, preformatted, status, }) {
|
||||
|
|
@ -28,13 +28,10 @@ async function getMessage({ messageInput, messagePath, messageCancelled, message
|
|||
message = messageInput;
|
||||
}
|
||||
}
|
||||
if (!message) {
|
||||
throw new Error('no message, check your message inputs');
|
||||
}
|
||||
if (preformatted) {
|
||||
message = `\`\`\`\n${message}\n\`\`\``;
|
||||
}
|
||||
return message;
|
||||
return message !== null && message !== void 0 ? message : '';
|
||||
}
|
||||
exports.getMessage = getMessage;
|
||||
async function getMessageFromPath(searchPath) {
|
||||
|
|
@ -49,3 +46,36 @@ async function getMessageFromPath(searchPath) {
|
|||
return message;
|
||||
}
|
||||
exports.getMessageFromPath = getMessageFromPath;
|
||||
function addMessageHeader(messageId, message) {
|
||||
return `${messageId}\n\n${message}`;
|
||||
}
|
||||
exports.addMessageHeader = addMessageHeader;
|
||||
function removeMessageHeader(message) {
|
||||
return message.split('\n').slice(2).join('\n');
|
||||
}
|
||||
exports.removeMessageHeader = removeMessageHeader;
|
||||
function splitFind(find) {
|
||||
const matches = find.match(/\/((i|g|m|s|u|y){1,6})$/);
|
||||
if (!matches) {
|
||||
return {
|
||||
regExp: find,
|
||||
modifiers: 'gi',
|
||||
};
|
||||
}
|
||||
const [, modifiers] = matches;
|
||||
const regExp = find.replace(modifiers, '').slice(0, -1);
|
||||
return {
|
||||
regExp,
|
||||
modifiers,
|
||||
};
|
||||
}
|
||||
function findAndReplaceInMessage(find, replace, original) {
|
||||
var _a;
|
||||
let message = original;
|
||||
for (const [i, f] of find.entries()) {
|
||||
const { regExp, modifiers } = splitFind(f);
|
||||
message = message.replace(new RegExp(regExp, modifiers), (_a = replace[i]) !== null && _a !== void 0 ? _a : replace.join('\n'));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
exports.findAndReplaceInMessage = findAndReplaceInMessage;
|
||||
|
|
|
|||
32
package-lock.json
generated
32
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "@mshick/add-pr-comment",
|
||||
"version": "2.6.1",
|
||||
"version": "2.8.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@mshick/add-pr-comment",
|
||||
"version": "2.6.1",
|
||||
"version": "2.8.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/artifact": "^1.1.1",
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
"vitest": "^0.30.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.13.0 || ^18.0.0"
|
||||
"node": "^16.13.0 || ^18.0.0 || ^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact": {
|
||||
|
|
@ -7647,9 +7647,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -9049,9 +9049,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.23",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz",
|
||||
"integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==",
|
||||
"version": "8.4.33",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
|
||||
"integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -9068,7 +9068,7 @@
|
|||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.6",
|
||||
"nanoid": "^3.3.7",
|
||||
"picocolors": "^1.0.0",
|
||||
"source-map-js": "^1.0.2"
|
||||
},
|
||||
|
|
@ -10911,9 +10911,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.3.3.tgz",
|
||||
"integrity": "sha512-MwFlLBO4udZXd+VBcezo3u8mC77YQk+ik+fbc0GZWGgzfbPP+8Kf0fldhARqvSYmtIWoAJ5BXPClUbMTlqFxrA==",
|
||||
"version": "4.3.9",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz",
|
||||
"integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.17.5",
|
||||
|
|
@ -11184,9 +11184,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
|
||||
"integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mshick/add-pr-comment",
|
||||
"version": "2.6.1",
|
||||
"version": "2.8.2",
|
||||
"description": "A GitHub Action which adds a comment to a Pull Request Issue.",
|
||||
"keywords": [
|
||||
"GitHub",
|
||||
|
|
@ -25,9 +25,9 @@
|
|||
"build": "del-cli dist && tsc && ncc build --source-map",
|
||||
"clean": "rm -rf node_modules dist package-lock.json __tests__/runner/**/*",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"prepare": "npm run build && git add lib dist",
|
||||
"release": "npm run build && np --no-publish",
|
||||
"test": "vitest run",
|
||||
"version": "npm run build && git add lib dist",
|
||||
"watch": "vitest"
|
||||
},
|
||||
"prettier": {
|
||||
|
|
@ -148,6 +148,6 @@
|
|||
"vitest": "^0.30.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.13.0 || ^18.0.0"
|
||||
"node": "^16.13.0 || ^18.0.0 || ^20.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
import { GitHub } from '@actions/github/lib/utils'
|
||||
import { Endpoints } from '@octokit/types'
|
||||
import {
|
||||
CreateIssueCommentResponseData,
|
||||
ExistingIssueComment,
|
||||
ExistingIssueCommentResponseData,
|
||||
} from './types'
|
||||
|
||||
export type CreateIssueCommentResponseData =
|
||||
Endpoints['POST /repos/{owner}/{repo}/issues/{issue_number}/comments']['response']['data']
|
||||
|
||||
export async function getExistingCommentId(
|
||||
export async function getExistingComment(
|
||||
octokit: InstanceType<typeof GitHub>,
|
||||
owner: string,
|
||||
repo: string,
|
||||
issueNumber: number,
|
||||
messageId: string,
|
||||
): Promise<number | undefined> {
|
||||
): Promise<ExistingIssueComment | undefined> {
|
||||
const parameters = {
|
||||
owner,
|
||||
repo,
|
||||
|
|
@ -18,7 +19,7 @@ export async function getExistingCommentId(
|
|||
per_page: 100,
|
||||
}
|
||||
|
||||
let found
|
||||
let found: ExistingIssueCommentResponseData | undefined
|
||||
|
||||
for await (const comments of octokit.paginate.iterator(
|
||||
octokit.rest.issues.listComments,
|
||||
|
|
@ -33,7 +34,12 @@ export async function getExistingCommentId(
|
|||
}
|
||||
}
|
||||
|
||||
return found?.id
|
||||
if (found) {
|
||||
const { id, body } = found
|
||||
return { id, body }
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
export async function updateComment(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ export async function getInputs(): Promise<Inputs> {
|
|||
const messageId = messageIdInput === '' ? 'add-pr-comment' : `add-pr-comment:${messageIdInput}`
|
||||
const messageInput = core.getInput('message', { required: false })
|
||||
const messagePath = core.getInput('message-path', { required: false })
|
||||
const messageFind = core.getMultilineInput('find', { required: false })
|
||||
const messageReplace = core.getMultilineInput('replace', { required: false })
|
||||
const repoOwner = core.getInput('repo-owner', { required: true })
|
||||
const repoName = core.getInput('repo-name', { required: true })
|
||||
const repoToken = core.getInput('repo-token', { required: true })
|
||||
|
|
@ -41,6 +43,8 @@ export async function getInputs(): Promise<Inputs> {
|
|||
messageCancelled,
|
||||
messageSkipped,
|
||||
messagePath,
|
||||
messageFind,
|
||||
messageReplace,
|
||||
preformatted,
|
||||
proxyUrl,
|
||||
pullRequestNumber: payload.pull_request?.number,
|
||||
|
|
|
|||
54
src/main.ts
54
src/main.ts
|
|
@ -1,16 +1,16 @@
|
|||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import {
|
||||
CreateIssueCommentResponseData,
|
||||
createComment,
|
||||
deleteComment,
|
||||
getExistingCommentId,
|
||||
updateComment,
|
||||
} from './comments'
|
||||
import { createComment, deleteComment, getExistingComment, updateComment } from './comments'
|
||||
import { getInputs } from './config'
|
||||
import { getIssueNumberFromCommitPullsList } from './issues'
|
||||
import { getMessage } from './message'
|
||||
import {
|
||||
addMessageHeader,
|
||||
findAndReplaceInMessage,
|
||||
getMessage,
|
||||
removeMessageHeader,
|
||||
} from './message'
|
||||
import { createCommentProxy } from './proxy'
|
||||
import { CreateIssueCommentResponseData, ExistingIssueComment } from './types'
|
||||
|
||||
const run = async (): Promise<void> => {
|
||||
try {
|
||||
|
|
@ -34,11 +34,13 @@ const run = async (): Promise<void> => {
|
|||
messageSkipped,
|
||||
preformatted,
|
||||
status,
|
||||
messageFind,
|
||||
messageReplace,
|
||||
} = await getInputs()
|
||||
|
||||
const octokit = github.getOctokit(repoToken)
|
||||
|
||||
const message = await getMessage({
|
||||
let message = await getMessage({
|
||||
messagePath,
|
||||
messageInput,
|
||||
messageSkipped,
|
||||
|
|
@ -68,20 +70,20 @@ const run = async (): Promise<void> => {
|
|||
return
|
||||
}
|
||||
|
||||
let existingCommentId
|
||||
let existingComment: ExistingIssueComment | undefined
|
||||
|
||||
if (!allowRepeats) {
|
||||
core.debug('repeat comments are disallowed, checking for existing')
|
||||
|
||||
existingCommentId = await getExistingCommentId(octokit, owner, repo, issueNumber, messageId)
|
||||
existingComment = await getExistingComment(octokit, owner, repo, issueNumber, messageId)
|
||||
|
||||
if (existingCommentId) {
|
||||
core.debug(`existing comment found with id: ${existingCommentId}`)
|
||||
if (existingComment) {
|
||||
core.debug(`existing comment found with id: ${existingComment.id}`)
|
||||
}
|
||||
}
|
||||
|
||||
// if no existing comment and updateOnly is true, exit
|
||||
if (!existingCommentId && updateOnly) {
|
||||
if (!existingComment && updateOnly) {
|
||||
core.info('no existing comment found and update-only is true, exiting')
|
||||
core.setOutput('comment-created', 'false')
|
||||
return
|
||||
|
|
@ -89,11 +91,23 @@ const run = async (): Promise<void> => {
|
|||
|
||||
let comment: CreateIssueCommentResponseData | null | undefined
|
||||
|
||||
const body = `${messageId}\n\n${message}`
|
||||
if (messageFind?.length && (messageReplace?.length || message) && existingComment?.body) {
|
||||
message = findAndReplaceInMessage(
|
||||
messageFind,
|
||||
messageReplace?.length ? messageReplace : [message],
|
||||
removeMessageHeader(existingComment.body),
|
||||
)
|
||||
}
|
||||
|
||||
if (!message) {
|
||||
throw new Error('no message, check your message inputs')
|
||||
}
|
||||
|
||||
const body = addMessageHeader(messageId, message)
|
||||
|
||||
if (proxyUrl) {
|
||||
comment = await createCommentProxy({
|
||||
commentId: existingCommentId,
|
||||
commentId: existingComment?.id,
|
||||
owner,
|
||||
repo,
|
||||
issueNumber,
|
||||
|
|
@ -101,13 +115,13 @@ const run = async (): Promise<void> => {
|
|||
repoToken,
|
||||
proxyUrl,
|
||||
})
|
||||
core.setOutput(existingCommentId ? 'comment-updated' : 'comment-created', 'true')
|
||||
} else if (existingCommentId) {
|
||||
core.setOutput(existingComment?.id ? 'comment-updated' : 'comment-created', 'true')
|
||||
} else if (existingComment?.id) {
|
||||
if (refreshMessagePosition) {
|
||||
await deleteComment(octokit, owner, repo, existingCommentId, body)
|
||||
await deleteComment(octokit, owner, repo, existingComment.id, body)
|
||||
comment = await createComment(octokit, owner, repo, issueNumber, body)
|
||||
} else {
|
||||
comment = await updateComment(octokit, owner, repo, existingCommentId, body)
|
||||
comment = await updateComment(octokit, owner, repo, existingComment.id, body)
|
||||
}
|
||||
core.setOutput('comment-updated', 'true')
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export async function getMessage({
|
|||
| 'messagePath'
|
||||
| 'preformatted'
|
||||
| 'status'
|
||||
>) {
|
||||
>): Promise<string> {
|
||||
let message
|
||||
|
||||
if (status === 'success' && messageSuccess) {
|
||||
|
|
@ -48,15 +48,11 @@ export async function getMessage({
|
|||
}
|
||||
}
|
||||
|
||||
if (!message) {
|
||||
throw new Error('no message, check your message inputs')
|
||||
}
|
||||
|
||||
if (preformatted) {
|
||||
message = `\`\`\`\n${message}\n\`\`\``
|
||||
}
|
||||
|
||||
return message
|
||||
return message ?? ''
|
||||
}
|
||||
|
||||
export async function getMessageFromPath(searchPath: string) {
|
||||
|
|
@ -74,3 +70,45 @@ export async function getMessageFromPath(searchPath: string) {
|
|||
|
||||
return message
|
||||
}
|
||||
|
||||
export function addMessageHeader(messageId: string, message: string) {
|
||||
return `${messageId}\n\n${message}`
|
||||
}
|
||||
|
||||
export function removeMessageHeader(message: string) {
|
||||
return message.split('\n').slice(2).join('\n')
|
||||
}
|
||||
|
||||
function splitFind(find: string) {
|
||||
const matches = find.match(/\/((i|g|m|s|u|y){1,6})$/)
|
||||
|
||||
if (!matches) {
|
||||
return {
|
||||
regExp: find,
|
||||
modifiers: 'gi',
|
||||
}
|
||||
}
|
||||
|
||||
const [, modifiers] = matches
|
||||
const regExp = find.replace(modifiers, '').slice(0, -1)
|
||||
|
||||
return {
|
||||
regExp,
|
||||
modifiers,
|
||||
}
|
||||
}
|
||||
|
||||
export function findAndReplaceInMessage(
|
||||
find: string[],
|
||||
replace: string[],
|
||||
original: string,
|
||||
): string {
|
||||
let message = original
|
||||
|
||||
for (const [i, f] of find.entries()) {
|
||||
const { regExp, modifiers } = splitFind(f)
|
||||
message = message.replace(new RegExp(regExp, modifiers), replace[i] ?? replace.join('\n'))
|
||||
}
|
||||
|
||||
return message
|
||||
}
|
||||
|
|
|
|||
12
src/types.ts
12
src/types.ts
|
|
@ -1,3 +1,5 @@
|
|||
import { Endpoints } from '@octokit/types'
|
||||
|
||||
export interface Inputs {
|
||||
allowRepeats: boolean
|
||||
attachPath?: string[]
|
||||
|
|
@ -6,6 +8,8 @@ export interface Inputs {
|
|||
messageInput?: string
|
||||
messageId: string
|
||||
messagePath?: string
|
||||
messageFind?: string[]
|
||||
messageReplace?: string[]
|
||||
messageSuccess?: string
|
||||
messageFailure?: string
|
||||
messageCancelled?: string
|
||||
|
|
@ -20,3 +24,11 @@ export interface Inputs {
|
|||
owner: string
|
||||
updateOnly: boolean
|
||||
}
|
||||
|
||||
export type CreateIssueCommentResponseData =
|
||||
Endpoints['POST /repos/{owner}/{repo}/issues/{issue_number}/comments']['response']['data']
|
||||
|
||||
export type ExistingIssueCommentResponseData =
|
||||
Endpoints['GET /repos/{owner}/{repo}/issues/{issue_number}/comments']['response']['data'][0]
|
||||
|
||||
export type ExistingIssueComment = Pick<ExistingIssueCommentResponseData, 'id' | 'body'>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue