Preformatted messages (#97)

* refactor message creation
This commit is contained in:
Michael Shick 2023-05-05 16:02:36 -04:00 committed by GitHub
parent ef723874d4
commit a251f051d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 154 additions and 85 deletions

View file

@ -62,6 +62,7 @@ jobs:
- uses: ./
with:
preformatted: true
message-id: path
message-path: |
.github/test/file-*.txt

View file

@ -87,6 +87,7 @@ jobs:
| issue | with | Optional issue number override. | no | |
| 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 | |
## Advanced Uses
@ -169,7 +170,6 @@ jobs:
message-part-*.txt
```
### Bring your own issues
You can set an issue id explicitly. Helpful for cases where you want to post
@ -202,7 +202,7 @@ jobs:
issue: ${{ steps.pr.outputs.issue }}
message: |
**Howdie!**
````
```
## Contributors ✨

View file

@ -30,6 +30,7 @@ type Inputs = {
'message-cancelled'?: string
'message-skipped'?: string
'update-only'?: string
preformatted?: string
status?: 'success' | 'failure' | 'cancelled' | 'skipped'
}
@ -41,6 +42,7 @@ const defaultInputs: Inputs = {
'repo-token': repoToken,
'message-id': 'add-pr-comment',
'allow-repeats': 'false',
status: 'success',
}
const defaultIssueNumber = 1
@ -95,10 +97,10 @@ const server = setupServer(...handlers)
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(() => {})
// 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())
@ -392,4 +394,17 @@ describe('add-pr-comment action', () => {
await run()
expect(messagePayload?.body).toContain('666')
})
it('wraps a message in a codeblock if preformatted is true', async () => {
inputs.message = undefined
inputs['preformatted'] = 'true'
inputs['message-path'] = messagePath1Fixture
await expect(run()).resolves.not.toThrow()
expect(
`<!-- add-pr-comment:add-pr-comment -->\n\n\`\`\`\n${messagePath1FixturePayload}\n\`\`\``,
).toEqual(messagePayload?.body)
expect(core.setOutput).toHaveBeenCalledWith('comment-created', 'true')
expect(core.setOutput).toHaveBeenCalledWith('comment-id', postIssueCommentsResponse.id)
})
})

View file

@ -56,6 +56,9 @@ inputs:
update-only:
description: "Only update the comment if it already exists."
required: false
preformatted:
description: "Treat message text (from a file or input) as pre-formatted and place it in a codeblock."
required: false
outputs:
comment-created:
description: "Whether a comment was created."

View file

