Move result-index availability check to monitorQuery

This commit is contained in:
Koen Vlaswinkel
2022-09-02 15:47:17 +02:00
parent 57666bbbe3
commit 80867e6f58
2 changed files with 45 additions and 41 deletions

View File

@@ -10,6 +10,8 @@ import { RemoteQuery } from './remote-query';
import { RemoteQueryFailureIndexItem, RemoteQueryResultIndex, RemoteQuerySuccessIndexItem } from './remote-query-result-index'; import { RemoteQueryFailureIndexItem, RemoteQueryResultIndex, RemoteQuerySuccessIndexItem } from './remote-query-result-index';
import { getErrorMessage } from '../pure/helpers-pure'; import { getErrorMessage } from '../pure/helpers-pure';
export const RESULT_INDEX_ARTIFACT_NAME = 'result-index';
interface ApiSuccessIndexItem { interface ApiSuccessIndexItem {
nwo: string; nwo: string;
id: string; id: string;
@@ -43,7 +45,8 @@ export async function getRemoteQueryIndex(
const workflowUri = `https://github.com/${owner}/${repoName}/actions/runs/${workflowRunId}`; const workflowUri = `https://github.com/${owner}/${repoName}/actions/runs/${workflowRunId}`;
const artifactsUrlPath = `/repos/${owner}/${repoName}/actions/artifacts`; const artifactsUrlPath = `/repos/${owner}/${repoName}/actions/artifacts`;
const [artifactList, resultIndexArtifactId] = await waitForArtifact(credentials, owner, repoName, workflowRunId, 'result-indx'); const artifactList = await listWorkflowRunArtifacts(credentials, owner, repoName, workflowRunId);
const resultIndexArtifactId = tryGetArtifactIDfromName(RESULT_INDEX_ARTIFACT_NAME, artifactList);
if (!resultIndexArtifactId) { if (!resultIndexArtifactId) {
return undefined; return undefined;
} }
@@ -115,6 +118,27 @@ export async function downloadArtifactFromLink(
return path.join(extractedPath, downloadLink.innerFilePath || ''); return path.join(extractedPath, downloadLink.innerFilePath || '');
} }
/**
* Checks whether a specific artifact is present in the list of artifacts of a workflow run.
* @param credentials Credentials for authenticating to the GitHub API.
* @param owner
* @param repo
* @param workflowRunId The ID of the workflow run to get the artifact for.
* @param artifactName The artifact name, as a string.
* @returns A boolean indicating if the artifact is available.
*/
export async function isArtifactAvailable(
credentials: Credentials,
owner: string,
repo: string,
workflowRunId: number,
artifactName: string,
): Promise<boolean> {
const artifactList = await listWorkflowRunArtifacts(credentials, owner, repo, workflowRunId);
return tryGetArtifactIDfromName(artifactName, artifactList) !== undefined;
}
/** /**
* Downloads the result index artifact and extracts the result index items. * Downloads the result index artifact and extracts the result index items.
* @param credentials Credentials for authenticating to the GitHub API. * @param credentials Credentials for authenticating to the GitHub API.
@@ -254,44 +278,6 @@ function tryGetArtifactIDfromName(
return artifact?.id; return artifact?.id;
} }
/**
* Wait for an artifact to be available in a workflow run.
* @param credentials Credentials for authenticating to the GitHub API.
* @param owner
* @param repo
* @param workflowRunId The ID of the workflow run to get the artifact for.
* @param artifactName The artifact name, as a string.
* @param maxAttempts The maximum number of attempts to download the artifact.
* @returns An array containing the full list of artifacts and the ID of the artifact with the given name.
*/
async function waitForArtifact(
credentials: Credentials,
owner: string,
repo: string,
workflowRunId: number,
artifactName: string,
maxAttempts = 10,
intervalBetweenAttempts = 1000
): Promise<[Awaited<ReturnType<typeof listWorkflowRunArtifacts>>, number | undefined]> {
let attemptCount = 0;
let artifactList: Awaited<ReturnType<typeof listWorkflowRunArtifacts>> = [];
while (attemptCount < maxAttempts) {
artifactList = await listWorkflowRunArtifacts(credentials, owner, repo, workflowRunId);
const resultIndexArtifactId = tryGetArtifactIDfromName(artifactName, artifactList);
if (resultIndexArtifactId) {
return [artifactList, resultIndexArtifactId];
}
await new Promise(resolve => setTimeout(resolve, intervalBetweenAttempts));
attemptCount++;
}
return [artifactList, undefined];
}
/** /**
* Downloads an artifact from a workflow run. * Downloads an artifact from a workflow run.
* @param credentials Credentials for authenticating to the GitHub API. * @param credentials Credentials for authenticating to the GitHub API.

View File

@@ -1,7 +1,7 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { Credentials } from '../authentication'; import { Credentials } from '../authentication';
import { Logger } from '../logging'; import { Logger } from '../logging';
import { getWorkflowStatus } from './gh-actions-api-client'; import { getWorkflowStatus, isArtifactAvailable, RESULT_INDEX_ARTIFACT_NAME } from './gh-actions-api-client';
import { RemoteQuery } from './remote-query'; import { RemoteQuery } from './remote-query';
import { RemoteQueryWorkflowResult } from './remote-query-workflow-result'; import { RemoteQueryWorkflowResult } from './remote-query-workflow-result';
@@ -42,7 +42,25 @@ export class RemoteQueriesMonitor {
remoteQuery.controllerRepository.name, remoteQuery.controllerRepository.name,
remoteQuery.actionsWorkflowRunId); remoteQuery.actionsWorkflowRunId);
if (workflowStatus.status !== 'InProgress') { // Even if the workflow indicates it has completed, artifacts
// might still take a while to become available. So we need to
// check for the artifact before we can declare the workflow
// as having completed.
if (workflowStatus.status === 'CompletedSuccessfully') {
const resultIndexAvailable = await isArtifactAvailable(
credentials,
remoteQuery.controllerRepository.owner,
remoteQuery.controllerRepository.name,
remoteQuery.actionsWorkflowRunId,
RESULT_INDEX_ARTIFACT_NAME
);
if (resultIndexAvailable) {
return workflowStatus;
}
// We don't have a result-index yet, so we'll keep monitoring.
} else if (workflowStatus.status !== 'InProgress') {
return workflowStatus; return workflowStatus;
} }