Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/github_actions/actions/checkout-3
Browse files Browse the repository at this point in the history
  • Loading branch information
Barry Gordon authored and GitHub committed Mar 8, 2022
2 parents ea4c57d + 9b9cffd commit ad10532
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 43 deletions.
2 changes: 1 addition & 1 deletion __tests__/container-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('ContainerService', () => {

test('raises an exception', async () => {
await expect(ContainerService.run(container)).rejects.toThrow(
/Failure running container/
/The updater encountered one or more errors/
)
})
})
Expand Down
46 changes: 42 additions & 4 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'path'
import * as core from '@actions/core'
import {Context} from '@actions/github/lib/context'
import {ApiClient} from '../src/api-client'
import {ContainerRuntimeError} from '../src/container-service'
import {Updater, UpdaterFetchError} from '../src/updater'
import {ImageService} from '../src/image-service'
import * as inputs from '../src/inputs'
Expand All @@ -29,6 +30,9 @@ describe('run', () => {
process.env.GITHUB_ACTOR = 'dependabot[bot]'
process.env.GITHUB_WORKSPACE = workspace

process.env.GITHUB_SERVER_URL = 'https://test.dev'
process.env.GITHUB_REPOSITORY = 'foo/bar'

markJobAsProcessedSpy = jest.spyOn(
ApiClient.prototype,
'markJobAsProcessed'
Expand Down Expand Up @@ -130,7 +134,7 @@ describe('run', () => {
await run(context)

expect(core.setFailed).toHaveBeenCalledWith(
new Error('unexpected error retrieving job params')
`Dependabot encountered an unexpected problem\n\nError: unexpected error retrieving job params\n\nFor more information see: https://test.dev/foo/bar/network/updates/1 (write access required)`
)
})

Expand Down Expand Up @@ -159,7 +163,7 @@ describe('run', () => {
await run(context)

expect(core.setFailed).toHaveBeenCalledWith(
new Error('error getting job details')
`Dependabot encountered an unexpected problem\n\nError: error getting job details\n\nFor more information see: https://test.dev/foo/bar/network/updates/1 (write access required)`
)
})

Expand Down Expand Up @@ -239,7 +243,41 @@ describe('run', () => {
})
})

describe('when there is an error running the update', () => {
describe('when there the update container exits with an error signal', () => {
beforeEach(() => {
jest
.spyOn(Updater.prototype, 'runUpdater')
.mockImplementationOnce(
jest.fn(async () =>
Promise.reject(new ContainerRuntimeError('the container melted'))
)
)

context = new Context()
})

test('it fails the workflow', async () => {
await run(context)

expect(core.setFailed).toHaveBeenCalledWith(
`Dependabot encountered an error performing the update\n\nError: the container melted\n\nFor more information see: https://test.dev/foo/bar/network/updates/1 (write access required)`
)
})

test('it relays a failure message to the dependabot service', async () => {
await run(context)

expect(reportJobErrorSpy).toHaveBeenCalledWith({
'error-type': 'actions_workflow_updater',
'error-details': {
'action-error': 'the container melted'
}
})
expect(markJobAsProcessedSpy).toHaveBeenCalled()
})
})

describe('when there is an unexpected error running the update', () => {
beforeEach(() => {
jest
.spyOn(Updater.prototype, 'runUpdater')
Expand All @@ -256,7 +294,7 @@ describe('run', () => {
await run(context)

expect(core.setFailed).toHaveBeenCalledWith(
expect.stringContaining('error running the update')
`Dependabot encountered an error performing the update\n\nError: error running the update\n\nFor more information see: https://test.dev/foo/bar/network/updates/1 (write access required)`
)
})

Expand Down
37 changes: 22 additions & 15 deletions dist/main/index.js

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

2 changes: 1 addition & 1 deletion dist/main/index.js.map

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/container-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {pack} from 'tar-stream'
import {FileFetcherInput, FileUpdaterInput, ProxyConfig} from './config-types'
import {outStream, errStream} from './utils'

class ContainerRuntimeError extends Error {}
export class ContainerRuntimeError extends Error {}

export const ContainerService = {
async storeInput(
Expand Down Expand Up @@ -50,8 +50,9 @@ export const ContainerService = {
if (outcome.StatusCode === 0) {
return true
} else {
core.info(`Failure running container ${container.id}`)
throw new ContainerRuntimeError(
`Failure running container ${container.id}`
'The updater encountered one or more errors.'
)
}
} finally {
Expand Down
64 changes: 44 additions & 20 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ export async function run(context: Context): Promise<void> {
try {
await ImageService.pull(UPDATER_IMAGE_NAME)
await ImageService.pull(PROXY_IMAGE_NAME)
} catch (error) {
core.error('Error fetching updater images')

await failJob(apiClient, error, DependabotErrorType.Image)
} catch (error: any) {
await failJob(
apiClient,
'Error fetching updater images',
error,
DependabotErrorType.Image
)
return
}
core.endGroup()
Expand All @@ -71,29 +74,42 @@ export async function run(context: Context): Promise<void> {
core.info('Starting update process')

await updater.runUpdater()
} catch (error) {
} catch (error: any) {
// If we have encountered a UpdaterFetchError, the Updater will already have
// reported the error and marked the job as processed, so we only need to
// set an exit status.
if (error instanceof UpdaterFetchError) {
setFailed(
'Dependabot was unable to retrieve the files required to perform the update'
'Dependabot was unable to retrieve the files required to perform the update',
null
)
botSay('finished: unable to fetch files')
return
} else {
core.error('Error performing update')
await failJob(apiClient, error, DependabotErrorType.UpdateRun)
await failJob(
apiClient,
'Dependabot encountered an error performing the update',
error,
DependabotErrorType.UpdateRun
)
return
}
}
botSay('finished')
} catch (error) {
} catch (error: any) {
if (error instanceof CredentialFetchingError) {
core.error('Error retrieving update job credentials')
await failJob(apiClient, error, DependabotErrorType.UpdateRun)
await failJob(
apiClient,
'Dependabot was unable to retrieve job credentials',
error,
DependabotErrorType.UpdateRun
)
} else {
await failJob(apiClient, error)
await failJob(
apiClient,
'Dependabot was unable to start the update',
error
)
}

return
Expand All @@ -104,13 +120,14 @@ export async function run(context: Context): Promise<void> {
//
// We output the raw error in the Action logs and defer
// to workflow_run monitoring to detect the job failure.
setFailed(error)
setFailed('Dependabot encountered an unexpected problem', error)
botSay('finished: unexpected error')
}
}

async function failJob(
apiClient: ApiClient,
message: string,
error: Error,
errorType = DependabotErrorType.Unknown
): Promise<void> {
Expand All @@ -121,22 +138,29 @@ async function failJob(
}
})
await apiClient.markJobAsProcessed()
setFailed(error.message)
setFailed(message, error)
botSay('finished: error reported to Dependabot')
}

function botSay(message: string): void {
core.info(`🤖 ~ ${message} ~`)
}

function setFailed(message: string | Error): void {
function setFailed(message: string, error: Error | null): void {
if (jobId) {
message = [message, error, dependabotJobHelp()].filter(Boolean).join('\n\n')
}

core.setFailed(message)
}

function dependabotJobHelp(): string | null {
if (jobId) {
core.error(
`For more information see: ${dependabotJobUrl(
jobId
)} (write access required)`
)
return `For more information see: ${dependabotJobUrl(
jobId
)} (write access required)`
} else {
return null
}
}

Expand Down

0 comments on commit ad10532

Please sign in to comment.