@ -1,27 +1,6 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import { getMessageFromPaths } from './util'
interface Inputs {
allowRepeats: boolean
attachPath?: string[]
commitSha: string
issue?: number
message?: string
messageId: string
messagePath?: string
messageSuccess?: string
messageFailure?: string
messageCancelled?: string
proxyUrl?: string
pullRequestNumber?: number
refreshMessagePosition: boolean
repo: string
repoToken: string
status?: string
owner: string
updateOnly: boolean
}
import { Inputs } from './types'
export async function getInputs(): Promise<Inputs> {
const messageIdInput = core.getInput('message-id', { required: false })
@ -38,52 +17,31 @@ export async function getInputs(): Promise<Inputs> {
const refreshMessagePosition =
core.getInput('refresh-message-position', { required: false }) === 'true'
const updateOnly = core.getInput('update-only', { required: false }) === 'true'
const preformatted = core.getInput('preformatted', { required: false }) === 'true'
if (messageInput && messagePath) {
throw new Error('must specify only one, message or message-path')
}
let message
if (messagePath) {
message = await getMessageFromPaths(messagePath)
} else {
message = messageInput
}
const messageSuccess = core.getInput(`message-success`)
const messageFailure = core.getInput(`message-failure`)
const messageCancelled = core.getInput(`message-cancelled`)
const messageSkipped = core.getInput(`message-skipped`)
if (status === 'success' && messageSuccess) {
message = messageSuccess
}
if (status === 'failure' && messageFailure) {
message = messageFailure
}
if (status === 'cancelled' && messageCancelled) {
message = messageCancelled
}
if (status === 'skipped' && messageSkipped) {
message = messageSkipped
}
if (!message) {
throw new Error('no message, check your message inputs')
}
const { payload } = github.context
return {
allowRepeats,
commitSha: github.context.sha,
issue: issue ? Number(issue) : payload.issue?.number,
message,
messageInput,
messageId: `<!-- ${messageId} -->`,
messageSuccess,
messageFailure,
messageCancelled,
messageSkipped,
messagePath,
preformatted,
proxyUrl,
pullRequestNumber: payload.pull_request?.number,
refreshMessagePosition,

View file

@ -2,36 +2,13 @@ import * as core from '@actions/core'
import * as glob from '@actions/glob'
import fs from 'node:fs/promises'
export async function getMessageFromPaths(searchPath: string) {
let message = ''
const files = await findFiles(searchPath)
for (const [index, path] of files.entries()) {
if (index > 0) {
message += '\n'
}
message += await fs.readFile(path, { encoding: 'utf8' })
}
return message
}
function getDefaultGlobOptions(): glob.GlobOptions {
return {
export async function findFiles(searchPath: string): Promise<string[]> {
const searchResults: string[] = []
const globber = await glob.create(searchPath, {
followSymbolicLinks: true,
implicitDescendants: true,
omitBrokenSymbolicLinks: true,
}
}
export async function findFiles(
searchPath: string,
globOptions?: glob.GlobOptions,
): Promise<string[]> {
const searchResults: string[] = []
const globber = await glob.create(searchPath, globOptions || getDefaultGlobOptions())
})
const rawSearchResults: string[] = await globber.glob()
for (const searchResult of rawSearchResults) {

View file

@ -9,13 +9,15 @@ import {
} from './comments'
import { getInputs } from './config'
import { getIssueNumberFromCommitPullsList } from './issues'
import { getMessage } from './message'
import { createCommentProxy } from './proxy'
const run = async (): Promise<void> => {
try {
const {
allowRepeats,
message,
messagePath,
messageInput,
messageId,
refreshMessagePosition,
repoToken,
@ -26,10 +28,27 @@ const run = async (): Promise<void> => {
repo,
owner,
updateOnly,
messageCancelled,
messageFailure,
messageSuccess,
messageSkipped,
preformatted,
status,
} = await getInputs()
const octokit = github.getOctokit(repoToken)
const message = await getMessage({
messagePath,
messageInput,
messageSkipped,
messageCancelled,
messageSuccess,
messageFailure,
preformatted,
status,
})
let issueNumber
if (issue) {

74
src/message.ts Normal file
View file

@ -0,0 +1,74 @@
import fs from 'node:fs/promises'
import { findFiles } from './files'
import { Inputs } from './types'
export async function getMessage({
messageInput,
messagePath,
messageCancelled,
messageSkipped,
messageFailure,
messageSuccess,
preformatted,
status,
}: Pick<
Inputs,
| 'messageInput'
| 'messageCancelled'
| 'messageSuccess'
| 'messageFailure'
| 'messageSkipped'
| 'messagePath'
| 'preformatted'
| 'status'
>) {
let message
if (status === 'success') {
if (messageSuccess) {
message = messageSuccess
} else if (messagePath) {
message = await getMessageFromPath(messagePath)
} else {
message = messageInput
}
}
if (status === 'failure' && messageFailure) {
message = messageFailure
}
if (status === 'cancelled' && messageCancelled) {
message = messageCancelled
}
if (status === 'skipped' && messageSkipped) {
message = messageSkipped
}
if (!message) {
throw new Error('no message, check your message inputs')
}
if (preformatted) {
message = `\`\`\`\n${message}\n\`\`\``
}
return message
}
export async function getMessageFromPath(searchPath: string) {
let message = ''
const files = await findFiles(searchPath)
for (const [index, path] of files.entries()) {
if (index > 0) {
message += '\n'
}
message += await fs.readFile(path, { encoding: 'utf8' })
}
return message
}

22
src/types.ts Normal file
View file

@ -0,0 +1,22 @@
export interface Inputs {
allowRepeats: boolean
attachPath?: string[]
commitSha: string
issue?: number
messageInput?: string
messageId: string
messagePath?: string
messageSuccess?: string
messageFailure?: string
messageCancelled?: string
messageSkipped?: string
preformatted: boolean
proxyUrl?: string
pullRequestNumber?: number
refreshMessagePosition: boolean
repo: string
repoToken: string
status: string
owner: string
updateOnly: boolean
}