CI: finalize lingering steps when a job reaches a terminal state

28faa73 · gmorell · 2026-06-25 18:26

1 files +36 -0
Message
{commit_body(@commit)}

Files changed

modified lib/git_gud/workflows.ex
+36 −0
@@ -763,6 +763,7 @@ defmodule GitGud.Workflows do
763 763 broadcast({:job_status, job.workflow_run_id, updated})
764 764
765 765 if WorkflowJob.terminal?(updated.status) do
766 + finalize_steps(updated)
766 767 resolve_dependents(updated)
767 768 end
768 769
@@ -770,6 +771,41 @@ defmodule GitGud.Workflows do
770 771 {:ok, updated}
771 772 end
772 773
774 + # When a job reaches a terminal state the runner doesn't reliably send
775 + # a final per-step report — a failed job skips its remaining steps, and
776 + # the terminal UpdateTask often carries only the job-level result — so
777 + # `apply_step_states/2` never moves those rows off `pending`/`running`.
778 + # Sweep the stragglers here so a finished job never shows in-flight
779 + # steps:
780 + # * job succeeded → step succeeded
781 + # * step never started → skipped
782 + # * step was in flight → inherit the job's terminal status
783 + defp finalize_steps(%WorkflowJob{id: jid, status: job_status}) do
784 + now = DateTime.utc_now() |> DateTime.truncate(:second)
785 +
786 + from(s in WorkflowStep,
787 + where: s.workflow_job_id == ^jid and s.status in ["pending", "running"]
788 + )
789 + |> Repo.all()
790 + |> Enum.each(fn step ->
791 + status =
792 + cond do
793 + job_status == "success" -> "success"
794 + step.status == "pending" -> "skipped"
795 + job_status in ["failure", "cancelled"] -> job_status
796 + true -> "failure"
797 + end
798 +
799 + changes =
800 + %{status: status}
801 + |> maybe_put(:conclusion, step_status_conclusion(status))
802 + |> maybe_put(:completed_at, step.completed_at || now)
803 +
804 + {:ok, updated} = step |> Ecto.Changeset.change(changes) |> Repo.update()
805 + broadcast({:step_status, jid, updated})
806 + end)
807 + end
808 +
773 809 @doc """
774 810 After a job reaches a terminal state, walk every sibling job in the
775 811 same run whose `needs:` array contains this job's `job_id` and

Parents: 7370f38