From 34e6533e70e1a1b34f8241d60ce1f7924afdddbc Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Tue, 24 Aug 2021 11:33:42 +0100 Subject: [PATCH 1/6] Add API client methods for error reporting and failure --- src/api-client.ts | 54 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/api-client.ts b/src/api-client.ts index f09c900..fdcdf07 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -10,6 +10,8 @@ export class JobParameters { ) {} } +// TODO: Populate with enabled values +// TODO: Rescue unsupported values export enum PackageManager { NpmAndYarn = 'npm_and_yarn' } @@ -23,6 +25,15 @@ export type JobDetails = { 'package-manager': PackageManager } +export enum JobErrorType { + Unknown = 'actions_runner_unknown' +} + +export type JobError = { + 'error-type': JobErrorType + 'error-detail': any +} + export type Credential = { type: string host: string @@ -50,8 +61,8 @@ export class APIClient { } async getCredentials(): Promise { - const detailsURL = `/update_jobs/${this.params.jobID}/credentials` - const res = await this.client.get(detailsURL, { + const credentialsURL = `/update_jobs/${this.params.jobID}/credentials` + const res = await this.client.get(credentialsURL, { headers: {Authorization: this.params.credentialsToken} }) if (res.status !== 200) { @@ -60,4 +71,43 @@ export class APIClient { return res.data.data.attributes.credentials } + + async reportJobError(error: JobError): Promise { + const recordErrorURL = `/update_jobs/${this.params.jobID}/record_update_job_error` + const res = await this.client.post(recordErrorURL, error, { + headers: {Authorization: this.params.jobToken} + }) + if (res.status !== 200) { + throw new Error(`Unexpected status code: ${res.status}`) + } + + return res.data.data.attributes + } + + async markJobAsProcessed(): Promise { + const markAsProcessedURL = `/update_jobs/${this.params.jobID}/mark_as_processed` + const res = await this.client.get(markAsProcessedURL, { + headers: {Authorization: this.params.credentialsToken} + }) + if (res.status !== 200) { + throw new Error(`Unexpected status code: ${res.status}`) + } + + return res.data.data.attributes + } + + async failJob(error: Error): Promise { + const jobError = this.jobErrorFor(error) + await this.reportJobError(jobError) + await this.markJobAsProcessed() + } + + private jobErrorFor(error: Error): JobError { + const errorType = JobErrorType.Unknown + + return { + 'error-type': errorType, + 'error-detail': error.message + } + } } From f5b81399b4aaf5862bb351ee231c67d22f87b972 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Wed, 25 Aug 2021 19:14:09 +0100 Subject: [PATCH 2/6] Add a unit test for the action entry point --- __fixtures__/events/default.json | 21 ++++ __tests__/helpers.ts | 12 ++- __tests__/main.test.ts | 158 ++++++++++++++++++++++++++++++- src/main.ts | 12 ++- 4 files changed, 195 insertions(+), 8 deletions(-) create mode 100644 __fixtures__/events/default.json diff --git a/__fixtures__/events/default.json b/__fixtures__/events/default.json new file mode 100644 index 0000000..f6be12a --- /dev/null +++ b/__fixtures__/events/default.json @@ -0,0 +1,21 @@ +{ + "inputs": { + "jobID": "1", + "jobToken": "xxx", + "credentialsToken": "yyy", + "dependabotAPIURL": "http://localhost:9000" + }, + "ref": "main", + "repository": { + "owner": { + "login": "dependabot" + }, + "name": "dependabot-core" + }, + "sender": { + "type": "User" + }, + "installation": null, + "organization": null, + "workflow": "--workflow-yaml-goes-here--" +} diff --git a/__tests__/helpers.ts b/__tests__/helpers.ts index 6cbc29e..2c9ab7b 100644 --- a/__tests__/helpers.ts +++ b/__tests__/helpers.ts @@ -25,7 +25,7 @@ export const removeDanglingUpdaterContainers = async (): Promise => { await docker.pruneContainers() } -export const runFakeDependabotApi = async (port: number): Promise => { +export const runFakeDependabotApi = async (port = 9000): Promise => { const server = spawn('node', [ `${path.join(__dirname, 'server/server.js')}`, `${port}` @@ -44,3 +44,13 @@ export const runFakeDependabotApi = async (port: number): Promise => { server.kill() } } + +export const eventFixturePath = (fixtureName: string): string => { + return path.join( + __dirname, + '..', + '__fixtures__', + 'events', + `${fixtureName}.json` + ) +} diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 3c1f2fe..998b887 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -1,2 +1,156 @@ -// shows how the runner will run a javascript action with env / stdout protocol -test('test runs', () => {}) +import * as core from '@actions/core' +import {Context} from '@actions/github/lib/context' +import {APIClient} from '../src/api-client' +import {Updater} from '../src/updater' +import * as inputs from '../src/inputs' +import {run} from '../src/main' + +import {eventFixturePath} from './helpers' + +// We do not need to build actual containers or run updates for this test. +jest.mock('../src/api-client') +jest.mock('../src/image-service') +jest.mock('../src/updater') + +describe('run', () => { + let context: Context + + beforeEach(async () => { + jest.spyOn(core, 'info').mockImplementation(jest.fn()) + jest.spyOn(core, 'setFailed').mockImplementation(jest.fn()) + }) + + afterEach(async () => { + jest.clearAllMocks() // Reset any mocked classes + }) + + describe('when the run follows the happy path', () => { + beforeAll(() => { + process.env.GITHUB_EVENT_PATH = eventFixturePath('default') + process.env.GITHUB_EVENT_NAME = 'workflow_dispatch' + context = new Context() + }) + + test('it signs off at completion without any errors', async () => { + await run(context) + + expect(core.setFailed).not.toHaveBeenCalled() + expect(core.info).toHaveBeenCalledWith( + expect.stringContaining('🤖 ~fin~') + ) + }) + }) + + describe('when the action is triggered on an unsupported event', () => { + beforeAll(() => { + process.env.GITHUB_EVENT_PATH = eventFixturePath('default') + process.env.GITHUB_EVENT_NAME = 'issue_created' + context = new Context() + }) + + test('it explains the event is unsupported without logging to dependabot-api', async () => { + await run(context) + + expect(core.setFailed).not.toHaveBeenCalled() + expect(core.info).toHaveBeenCalledWith( + expect.stringContaining( + "Dependabot Updater Action does not support 'issue_created' events." + ) + ) + }) + }) + + describe('when there is an error retrieving job parameters', () => { + beforeEach(() => { + jest.spyOn(inputs, 'getJobParameters').mockImplementationOnce( + jest.fn(() => { + throw new Error('unexpected error retrieving job params') + }) + ) + + process.env.GITHUB_EVENT_PATH = eventFixturePath('default') + process.env.GITHUB_EVENT_NAME = 'workflow_dispatch' + context = new Context() + }) + + test('it relays an error to dependabot-api and marks the job as processed', async () => { + await run(context) + + expect(core.setFailed).toHaveBeenCalledWith( + expect.stringContaining('unexpected error retrieving job params') + ) + }) + }) + + describe('when there is an error retrieving job details from DependabotAPI', () => { + beforeEach(() => { + jest + .spyOn(APIClient.prototype, 'getJobDetails') + .mockImplementationOnce( + jest.fn(async () => + Promise.reject(new Error('error getting job details')) + ) + ) + + process.env.GITHUB_EVENT_PATH = eventFixturePath('default') + process.env.GITHUB_EVENT_NAME = 'workflow_dispatch' + context = new Context() + }) + + test('it relays an error to dependabot-api and marks the job as processed', async () => { + await run(context) + + expect(core.setFailed).toHaveBeenCalledWith( + expect.stringContaining('error getting job details') + ) + }) + }) + + describe('when there is an error retrieving job credentials from DependabotAPI', () => { + beforeEach(() => { + jest + .spyOn(APIClient.prototype, 'getCredentials') + .mockImplementationOnce( + jest.fn(async () => + Promise.reject(new Error('error getting credentials')) + ) + ) + + process.env.GITHUB_EVENT_PATH = eventFixturePath('default') + process.env.GITHUB_EVENT_NAME = 'workflow_dispatch' + context = new Context() + }) + + test('it relays an error to dependabot-api and marks the job as processed', async () => { + await run(context) + + expect(core.setFailed).toHaveBeenCalledWith( + expect.stringContaining('error getting credentials') + ) + }) + }) + + describe('when there is an error running the update', () => { + beforeAll(() => { + jest + .spyOn(Updater.prototype, 'runUpdater') + .mockImplementationOnce( + jest.fn(async () => + Promise.reject(new Error('error running the update')) + ) + ) + + process.env.GITHUB_EVENT_PATH = eventFixturePath('default') + process.env.GITHUB_EVENT_NAME = 'workflow_dispatch' + context = new Context() + }) + + test('it relays an error to dependabot-api and marks the job as processed', async () => { + await run(context) + + expect(core.setFailed).toHaveBeenCalledWith( + expect.stringContaining('error running the update') + ) + }) + }) +}) diff --git a/src/main.ts b/src/main.ts index f100120..26e6ed8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,6 @@ import * as core from '@actions/core' import * as github from '@actions/github' +import {Context} from '@actions/github/lib/context' import {getJobParameters} from './inputs' import {ImageService} from './image-service' import {Updater} from './updater' @@ -11,15 +12,15 @@ export const UPDATER_IMAGE_NAME = export const PROXY_IMAGE_NAME = 'docker.pkg.github.com/github/dependabot-update-job-proxy:latest' -async function run(): Promise { +export async function run(context: Context): Promise { try { // Decode JobParameters: - const params = getJobParameters(github.context) + const params = getJobParameters(context) if (params === null) { return // No parameters, nothing to do } - core.info(JSON.stringify(params)) + core.debug(JSON.stringify(params)) core.setSecret(params.jobToken) core.setSecret(params.credentialsToken) @@ -39,9 +40,10 @@ async function run(): Promise { await ImageService.pull(PROXY_IMAGE_NAME) await updater.runUpdater() + core.info('🤖 ~fin~') } catch (error) { - core.setFailed(error.message) + core.setFailed(error) } } -run() +run(github.context) From 5d128b3980b387fca5f38541be1edb94aea30699 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Wed, 25 Aug 2021 20:02:03 +0100 Subject: [PATCH 3/6] Clarify the inner/outer failure loops --- __tests__/main.test.ts | 74 ++++++++++++++++++++++++++++++++++++------ src/api-client.ts | 2 +- src/main.ts | 40 +++++++++++++++-------- 3 files changed, 91 insertions(+), 25 deletions(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 998b887..e243544 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -15,7 +15,19 @@ jest.mock('../src/updater') describe('run', () => { let context: Context + let failJobSpy: any + let markJobAsProcessedSpy: any + let reportJobErrorSpy: any + beforeEach(async () => { + failJobSpy = jest.spyOn(APIClient.prototype, 'failJob') + + markJobAsProcessedSpy = jest.spyOn( + APIClient.prototype, + 'markJobAsProcessed' + ) + reportJobErrorSpy = jest.spyOn(APIClient.prototype, 'reportJobError') + jest.spyOn(core, 'info').mockImplementation(jest.fn()) jest.spyOn(core, 'setFailed').mockImplementation(jest.fn()) }) @@ -39,6 +51,14 @@ describe('run', () => { expect.stringContaining('🤖 ~fin~') ) }) + + test('it defers reporting back to dependabot-api to the updater itself', async () => { + await run(context) + + expect(markJobAsProcessedSpy).not.toHaveBeenCalled() + expect(failJobSpy).not.toHaveBeenCalled() + expect(reportJobErrorSpy).not.toHaveBeenCalled() + }) }) describe('when the action is triggered on an unsupported event', () => { @@ -48,16 +68,20 @@ describe('run', () => { context = new Context() }) - test('it explains the event is unsupported without logging to dependabot-api', async () => { + test('it fails the workflow', async () => { await run(context) expect(core.setFailed).not.toHaveBeenCalled() expect(core.info).toHaveBeenCalledWith( - expect.stringContaining( - "Dependabot Updater Action does not support 'issue_created' events." - ) + "Dependabot Updater Action does not support 'issue_created' events." ) }) + + test('it does not report this failed run to dependabot-api', async () => { + await run(context) + + expect(failJobSpy).not.toHaveBeenCalled() + }) }) describe('when there is an error retrieving job parameters', () => { @@ -73,13 +97,19 @@ describe('run', () => { context = new Context() }) - test('it relays an error to dependabot-api and marks the job as processed', async () => { + test('it fails the workflow with the raw error', async () => { await run(context) expect(core.setFailed).toHaveBeenCalledWith( - expect.stringContaining('unexpected error retrieving job params') + new Error('unexpected error retrieving job params') ) }) + + test('it does not inform dependabot-api as it cannot instantiate a client without the params', async () => { + await run(context) + + expect(failJobSpy).not.toHaveBeenCalled() + }) }) describe('when there is an error retrieving job details from DependabotAPI', () => { @@ -97,13 +127,21 @@ describe('run', () => { context = new Context() }) - test('it relays an error to dependabot-api and marks the job as processed', async () => { + test('it fails the workflow', async () => { await run(context) expect(core.setFailed).toHaveBeenCalledWith( expect.stringContaining('error getting job details') ) }) + + test('it relays a failure message to the dependabot service', async () => { + await run(context) + + expect(failJobSpy).toHaveBeenCalledWith( + new Error('error getting job details') + ) + }) }) describe('when there is an error retrieving job credentials from DependabotAPI', () => { @@ -121,17 +159,25 @@ describe('run', () => { context = new Context() }) - test('it relays an error to dependabot-api and marks the job as processed', async () => { + test('it fails the workflow', async () => { await run(context) expect(core.setFailed).toHaveBeenCalledWith( expect.stringContaining('error getting credentials') ) }) + + test('it relays a failure message to the dependabot service', async () => { + await run(context) + + expect(failJobSpy).toHaveBeenCalledWith( + new Error('error getting credentials') + ) + }) }) describe('when there is an error running the update', () => { - beforeAll(() => { + beforeEach(() => { jest .spyOn(Updater.prototype, 'runUpdater') .mockImplementationOnce( @@ -145,12 +191,20 @@ describe('run', () => { context = new Context() }) - test('it relays an error to dependabot-api and marks the job as processed', async () => { + test('it fails the workflow', async () => { await run(context) expect(core.setFailed).toHaveBeenCalledWith( expect.stringContaining('error running the update') ) }) + + test('it relays a failure message to the dependabot service', async () => { + await run(context) + + expect(failJobSpy).toHaveBeenCalledWith( + new Error('error running the update') + ) + }) }) }) diff --git a/src/api-client.ts b/src/api-client.ts index fdcdf07..3a4bea9 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -26,7 +26,7 @@ export type JobDetails = { } export enum JobErrorType { - Unknown = 'actions_runner_unknown' + Unknown = 'actions_workflow_unknown' } export type JobError = { diff --git a/src/main.ts b/src/main.ts index 26e6ed8..b605334 100644 --- a/src/main.ts +++ b/src/main.ts @@ -27,21 +27,33 @@ export async function run(context: Context): Promise { const client = axios.create({baseURL: params.dependabotAPIURL}) const apiClient = new APIClient(client, params) - const details = await apiClient.getJobDetails() - const credentials = await apiClient.getCredentials() - const updater = new Updater( - UPDATER_IMAGE_NAME, - PROXY_IMAGE_NAME, - apiClient, - details, - credentials - ) - await ImageService.pull(UPDATER_IMAGE_NAME) - await ImageService.pull(PROXY_IMAGE_NAME) - - await updater.runUpdater() - core.info('🤖 ~fin~') + + try { + const details = await apiClient.getJobDetails() + const credentials = await apiClient.getCredentials() + const updater = new Updater( + UPDATER_IMAGE_NAME, + PROXY_IMAGE_NAME, + apiClient, + details, + credentials + ) + await ImageService.pull(UPDATER_IMAGE_NAME) + await ImageService.pull(PROXY_IMAGE_NAME) + + await updater.runUpdater() + core.info('🤖 ~fin~') + } catch (error) { + // Update Dependabot API on the job failure + apiClient.failJob(error) + core.setFailed(error.message) + } } catch (error) { + // If we've reached this point, we do not have a viable + // API client to report back to Dependabot API. + // + // We output the raw error in the Action logs and defer + // to workflow_run monitoring to detect the job failure. core.setFailed(error) } } From 533bb57a0edf4d43a2ea7a77089761ed86f333e2 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Wed, 25 Aug 2021 20:39:40 +0100 Subject: [PATCH 4/6] Move the failJob method up to the main file --- __tests__/main.test.ts | 34 +++++++++++++++++++--------------- src/api-client.ts | 21 +-------------------- src/main.ts | 18 +++++++++++++++++- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index e243544..de29be6 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -15,13 +15,10 @@ jest.mock('../src/updater') describe('run', () => { let context: Context - let failJobSpy: any let markJobAsProcessedSpy: any let reportJobErrorSpy: any beforeEach(async () => { - failJobSpy = jest.spyOn(APIClient.prototype, 'failJob') - markJobAsProcessedSpy = jest.spyOn( APIClient.prototype, 'markJobAsProcessed' @@ -56,7 +53,6 @@ describe('run', () => { await run(context) expect(markJobAsProcessedSpy).not.toHaveBeenCalled() - expect(failJobSpy).not.toHaveBeenCalled() expect(reportJobErrorSpy).not.toHaveBeenCalled() }) }) @@ -80,7 +76,8 @@ describe('run', () => { test('it does not report this failed run to dependabot-api', async () => { await run(context) - expect(failJobSpy).not.toHaveBeenCalled() + expect(markJobAsProcessedSpy).not.toHaveBeenCalled() + expect(reportJobErrorSpy).not.toHaveBeenCalled() }) }) @@ -108,7 +105,8 @@ describe('run', () => { test('it does not inform dependabot-api as it cannot instantiate a client without the params', async () => { await run(context) - expect(failJobSpy).not.toHaveBeenCalled() + expect(markJobAsProcessedSpy).not.toHaveBeenCalled() + expect(reportJobErrorSpy).not.toHaveBeenCalled() }) }) @@ -138,9 +136,11 @@ describe('run', () => { test('it relays a failure message to the dependabot service', async () => { await run(context) - expect(failJobSpy).toHaveBeenCalledWith( - new Error('error getting job details') - ) + expect(reportJobErrorSpy).toHaveBeenCalledWith({ + 'error-type': 'actions_workflow_unknown', + 'error-detail': 'error getting job details' + }) + expect(markJobAsProcessedSpy).toHaveBeenCalled() }) }) @@ -170,9 +170,11 @@ describe('run', () => { test('it relays a failure message to the dependabot service', async () => { await run(context) - expect(failJobSpy).toHaveBeenCalledWith( - new Error('error getting credentials') - ) + expect(reportJobErrorSpy).toHaveBeenCalledWith({ + 'error-type': 'actions_workflow_unknown', + 'error-detail': 'error getting credentials' + }) + expect(markJobAsProcessedSpy).toHaveBeenCalled() }) }) @@ -202,9 +204,11 @@ describe('run', () => { test('it relays a failure message to the dependabot service', async () => { await run(context) - expect(failJobSpy).toHaveBeenCalledWith( - new Error('error running the update') - ) + expect(reportJobErrorSpy).toHaveBeenCalledWith({ + 'error-type': 'actions_workflow_unknown', + 'error-detail': 'error running the update' + }) + expect(markJobAsProcessedSpy).toHaveBeenCalled() }) }) }) diff --git a/src/api-client.ts b/src/api-client.ts index 3a4bea9..1dac7bc 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -25,12 +25,8 @@ export type JobDetails = { 'package-manager': PackageManager } -export enum JobErrorType { - Unknown = 'actions_workflow_unknown' -} - export type JobError = { - 'error-type': JobErrorType + 'error-type': string 'error-detail': any } @@ -95,19 +91,4 @@ export class APIClient { return res.data.data.attributes } - - async failJob(error: Error): Promise { - const jobError = this.jobErrorFor(error) - await this.reportJobError(jobError) - await this.markJobAsProcessed() - } - - private jobErrorFor(error: Error): JobError { - const errorType = JobErrorType.Unknown - - return { - 'error-type': errorType, - 'error-detail': error.message - } - } } diff --git a/src/main.ts b/src/main.ts index b605334..2e0f4d8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -12,6 +12,10 @@ export const UPDATER_IMAGE_NAME = export const PROXY_IMAGE_NAME = 'docker.pkg.github.com/github/dependabot-update-job-proxy:latest' +export enum DependabotErrorType { + Unknown = 'actions_workflow_unknown' +} + export async function run(context: Context): Promise { try { // Decode JobParameters: @@ -45,7 +49,7 @@ export async function run(context: Context): Promise { core.info('🤖 ~fin~') } catch (error) { // Update Dependabot API on the job failure - apiClient.failJob(error) + failJob(apiClient, error) core.setFailed(error.message) } } catch (error) { @@ -58,4 +62,16 @@ export async function run(context: Context): Promise { } } +async function failJob( + apiClient: APIClient, + error: Error, + errorType = DependabotErrorType.Unknown +): Promise { + await apiClient.reportJobError({ + 'error-type': errorType, + 'error-detail': error.message + }) + await apiClient.markJobAsProcessed() +} + run(github.context) From 70d83e32e3545f0bb4cea9f11a2c80ee7bd96d78 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Wed, 25 Aug 2021 20:54:09 +0100 Subject: [PATCH 5/6] Return meaningful error types depending on what failed --- __tests__/main.test.ts | 37 ++++++++++++++++++++++++++++++++++++- src/main.ts | 23 +++++++++++++++++++---- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index de29be6..8e467da 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -2,6 +2,7 @@ import * as core from '@actions/core' import {Context} from '@actions/github/lib/context' import {APIClient} from '../src/api-client' import {Updater} from '../src/updater' +import {ImageService} from '../src/image-service' import * as inputs from '../src/inputs' import {run} from '../src/main' @@ -178,6 +179,40 @@ describe('run', () => { }) }) + describe('when there is an error pulling images', () => { + beforeEach(() => { + jest + .spyOn(ImageService, 'pull') + .mockImplementationOnce( + jest.fn(async () => + Promise.reject(new Error('error pulling an image')) + ) + ) + + process.env.GITHUB_EVENT_PATH = eventFixturePath('default') + process.env.GITHUB_EVENT_NAME = 'workflow_dispatch' + context = new Context() + }) + + test('it fails the workflow', async () => { + await run(context) + + expect(core.setFailed).toHaveBeenCalledWith( + expect.stringContaining('error pulling an image') + ) + }) + + test('it relays a failure message to the dependabot service', async () => { + await run(context) + + expect(reportJobErrorSpy).toHaveBeenCalledWith({ + 'error-type': 'actions_workflow_image', + 'error-detail': 'error pulling an image' + }) + expect(markJobAsProcessedSpy).toHaveBeenCalled() + }) + }) + describe('when there is an error running the update', () => { beforeEach(() => { jest @@ -205,7 +240,7 @@ describe('run', () => { await run(context) expect(reportJobErrorSpy).toHaveBeenCalledWith({ - 'error-type': 'actions_workflow_unknown', + 'error-type': 'actions_workflow_updater', 'error-detail': 'error running the update' }) expect(markJobAsProcessedSpy).toHaveBeenCalled() diff --git a/src/main.ts b/src/main.ts index 2e0f4d8..4baedca 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,7 +13,9 @@ export const PROXY_IMAGE_NAME = 'docker.pkg.github.com/github/dependabot-update-job-proxy:latest' export enum DependabotErrorType { - Unknown = 'actions_workflow_unknown' + Unknown = 'actions_workflow_unknown', + Image = 'actions_workflow_image', + UpdateRun = 'actions_workflow_updater' } export async function run(context: Context): Promise { @@ -42,10 +44,23 @@ export async function run(context: Context): Promise { details, credentials ) - await ImageService.pull(UPDATER_IMAGE_NAME) - await ImageService.pull(PROXY_IMAGE_NAME) - await updater.runUpdater() + try { + await ImageService.pull(UPDATER_IMAGE_NAME) + await ImageService.pull(PROXY_IMAGE_NAME) + } catch (error) { + failJob(apiClient, error, DependabotErrorType.Image) + core.setFailed(error.message) + return + } + + try { + await updater.runUpdater() + } catch (error) { + failJob(apiClient, error, DependabotErrorType.UpdateRun) + core.setFailed(error.message) + return + } core.info('🤖 ~fin~') } catch (error) { // Update Dependabot API on the job failure From 4fb3a24af3d6718257a94a975f2709edeebb2d60 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Wed, 25 Aug 2021 21:39:04 +0100 Subject: [PATCH 6/6] DRY out use of core.setFailed --- src/main.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main.ts b/src/main.ts index 4baedca..764531d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -49,23 +49,20 @@ export async function run(context: Context): Promise { await ImageService.pull(UPDATER_IMAGE_NAME) await ImageService.pull(PROXY_IMAGE_NAME) } catch (error) { - failJob(apiClient, error, DependabotErrorType.Image) - core.setFailed(error.message) + await failJob(apiClient, error, DependabotErrorType.Image) return } try { await updater.runUpdater() } catch (error) { - failJob(apiClient, error, DependabotErrorType.UpdateRun) - core.setFailed(error.message) + await failJob(apiClient, error, DependabotErrorType.UpdateRun) return } core.info('🤖 ~fin~') } catch (error) { // Update Dependabot API on the job failure - failJob(apiClient, error) - core.setFailed(error.message) + await failJob(apiClient, error) } } catch (error) { // If we've reached this point, we do not have a viable @@ -87,6 +84,7 @@ async function failJob( 'error-detail': error.message }) await apiClient.markJobAsProcessed() + core.setFailed(error.message) } run(github.context)