This commit is contained in:
John McCall 2024-03-16 14:23:32 -04:00
parent 1f2fd3a2fe
commit fc92d2c06e
5 changed files with 72 additions and 83 deletions

View File

@ -7,17 +7,27 @@ import { expect } from '@jest/globals'
import { equal } from 'assert'
import * as axios from 'axios'
describe('wait.ts', () => {
describe('fetchPullRequest.ts', () => {
it('throws an invalid number', async () => {
const input = parseInt('foo', 10)
expect(isNaN(input)).toBe(true)
const pr_number = parseInt('foo', 10)
const token = 'thisisatoken'
expect(isNaN(pr_number)).toBe(true)
await expect(fetchPullRequest('test', input)).rejects.toThrow('Pull request number input is not a number.')
await expect(fetchPullRequest('test', pr_number, token)).rejects.toThrow('Pull request input is not a number.')
})
// it('returns with valid inputs', async () => {
// const res: any = fetchPullRequest('lowlydba/dba-multitool', 1)
// expect(res.length > 0)
it('returns with valid inputs', async () => {
const res: any = fetchPullRequest('lowlydba/dba-multitool', 1, 'token-here')
expect(res.length > 0)
})
it('throws for a 404 pull request', async () => {
const pr_number = 99999
const token = 'thisisatoken'
const repo = 'lowlydba/notreal'
expect(isNaN(pr_number)).toBe(false)
await expect(fetchPullRequest(repo, pr_number, token)).rejects.toThrow('AxiosError: Request failed with status code 404')
})
// })
})

View File

@ -30,7 +30,7 @@ describe('action', () => {
setOutputMock = jest.spyOn(core, 'setOutput').mockImplementation()
})
it('sets the time output', async () => {
it('runs successfully', async () => {
// Set the action's inputs as return values from core.getInput()
getInputMock.mockImplementation(name => {
switch (name) {
@ -43,44 +43,30 @@ describe('action', () => {
await main.run()
expect(runMock).toHaveReturned()
// Verify that all of the core library functions were called correctly
expect(debugMock).toHaveBeenNthCalledWith(1, 'Waiting 500 milliseconds ...')
expect(debugMock).toHaveBeenNthCalledWith(
2,
expect.stringMatching(timeRegex)
)
expect(debugMock).toHaveBeenNthCalledWith(
3,
expect.stringMatching(timeRegex)
)
expect(setOutputMock).toHaveBeenNthCalledWith(
1,
'time',
expect.stringMatching(timeRegex)
)
expect(errorMock).not.toHaveBeenCalled()
})
it('sets a failed status', async () => {
// Set the action's inputs as return values from core.getInput()
getInputMock.mockImplementation(name => {
switch (name) {
case 'milliseconds':
return 'this is not a number'
default:
return ''
}
})
// it('sets a failed status', async () => {
// // Set the action's inputs as return values from core.getInput()
// getInputMock.mockImplementation(name => {
// switch (name) {
// case 'pr-number':
// return 'this is not a number'
// case 'token':
// return 'some-token-thing'
// case 'repository':
// return 'lowlydba/require-all-codeowners'
// default:
// return ''
// }
// })
await main.run()
expect(runMock).toHaveReturned()
// await main.run()
// expect(runMock).toHaveReturned()
// Verify that all of the core library functions were called correctly
expect(setFailedMock).toHaveBeenNthCalledWith(
1,
'milliseconds not a number'
)
expect(errorMock).not.toHaveBeenCalled()
})
// // Verify that all of the core library functions were called correctly
// expect(setFailedMock).toHaveBeenNthCalledWith(
// 1,
// 'Pull request input is not a number.'
// )
// })
})

View File

@ -11,10 +11,10 @@ inputs:
description: "The number of the pull request."
required: true
default: "999"
token:
repo-token:
description: "Github token for authentication."
required: false
default: ${{ secets.GITHUB_TOKEN }}
default: ${{ github.token }}
repository:
description: "owner/repository of pull request."
required: false

View File

@ -6,14 +6,21 @@ import axios from 'axios';
* @param prNumber The number of the pull request.
* @returns {Promise<axios.AxiosResponse>}
*/
export async function fetchPullRequest(repository: string, prNumber: number): Promise<axios.AxiosResponse> {
export async function fetchPullRequest(repository: string, prNumber: number, token: string): Promise<axios.AxiosResponse> {
if (isNaN(prNumber)) {
throw new Error(`Pull request number input is not a number.`)
throw new Error(`Pull request input is not a number.`)
}
const url: string = `https://github.com/${repository}/pull/${prNumber}`;
let res = await axios.get(url)
if (res.status != 200) {
throw new Error(`Unable to access '${url}' - make sure you are authorized.`)
const axiosInstance = axios.create({
baseURL: 'https://github.com/',
headers: {
Authorization: `Bearer ${token}`
}
});
try {
let response = await axiosInstance.get(`/${repository}/pull/${prNumber}`);
return response
}
catch (err) {
throw new Error(`${err}`)
}
return res
}

View File

@ -9,50 +9,36 @@ import { fetchPullRequest } from './fetchPullRequest';
export async function run(): Promise<void> {
try {
core.getIDToken
const token: string = core.getInput('repo-token')
const repo: string = core.getInput('repository')
const prNumber: string = core.getInput('pr-number')
const prNumber: string = core.getInput('pr-number', { required: true })
fetchPullRequest(repo, parseInt(prNumber))
fetchPullRequest(repo, parseInt(prNumber), token)
.then(function (response) {
const $ = cheerio.load(response.data)
const sidebarContext = '.sidebar-assignee'
const codeownerSelector = 'button[id*="codeowner-"]'
const pendingCodeOwnerSelector = 'tool-tip[for*="review-"]'
// Codeowners
const codeowner: Array<String> = $(codeownerSelector, sidebarContext).map((i, x) => $(x).attr('id')?.split('-')[1].trim()).toArray()
const countCodeowner: number = codeowner.length
// Pending CodeOwners
const pendingCodeowner: Array<String> = $(codeownerSelector, sidebarContext).map((i, x) => $(x).attr('id')?.split('-')[1].trim()).toArray()
const countCodeowner: number = pendingCodeowner.length
if (countCodeowner < 1) {
core.notice("No code owners detected in the pull request.")
if (countCodeowner === 0) {
core.notice("No pending code owners detected in the pull request.")
core.setOutput('numPendingCodeOwner', countCodeowner)
return core.ExitCode.Success
}
// Pending
const pending: Array<String> = []
$(pendingCodeOwnerSelector, sidebarContext).map(function () {
const name = $(this).text().split(' ')[$(this).text().split(' ').length - 1].trim()
if (codeowner.indexOf(name) != -1) { //TODO Find out what the approved message is
pending.push(name)
}
});
const countPending: number = pending.length
if (countPending < countCodeowner) {
core.setFailed("Code owners pending approval: " + pending.sort())
else {
core.setOutput('numPendingCodeOwner', countCodeowner)
core.setFailed(`${countCodeowner} pending CodeOwner reviews.`)
}
core.setOutput('approved', codeowner)
core.setOutput('approved-count', countCodeowner - countPending)
core.setOutput('pending', pending)
core.setOutput('pending-count', countPending)
})
.catch(function (err: Error) {
if (err instanceof Error) core.setFailed(err.message)
throw new Error(err.message)
})
}
catch {
catch (err) {
if (err instanceof Error) core.setFailed(err.message)
}
};