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 bf9330fe1e [Improve][CI] Sync build checks from workflow jobs (#11840)
bf9330fe1e is described below
commit bf9330fe1ed528ecd8ca2658abf41a2fad4fc904
Author: Daniel <[email protected]>
AuthorDate: Tue Aug 18 21:40:58 2026 +0800
[Improve][CI] Sync build checks from workflow jobs (#11840)
---
.github/workflows/update_build_status.yml | 126 ++++++++++++++++++++++++++++--
1 file changed, 118 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/update_build_status.yml
b/.github/workflows/update_build_status.yml
index ed34e72911..1e853f9700 100644
--- a/.github/workflows/update_build_status.yml
+++ b/.github/workflows/update_build_status.yml
@@ -83,6 +83,105 @@ jobs:
return sameStatus && sameConclusion && sameDetailsUrl;
}
+ function deriveCompletedConclusion(jobs, fallbackConclusion) {
+ const conclusions = jobs
+ .map((job) => job.conclusion)
+ .filter((conclusion) => typeof conclusion === 'string' &&
conclusion.length > 0);
+
+ if (conclusions.length === 0) {
+ return fallbackConclusion;
+ }
+
+ if (
+ conclusions.includes('failure')
+ || conclusions.includes('startup_failure')
+ ) {
+ return 'failure';
+ }
+ if (conclusions.includes('timed_out')) {
+ return 'timed_out';
+ }
+ if (conclusions.includes('action_required')) {
+ return 'action_required';
+ }
+ if (conclusions.includes('cancelled')) {
+ return 'cancelled';
+ }
+ if (conclusions.every((conclusion) => conclusion === 'skipped'))
{
+ return 'skipped';
+ }
+ if (
+ conclusions.includes('neutral')
+ && conclusions.every(
+ (conclusion) => conclusion === 'neutral' || conclusion ===
'skipped'
+ )
+ ) {
+ return 'neutral';
+ }
+
+ return 'success';
+ }
+
+ async function listWorkflowJobs(workflowRunParams) {
+ const jobs = [];
+ let page = 1;
+
+ while (true) {
+ const response = await github.request(
+ 'GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs',
+ {
+ ...workflowRunParams,
+ per_page: 100,
+ page
+ }
+ );
+ const pageJobs = response.data.jobs || [];
+
+ jobs.push(...pageJobs);
+
+ if (pageJobs.length < 100) {
+ break;
+ }
+ page += 1;
+ }
+
+ return jobs;
+ }
+
+ async function normalizeWorkflowRun(workflowRunParams,
workflowRun) {
+ const normalizedWorkflowRun = {
+ status: workflowRun.status,
+ conclusion: workflowRun.conclusion,
+ details_url: workflowRun.html_url
+ };
+
+ if (workflowRun.status !== 'queued') {
+ return normalizedWorkflowRun;
+ }
+
+ // Reusable workflow runs can stay queued at the top level on
GitHub while
+ // child jobs are already running or finished, so derive a more
accurate state
+ // from the real job list before syncing the PR check run.
+ const jobs = await listWorkflowJobs(workflowRunParams);
+
+ if (jobs.length === 0 || jobs.every((job) => job.status ===
'queued')) {
+ return normalizedWorkflowRun;
+ }
+
+ if (jobs.every((job) => job.status === 'completed')) {
+ normalizedWorkflowRun.status = 'completed';
+ normalizedWorkflowRun.conclusion = deriveCompletedConclusion(
+ jobs,
+ workflowRun.conclusion
+ );
+ return normalizedWorkflowRun;
+ }
+
+ normalizedWorkflowRun.status = 'in_progress';
+ normalizedWorkflowRun.conclusion = null;
+ return normalizedWorkflowRun;
+ }
+
async function processPullRequest(searchItem) {
const prNumber = searchItem.number;
@@ -143,9 +242,20 @@ jobs:
return;
}
- if (shouldSkipPatch(buildCheckRun, workflowRun)) {
+ let normalizedWorkflowRun;
+ try {
+ normalizedWorkflowRun = await normalizeWorkflowRun(
+ workflowRunParams,
+ workflowRun
+ );
+ } catch (error) {
+ console.error(` Skip PR #${pr.number}: workflow jobs lookup
failed`, error);
+ return;
+ }
+
+ if (shouldSkipPatch(buildCheckRun, normalizedWorkflowRun)) {
console.log(
- ` Skip PR #${pr.number}: Build check run
${buildCheckRun.id} already matches
${workflowRun.status}/${workflowRun.conclusion}`
+ ` Skip PR #${pr.number}: Build check run
${buildCheckRun.id} already matches
${normalizedWorkflowRun.status}/${normalizedWorkflowRun.conclusion}`
);
return;
}
@@ -155,18 +265,18 @@ jobs:
repo: context.repo.repo,
check_run_id: buildCheckRun.id,
output: buildCheckRun.output,
- status: workflowRun.status,
- details_url: workflowRun.details_url
+ status: normalizedWorkflowRun.status,
+ details_url: normalizedWorkflowRun.details_url
};
- if (workflowRun.status === 'completed') {
- patchParams.conclusion = workflowRun.conclusion;
+ if (normalizedWorkflowRun.status === 'completed') {
+ patchParams.conclusion = normalizedWorkflowRun.conclusion;
console.log(
- ` Patch PR #${pr.number} check run ${buildCheckRun.id}:
${buildCheckRun.status}/${buildCheckRun.conclusion} ->
${workflowRun.status}/${workflowRun.conclusion}`
+ ` Patch PR #${pr.number} check run ${buildCheckRun.id}:
${buildCheckRun.status}/${buildCheckRun.conclusion} ->
${normalizedWorkflowRun.status}/${normalizedWorkflowRun.conclusion}`
);
} else {
console.log(
- ` Patch PR #${pr.number} check run ${buildCheckRun.id}:
${buildCheckRun.status} -> ${workflowRun.status}`
+ ` Patch PR #${pr.number} check run ${buildCheckRun.id}:
${buildCheckRun.status} -> ${normalizedWorkflowRun.status}`
);
}