diff --git a/README.md b/README.md index 8d6a7a1..021200d 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ steps: tinybird_token: ${{ secrets.TINYBIRD_TOKEN }} tinybird_datasource: workflow_id: - outcome: ${{ (contains(needs.*.result, 'failure') && 'failure') || 'success' }} + outcome: ${{ ((contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) && 'failure') || 'success' }} ``` ## Inputs diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 89df461..db29a75 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -4,10 +4,12 @@ import { getOctokit } from '@actions/github' import { createWorkflowEvent } from '../src/tb' jest.mock('../src/tb', () => ({ - createWorkflowEvent: jest.fn() + createWorkflowEvent: jest.fn(), + pushToTinybird: jest.fn() })) jest.mock('@actions/core', () => ({ + info: jest.fn(), getInput: jest.fn(), setFailed: jest.fn(), setSecret: jest.fn() @@ -29,25 +31,111 @@ jest.mock('@actions/github', () => ({ getOctokit: jest.fn() })) +// mock the getWorkflowRunAttempt +const mockOctokit = { + rest: { + actions: { + async getWorkflowRunAttempt() { + return { data: { run_started_at: '2020-01-22T19:33:08Z' } } + }, + listJobsForWorkflowRunAttempt: jest.fn() + } + } +} +;(getOctokit as jest.Mock).mockReturnValue(mockOctokit) + describe('run', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + it('should send custom outcome', async () => { - // mock the getWorkflowRunAttempt - const mockOctokit = { - rest: { - actions: { - async getWorkflowRunAttempt() { - return { data: { run_started_at: '2020-01-22T19:33:08Z' } } + // mock getInput + // eslint-disable-next-line no-extra-semi + ;(getInput as jest.Mock).mockImplementation((inputName: string) => { + switch (inputName) { + case 'outcome': + return 'custom_outcome' + default: + return 'mocked-input' + } + }) + + // run the function + await run() + + // assertions + expect(createWorkflowEvent).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + expect.anything(), + 'custom_outcome' + ) + }) + + it('should send send successful on all successful jobs', async () => { + mockOctokit.rest.actions.listJobsForWorkflowRunAttempt.mockReturnValue({ + data: { + jobs: [ + { + name: 'Successful Job 1', + conclusion: 'success' + }, + { + name: 'Successful Job 2', + conclusion: 'success' + } + ] + } + }) + + // mock getInput + ;(getInput as jest.Mock).mockImplementation((inputName: string) => { + switch (inputName) { + case 'outcome': + return undefined + default: + return 'mocked-input' + } + }) + + // run the function + await run() + + // assertions + expect(createWorkflowEvent).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + expect.anything(), + 'success' + ) + }) + + it('should send send failed on a failed job', async () => { + mockOctokit.rest.actions.listJobsForWorkflowRunAttempt.mockImplementation( + async () => { + return { + data: { + jobs: [ + { + name: 'Failed Job', + conclusion: 'failure' + }, + { + name: 'Successful Job', + conclusion: 'success' + } + ] } } } - } - ;(getOctokit as jest.Mock).mockReturnValueOnce(mockOctokit) + ) // mock getInput ;(getInput as jest.Mock).mockImplementation((inputName: string) => { switch (inputName) { case 'outcome': - return 'custom_outcome' + return undefined default: return 'mocked-input' } @@ -61,7 +149,49 @@ describe('run', () => { expect.anything(), expect.anything(), expect.anything(), - 'custom_outcome' + 'failure' + ) + }) + + it('should send send failed on a cancelled job', async () => { + mockOctokit.rest.actions.listJobsForWorkflowRunAttempt.mockImplementation( + async () => { + return { + data: { + jobs: [ + { + name: 'Cancelled Job', + conclusion: 'cancelled' + }, + { + name: 'Successful Job', + conclusion: 'success' + } + ] + } + } + } + ) + + // mock getInput + ;(getInput as jest.Mock).mockImplementation((inputName: string) => { + switch (inputName) { + case 'outcome': + return undefined + default: + return 'mocked-input' + } + }) + + // run the function + await run() + + // assertions + expect(createWorkflowEvent).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + expect.anything(), + 'failure' ) }) }) diff --git a/badges/coverage.svg b/badges/coverage.svg index a2e22e1..78218b0 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 59.57%Coverage59.57% \ No newline at end of file +Coverage: 68.08%Coverage68.08% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 608d355..4184cde 100644 --- a/dist/index.js +++ b/dist/index.js @@ -28981,7 +28981,10 @@ async function run() { let failed = false; for (const job of jobs.data.jobs) { core.info(`Job ${job.name} has conclusion: ${job.conclusion}`); - failed = failed || job.conclusion === 'failure'; + failed = + failed || + job.conclusion === 'failure' || + job.conclusion === 'cancelled'; } outcome = failed ? 'failure' : 'success'; } diff --git a/src/main.ts b/src/main.ts index 99b5109..8aaf8ae 100644 --- a/src/main.ts +++ b/src/main.ts @@ -41,7 +41,10 @@ export async function run(): Promise { let failed = false for (const job of jobs.data.jobs) { core.info(`Job ${job.name} has conclusion: ${job.conclusion}`) - failed = failed || job.conclusion === 'failure' + failed = + failed || + job.conclusion === 'failure' || + job.conclusion === 'cancelled' } outcome = failed ? 'failure' : 'success' }