diff --git a/.github/workflows/wait_for_required_workflows.yml b/.github/workflows/wait_for_required_workflows.yml index 3766eb67580056..53287030705a1a 100644 --- a/.github/workflows/wait_for_required_workflows.yml +++ b/.github/workflows/wait_for_required_workflows.yml @@ -67,35 +67,79 @@ jobs: actions = [...actions, 'test-policies'] } } + + pending = new Map() + for (const action of actions) { + if (pending.has(action)) { + pending.set(action, pending.get(action) + 1) + } else { + pending.set(action, 1) + } + } + + // We'll store IDs for the processed entries in this array + processed = [] - pendingActions = [...actions] - console.log(`Waiting for ${pendingActions.join(", ")}`) + console.log(`Actions: ${actions.join(", ")}`) while (now <= deadline) { - const checkRuns = await github.paginate(github.rest.checks.listForRef, { + console.log(`Waiting for ${Array.from(pending.keys()).join(", ")}`) + + const checkRuns = (await github.paginate(github.rest.checks.listForRef, { owner: 'cloudquery', repo: 'cloudquery', ref: context.payload.pull_request.head.sha, status: 'completed', per_page: 100 - }) + })).filter(({ id }) => !processed.includes(id)) // we filter out the runs we already processed + + // save to processed + processed = [...processed, ...checkRuns.map(({ id }) => id )] + const runs = checkRuns.map(({ id, name, conclusion }) => ({ id, name, conclusion })) console.log(`Got the following check runs: ${JSON.stringify(runs)}`) - const matchingRuns = runs.filter(({ name }) => actions.includes(name)) + + + const matchingRuns = runs.filter(({ name }) => pending.has(name)) const failedRuns = matchingRuns.filter(({ conclusion }) => conclusion !== 'success') if (failedRuns.length > 0) { throw new Error(`The following required workflows failed: ${failedRuns.map(({ name }) => name).join(", ")}`) } - console.log(`Matching runs: ${matchingRuns.map(({ name }) => name).join(", ")}`) - console.log(`Actions: ${actions.join(", ")}`) - if (matchingRuns.length === actions.length) { + console.log(`New matching check runs: ${matchingRuns.map(({ name }) => name).join(", ")}`) + + currentIDs = [] + for (const run of matchingRuns) { + const { id, name } = run + + // check if it was already processed (~ we have duplicate in output) + if (currentIDs.includes(id)) { + console.log(`Duplicate run encountered: ${run}`) + continue + } + + // save id to the processed array + currentIDs = [...currentIDs, id] + + if (!pending.has(name)) { + // We didn't account for this check but matched this. + // This should never happen. + throw new Error(`Extra check matched: ${run}`) + } + + // update value + const left = pending.get(name) + if (left === 1) { + pending.delete(name) + } else { + pending.set(name, left - 1) + } + } + + if (pending.size === 0) { console.log("All required workflows have passed") return } - pendingActions = actions.filter(action => !runs.some(({ name }) => name === action)) - console.log(`Waiting for ${pendingActions.join(", ")}`) + await new Promise(r => setTimeout(r, 5000)); now = new Date().getTime() } throw new Error(`Timed out waiting for ${pendingActions.join(', ')}`) - -