This is an automated email from the ASF dual-hosted git repository.

davidzollo pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 75599cf68b [Fix][CI] Retry and reconcile fork build status (#11888)
75599cf68b is described below

commit 75599cf68bacc2a73526510f065a63ed77ed078c
Author: Daniel <[email protected]>
AuthorDate: Thu Aug 20 21:15:16 2026 +0800

    [Fix][CI] Retry and reconcile fork build status (#11888)
---
 .github/workflows/notify_test_workflow.yml |  62 +++++++++++------
 .github/workflows/update_build_status.yml  | 107 ++++++++++++++++++++++-------
 2 files changed, 122 insertions(+), 47 deletions(-)

diff --git a/.github/workflows/notify_test_workflow.yml 
b/.github/workflows/notify_test_workflow.yml
index 2a0d1729f3..4563787e83 100644
--- a/.github/workflows/notify_test_workflow.yml
+++ b/.github/workflows/notify_test_workflow.yml
@@ -40,8 +40,10 @@ jobs:
         with:
           github-token: ${{ secrets.GITHUB_TOKEN }}
           script: |
-            const endpoint = 'GET 
/repos/:owner/:repo/actions/workflows/:id/runs?&branch=:branch'
-            const check_run_endpoint = 'GET 
/repos/:owner/:repo/commits/:ref/check-runs?per_page=100'
+            const endpoint = 'GET 
/repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs'
+            const check_run_endpoint = 'GET 
/repos/{owner}/{repo}/commits/{ref}/check-runs'
+            const MAX_LOOKUP_DURATION_MS = 60 * 1000
+            const LOOKUP_INTERVAL_MS = 5000
 
             // TODO: Should use pull_request.user and 
pull_request.user.repos_url?
             // If a different person creates a commit to another forked repo,
@@ -49,34 +51,57 @@ jobs:
             const params = {
               owner: context.payload.pull_request.head.repo.owner.login,
               repo: context.payload.pull_request.head.repo.name,
-              id: 'build_main.yml',
+              workflow_id: 'build_main.yml',
               branch: context.payload.pull_request.head.ref,
+              per_page: 100,
             }
             const check_run_params = {
               owner: context.payload.pull_request.head.repo.owner.login,
               repo: context.payload.pull_request.head.repo.name,
               ref: context.payload.pull_request.head.ref,
+              per_page: 100,
             }
 
             console.log('Ref: ' + context.payload.pull_request.head.ref)
             console.log('SHA: ' + context.payload.pull_request.head.sha)
 
-            // Wait 3 seconds to make sure the fork repository triggered a 
workflow.
-            await new Promise(r => setTimeout(r, 3000))
-
-            let runs
-            try {
-              runs = await github.request(endpoint, params)
-            } catch (error) {
-              console.error(error)
-              // Assume that runs were not found.
-            }
-
             const name = 'Build'
             const head_sha = context.payload.pull_request.head.sha
             let status = 'queued'
-            console.log('runs: ' + JSON.stringify(runs))
-            if (!runs || runs.data.workflow_runs.length === 0) {
+
+            async function findBuildWorkflowRun() {
+              const lookupDeadline = Date.now() + MAX_LOOKUP_DURATION_MS
+              let attempt = 1
+
+              while (true) {
+                try {
+                  const runs = await github.request(endpoint, params)
+                  const buildRun = runs.data.workflow_runs.find(
+                    (run) => run.head_sha === head_sha
+                  )
+
+                  console.log('runs: ' + JSON.stringify(runs))
+                  if (buildRun) {
+                    return buildRun
+                  }
+                } catch (error) {
+                  console.error(`Failed to find Build workflow run on attempt 
${attempt}`, error)
+                }
+
+                const remainingLookupTime = lookupDeadline - Date.now()
+                if (remainingLookupTime <= 0) {
+                  return null
+                }
+
+                await new Promise((resolve) =>
+                  setTimeout(resolve, Math.min(LOOKUP_INTERVAL_MS, 
remainingLookupTime))
+                )
+                attempt += 1
+              }
+            }
+
+            const build_run = await findBuildWorkflowRun()
+            if (!build_run) {
               status = 'completed'
               const conclusion = 'action_required'
 
@@ -109,13 +134,8 @@ jobs:
                 }
               })
             } else {
-              const build_run = runs.data.workflow_runs[0]
               const run_id = build_run.id
 
-              if (build_run.head_sha != context.payload.pull_request.head.sha) 
{
-                throw new Error('There was a new unsynced commit pushed. 
Please retrigger the workflow.');
-              }
-
               // Here we get check run ID to provide Check run view instead of 
Actions view, see also SPARK-37879.
               const check_runs = await github.request(check_run_endpoint, 
check_run_params)
               console.log('check_runs: ' + JSON.stringify(check_runs))
diff --git a/.github/workflows/update_build_status.yml 
b/.github/workflows/update_build_status.yml
index 1e853f9700..b7cd76eeeb 100644
--- a/.github/workflows/update_build_status.yml
+++ b/.github/workflows/update_build_status.yml
@@ -74,6 +74,42 @@ jobs:
               return items;
             }
 
+            async function findWorkflowRunForPullRequest(pr) {
+              if (!pr.head.repo) {
+                console.log(`  Skip PR #${pr.number}: head repository is 
unavailable`);
+                return null;
+              }
+
+              const workflowRunParams = {
+                owner: pr.head.repo.owner.login,
+                repo: pr.head.repo.name,
+                workflow_id: 'build_main.yml',
+                branch: pr.head.ref,
+                per_page: 100
+              };
+              const workflowRuns = await github.request(
+                'GET 
/repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs',
+                workflowRunParams
+              );
+              const workflowRun = workflowRuns.data.workflow_runs.find(
+                (run) => run.head_sha === pr.head.sha
+              );
+
+              if (!workflowRun) {
+                console.log(`  Skip PR #${pr.number}: no Build workflow run 
for ${pr.head.sha}`);
+                return null;
+              }
+
+              return {
+                workflowRun,
+                workflowRunParams: {
+                  owner: workflowRunParams.owner,
+                  repo: workflowRunParams.repo,
+                  run_id: workflowRun.id
+                }
+              };
+            }
+
             function shouldSkipPatch(checkRun, workflowRun) {
               const sameStatus = checkRun.status === workflowRun.status;
               const sameConclusion =
@@ -206,40 +242,52 @@ jobs:
                   }
                 );
 
