From d94575412932549a9972cf6bc8ba5dbf925ced34 Mon Sep 17 00:00:00 2001 From: Johannes Klein Date: Wed, 12 Jun 2024 23:56:32 +0200 Subject: [PATCH] feat(action): add last-successful-state parameter (#146) --- README.md | 6 ++++ action.yml | 6 +++- find-successful-workflow.ts | 59 +++++++++++++++++++++++-------------- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 8ef4964..08e17fd 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,12 @@ jobs: # Default: push last-successful-event: "" + # One or more states of the last workflow that is to be considered successful. + # Possible values: completed, action_required, cancelled, failure, neutral, skipped, stale, success, timed_out, in_progress, queued, requested, waiting, pending" + # + # Default: "success" + last-successful-state: "waiting,success" + # The path where your repository is. This is only required for cases where the repository code is checked out or moved to a specific path. # # Default: . diff --git a/action.yml b/action.yml index c87c567..939e75b 100644 --- a/action.yml +++ b/action.yml @@ -18,6 +18,9 @@ inputs: last-successful-event: description: "The type of event to check for the last successful commit corresponding to that workflow-id, e.g. push, pull_request, release etc" default: "push" + last-successful-state: + description: "The state of the last workflow that is to be considered successful, one or more of completed, action_required, cancelled, failure, neutral, skipped, stale, success, timed_out, in_progress, queued, requested, waiting, pending" + default: "success" working-directory: description: "The directory where your repository is located" default: "." @@ -49,7 +52,8 @@ runs: working_directory: ${{ inputs.working-directory }} working_id: ${{ inputs.workflow-id }} fallback_sha: ${{ inputs.fallback-sha }} - run: node "$GITHUB_ACTION_PATH/dist/index.js" "$gh_token" "$main_branch_name" "$error_on_no_successful_workflow" "$last_successful_event" "$working_directory" "$working_id" "$fallback_sha" + last_successful_state: ${{ inputs.last-successful-state }} + run: node "$GITHUB_ACTION_PATH/dist/index.js" "$gh_token" "$main_branch_name" "$error_on_no_successful_workflow" "$last_successful_event" "$working_directory" "$working_id" "$fallback_sha" "$last_successful_state" - name: Log base and head SHAs used for nx affected shell: bash diff --git a/find-successful-workflow.ts b/find-successful-workflow.ts index 0504758..5bf82fd 100644 --- a/find-successful-workflow.ts +++ b/find-successful-workflow.ts @@ -18,6 +18,7 @@ const lastSuccessfulEvent = process.argv[5]; const workingDirectory = process.argv[6]; const workflowId = process.argv[7]; const fallbackSHA = process.argv[8]; +const lastSuccessfulState = process.argv[9]; const defaultWorkingDirectory = "."; const ProxifiedClient = Octokit.plugin(proxyPlugin); @@ -171,29 +172,43 @@ async function findSuccessfulCommit( `Workflow Id not provided. Using workflow '${workflow_id}'\n`, ); } - // fetch all workflow runs on a given repo/branch/workflow with push and success - const shas = await octokit - .request( - `GET /repos/${owner}/${repo}/actions/workflows/${workflow_id}/runs`, - { - owner, - repo, - // on some workflow runs we do not have branch property - branch: - lastSuccessfulEvent === "push" || - lastSuccessfulEvent === "workflow_dispatch" - ? branch - : undefined, - workflow_id, - event: lastSuccessfulEvent, - status: "success", - }, - ) - .then(({ data: { workflow_runs } }) => - workflow_runs.map((run: { head_sha: any }) => run.head_sha), - ); - return await findExistingCommit(octokit, branch, shas); + // on some workflow runs we do not have branch property + const branchProperty = + lastSuccessfulEvent === "push" || + lastSuccessfulEvent === "workflow_dispatch" + ? branch + : undefined; + + const workflowStatesConsideredSuccessful = lastSuccessfulState.split(","); + + const iterator = octokit.paginate.iterator( + `GET /repos/${owner}/${repo}/actions/workflows/${workflow_id}/runs`, + { + owner, + repo, + branch: branchProperty, + workflow_id, + event: lastSuccessfulEvent, + per_page: 100, + }, + ); + + // iterate through each response + for await (const { data: workflow_runs } of iterator) { + const shas: string[] = workflow_runs + .filter( + (run: { status: string; conclusion: string }) => + workflowStatesConsideredSuccessful.includes(run.status) || + workflowStatesConsideredSuccessful.includes(run.conclusion), + ) + .map((run: { head_sha: string }) => run.head_sha); + + const firstExistingCommit = await findExistingCommit(octokit, branch, shas); + if (firstExistingCommit) { + return firstExistingCommit; + } + } } async function findMergeBaseRef(): Promise {