diff --git a/GitGitGadget/trigger-workflow-dispatch.js b/GitGitGadget/trigger-workflow-dispatch.js index 7a85011..6a023c5 100644 --- a/GitGitGadget/trigger-workflow-dispatch.js +++ b/GitGitGadget/trigger-workflow-dispatch.js @@ -44,15 +44,20 @@ const triggerWorkflowDispatch = async (context, token, owner, repo, workflow_id, token = await getInstallationAccessToken(context, installationID) } - const { headers: { date } } = await gitHubAPIRequest( + const response = await gitHubAPIRequest( context, token, 'POST', `/repos/${owner}/${repo}/actions/workflows/${workflow_id}/dispatches`, - { ref, inputs } + { ref, inputs, return_run_details: true } ) - const runs = await waitForWorkflowRun(context, token, owner, repo, workflow_id, new Date(date).toISOString()) + if (response.workflow_run_id) return response + + const date = response.headers?.date || new Date().toISOString() + // Avoid missing the run if its timestamp is slightly earlier than the response. + const after = new Date(Date.parse(date) - 5000).toISOString() + const runs = await waitForWorkflowRun(context, token, owner, repo, workflow_id, after) return runs[0] } diff --git a/__tests__/trigger-workflow-dispatch.test.js b/__tests__/trigger-workflow-dispatch.test.js index 1515d24..66ce0e4 100644 --- a/__tests__/trigger-workflow-dispatch.test.js +++ b/__tests__/trigger-workflow-dispatch.test.js @@ -1,4 +1,11 @@ const mockHTTPSRequest = jest.fn(async (_context, _hostname, method, requestPath) => { + if (method === 'POST' && requestPath === '/repos/hello/world/actions/workflows/run-details.yml/dispatches') { + return { + workflow_run_id: 12345, + run_url: 'https://api.github.com/repos/hello/world/actions/runs/12345', + html_url: 'https://github.com/hello/world/actions/runs/12345' + } + } if (method === 'POST' && requestPath === '/repos/hello/world/actions/workflows/the-workflow.yml/dispatches') { return { headers: { @@ -7,7 +14,7 @@ const mockHTTPSRequest = jest.fn(async (_context, _hostname, method, requestPath } } if (method === 'GET' && requestPath === '/user') return { login: 'the actor' } - if (method === 'GET' && requestPath === '/repos/hello/world/actions/runs?actor=the actor&event=workflow_dispatch&created=2023-01-23T01:23:45.000Z..*') { + if (method === 'GET' && requestPath === '/repos/hello/world/actions/runs?actor=the actor&event=workflow_dispatch&created=2023-01-23T01:23:40.000Z..*') { return { workflow_runs: [ { path: 'not this one.yml' }, @@ -45,13 +52,36 @@ const { privateKey } = generateKeyPairSync('rsa', { }) process.env['GITHUB_APP_PRIVATE_KEY'] = privateKey -test('trigger a workflow_dispatch event and wait for workflow run', async () => { +beforeEach(() => mockHTTPSRequest.mockClear()) + +test('use workflow run details returned by the dispatch', async () => { + const context = {} + const run = await triggerWorkflowDispatch(context, 'my-token', 'hello', 'world', 'run-details.yml', 'HEAD', { abc: 123 }) + expect(run).toEqual({ + workflow_run_id: 12345, + run_url: 'https://api.github.com/repos/hello/world/actions/runs/12345', + html_url: 'https://github.com/hello/world/actions/runs/12345' + }) + expect(mockHTTPSRequest).toHaveBeenCalledTimes(1) + expect(mockHTTPSRequest.mock.calls[0][4]).toEqual({ + ref: 'HEAD', + inputs: { abc: 123 }, + return_run_details: true + }) +}) + +test('fall back to waiting for the workflow run', async () => { const context = {} const run = await triggerWorkflowDispatch(context, 'my-token', 'hello', 'world', 'the-workflow.yml', 'HEAD', { abc: 123 }) expect(run).toEqual({ path: '.github/workflows/the-workflow.yml', breadcrumb: true }) + expect(mockHTTPSRequest.mock.calls[0][4]).toEqual({ + ref: 'HEAD', + inputs: { abc: 123 }, + return_run_details: true + }) }) test('list workflow runs', async () => {