diff --git a/src/hooks/useNotifications.test.ts b/src/hooks/useNotifications.test.ts index 30fb6dcf0..6e245c9c8 100644 --- a/src/hooks/useNotifications.test.ts +++ b/src/hooks/useNotifications.test.ts @@ -237,6 +237,14 @@ describe('hooks/useNotifications.ts', () => { url: 'https://api.github.com/5', }, }, + { + id: 6, + subject: { + title: 'This is a workflow run.', + type: 'WorkflowRun', + url: 'https://api.github.com/6', + }, + }, ]; nock('https://api.github.com') @@ -286,7 +294,7 @@ describe('hooks/useNotifications.ts', () => { expect(result.current.notifications[0].hostname).toBe('github.com'); }); - expect(result.current.notifications[0].notifications.length).toBe(5); + expect(result.current.notifications[0].notifications.length).toBe(6); }); }); }); diff --git a/src/typesGithub.ts b/src/typesGithub.ts index 6a2cbf9ff..d051ab674 100644 --- a/src/typesGithub.ts +++ b/src/typesGithub.ts @@ -219,3 +219,9 @@ export interface CheckSuiteAttributes { status: CheckSuiteStatus | null; branchName: string; } + +export interface WorkflowRunAttributes { + user: string; + statusDisplayName: string; + status: CheckSuiteStatus | null; +} diff --git a/src/utils/state.test.ts b/src/utils/state.test.ts index 7d328aa63..0335dde12 100644 --- a/src/utils/state.test.ts +++ b/src/utils/state.test.ts @@ -8,6 +8,7 @@ import { getDiscussionState, getIssueState, getPullRequestState, + getWorkflowRunAttributes, } from './state'; describe('utils/state.ts', () => { beforeEach(() => { @@ -518,4 +519,51 @@ describe('utils/state.ts', () => { expect(result).toBe('open'); }); }); + + describe('getWorkflowRunState', () => { + it('deploy review workflow run state', async () => { + const mockNotification = { + ...mockedSingleNotification, + subject: { + ...mockedSingleNotification.subject, + title: 'some-user requested your review to deploy to an environment', + }, + }; + + const result = getWorkflowRunAttributes(mockNotification); + + expect(result.user).toBe('some-user'); + expect(result.status).toBe('waiting'); + }); + + it('unknown workflow run state', async () => { + const mockNotification = { + ...mockedSingleNotification, + subject: { + ...mockedSingleNotification.subject, + title: + 'some-user requested your unknown-state to deploy to an environment', + }, + }; + + const result = getWorkflowRunAttributes(mockNotification); + + expect(result.user).toBe('some-user'); + expect(result.status).toBeNull(); + }); + + it('unhandled workflow run title', async () => { + const mockNotification = { + ...mockedSingleNotification, + subject: { + ...mockedSingleNotification.subject, + title: 'unhandled workflow run structure', + }, + }; + + const result = getWorkflowRunAttributes(mockNotification); + + expect(result).toBeNull(); + }); + }); }); diff --git a/src/utils/state.ts b/src/utils/state.ts index 39a26a75c..4d2b79c61 100644 --- a/src/utils/state.ts +++ b/src/utils/state.ts @@ -9,6 +9,7 @@ import { Notification, PullRequestStateType, StateType, + WorkflowRunAttributes, } from '../typesGithub'; import { apiRequestAuth } from './api-requests'; @@ -25,6 +26,8 @@ export async function getNotificationState( return await getIssueState(notification, token); case 'PullRequest': return await getPullRequestState(notification, token); + case 'WorkflowRun': + return getWorkflowRunAttributes(notification)?.status; default: return null; } @@ -59,9 +62,7 @@ export function getCheckSuiteAttributes( return null; } -export function getCheckSuiteStatus( - statusDisplayName: string, -): CheckSuiteStatus { +function getCheckSuiteStatus(statusDisplayName: string): CheckSuiteStatus { switch (statusDisplayName) { case 'cancelled': return 'cancelled'; @@ -151,3 +152,37 @@ export async function getPullRequestState( return pr.state; } + +/** + * Ideally we would be using a GitHub API to fetch the CheckSuite / WorkflowRun state, + * but there isn't an obvious/clean way to do this currently. + */ +export function getWorkflowRunAttributes( + notification: Notification, +): WorkflowRunAttributes | null { + const regexPattern = + /^(?.*?) requested your (?.*?) to deploy to an environment$/; + + const matches = regexPattern.exec(notification.subject.title); + + if (matches) { + const { groups } = matches; + + return { + user: groups.user, + status: getWorkflowRunStatus(groups.statusDisplayName), + statusDisplayName: groups.statusDisplayName, + }; + } + + return null; +} + +function getWorkflowRunStatus(statusDisplayName: string): CheckSuiteStatus { + switch (statusDisplayName) { + case 'review': + return 'waiting'; + default: + return null; + } +}