mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-08 22:13:26 +09:00
fix(actions): explain why a blocked or waiting job has not started (#38476)
When an Actions job is blocked or waiting, the job view only shows the generic **Blocked** / **Waiting** label. Users have no way to tell *why* a job is stuck — whether it's waiting on dependencies, waiting for a runner that doesn't exist, waiting for a runner whose labels don't match, or simply queued behind busy runners. ## Change The current-job detail line now surfaces the actual cause: - **Blocked** → lists the dependency jobs (`needs`) that haven't finished yet, e.g. *"Waiting for the following jobs to complete: build."* - **Waiting**, no online runner → *"No runner is online to pick up this job."* - **Waiting**, online runners but none match `runs-on` → *"No matching online runner with label: X"* (reuses the existing string) - **Waiting**, a matching runner exists but hasn't claimed the job → *"Waiting for a matching runner to become available."* The runner lookup reuses the same available-online-runner query the run list already performs, and only runs while a selected job is actually pending. Dependency resolution is scoped to the same parent job and treats matrix expansions of a `need` as pending until all of them complete.
This commit is contained in:
@@ -138,3 +138,48 @@ func TestConvertToViewModelCancellingTaskDoesNotRenderRunningSteps(t *testing.T)
|
||||
}
|
||||
assert.Equal(t, expectedViewJobs, viewJobSteps)
|
||||
}
|
||||
|
||||
func TestPendingNeeds(t *testing.T) {
|
||||
current := &actions_model.ActionRunJob{JobID: "deploy", Needs: []string{"build", "test"}}
|
||||
jobs := []*actions_model.ActionRunJob{
|
||||
current,
|
||||
{JobID: "build", Status: actions_model.StatusSuccess},
|
||||
{JobID: "test", Status: actions_model.StatusRunning},
|
||||
}
|
||||
// "test" is not done yet, "build" succeeded, so only "test" blocks.
|
||||
assert.Equal(t, []string{"test"}, pendingNeeds(current, jobs))
|
||||
|
||||
t.Run("all needs done", func(t *testing.T) {
|
||||
done := []*actions_model.ActionRunJob{
|
||||
current,
|
||||
{JobID: "build", Status: actions_model.StatusSuccess},
|
||||
{JobID: "test", Status: actions_model.StatusSkipped},
|
||||
}
|
||||
assert.Empty(t, pendingNeeds(current, done))
|
||||
})
|
||||
|
||||
t.Run("matrix expansion all required", func(t *testing.T) {
|
||||
matrix := []*actions_model.ActionRunJob{
|
||||
current,
|
||||
{JobID: "build", Status: actions_model.StatusSuccess},
|
||||
{JobID: "build", Status: actions_model.StatusRunning},
|
||||
{JobID: "test", Status: actions_model.StatusSuccess},
|
||||
}
|
||||
assert.Equal(t, []string{"build"}, pendingNeeds(current, matrix))
|
||||
})
|
||||
|
||||
t.Run("unresolved need treated as pending", func(t *testing.T) {
|
||||
missing := []*actions_model.ActionRunJob{current}
|
||||
assert.Equal(t, []string{"build", "test"}, pendingNeeds(current, missing))
|
||||
})
|
||||
|
||||
t.Run("parent job scope", func(t *testing.T) {
|
||||
// a same-named job under a different parent must not satisfy the need
|
||||
scoped := &actions_model.ActionRunJob{JobID: "deploy", Needs: []string{"build"}, ParentJobID: 5}
|
||||
jobs := []*actions_model.ActionRunJob{
|
||||
scoped,
|
||||
{JobID: "build", Status: actions_model.StatusSuccess, ParentJobID: 0},
|
||||
}
|
||||
assert.Equal(t, []string{"build"}, pendingNeeds(scoped, jobs))
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user