-                const buildCheckRun = checkRuns.data.check_runs.find(
-                  (checkRun) =>
-                    checkRun.name === 'Build' && checkRun.conclusion !== 
'action_required'
+                const buildCheckRuns = checkRuns.data.check_runs.filter(
+                  (checkRun) => checkRun.name === 'Build'
                 );
+                const buildCheckRun =
+                  buildCheckRuns.find(
+                    (checkRun) => checkRun.conclusion !== 'action_required'
+                  ) || buildCheckRuns[0];
 
                 if (!buildCheckRun) {
                   console.log(`  Skip PR #${pr.number}: no eligible Build 
check run`);
                   return;
                 }
 
-                if (!buildCheckRun.output || !buildCheckRun.output.text) {
-                  console.log(`  Skip PR #${pr.number}: Build check run 
${buildCheckRun.id} has no run metadata`);
-                  return;
-                }
-
                 let workflowRunParams;
-                try {
-                  workflowRunParams = JSON.parse(buildCheckRun.output.text);
-                } catch (error) {
-                  console.error(`  Skip PR #${pr.number}: invalid JSON in 
check run ${buildCheckRun.id}`, error);
-                  return;
-                }
-
                 let workflowRun;
-                try {
-                  workflowRun = (
-                    await github.request(
-                      'GET /repos/{owner}/{repo}/actions/runs/{run_id}',
-                      workflowRunParams
-                    )
-                  ).data;
-                } catch (error) {
-                  console.error(`  Skip PR #${pr.number}: workflow run lookup 
failed`, error);
-                  return;
+                if (buildCheckRun.conclusion === 'action_required') {
+                  const matchedWorkflowRun = await 
findWorkflowRunForPullRequest(pr);
+                  if (!matchedWorkflowRun) {
+                    return;
+                  }
+                  workflowRunParams = matchedWorkflowRun.workflowRunParams;
+                  workflowRun = matchedWorkflowRun.workflowRun;
+                } else {
+                  if (!buildCheckRun.output || !buildCheckRun.output.text) {
+                    console.log(`  Skip PR #${pr.number}: Build check run 
${buildCheckRun.id} has no run metadata`);
+                    return;
+                  }
+
+                  try {
+                    workflowRunParams = JSON.parse(buildCheckRun.output.text);
+                  } catch (error) {
+                    console.error(`  Skip PR #${pr.number}: invalid JSON in 
check run ${buildCheckRun.id}`, error);
+                    return;
+                  }
+
+                  try {
+                    workflowRun = (
+                      await github.request(
+                        'GET /repos/{owner}/{repo}/actions/runs/{run_id}',
+                        workflowRunParams
+                      )
+                    ).data;
+                  } catch (error) {
+                    console.error(`  Skip PR #${pr.number}: workflow run 
lookup failed`, error);
+                    return;
+                  }
                 }
 
                 let normalizedWorkflowRun;
@@ -264,7 +312,14 @@ jobs:
                   owner: context.repo.owner,
                   repo: context.repo.repo,
                   check_run_id: buildCheckRun.id,
-                  output: buildCheckRun.output,
+                  output:
+                    buildCheckRun.conclusion === 'action_required'
+                      ? {
+                          title: 'Test results',
+                          summary: `[See test 
results](${workflowRun.html_url})`,
+                          text: JSON.stringify(workflowRunParams)
+                        }
+                      : buildCheckRun.output,
                   status: normalizedWorkflowRun.status,
                   details_url: normalizedWorkflowRun.details_url
                 };

Reply via email to