mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-11-03 05:45:12 +08:00
Follow-up to https://gitea.com/gitea/runner/pulls/1362, whose crash e2e missed because it only drove the daemon on Docker. - `dispatch`, `failure_paths` and `reusable_workflow` run through the daemon and `exec`, each on Docker and one shared k3s cluster. - Fixed sleeps become gates the test releases, the job timeout uses a 15s runner deadline, k3s boots alongside Gitea, Gitea's data is on tmpfs. - Outside a container, `make test-e2e` runs `go test` in a Linux container on its own network like CI, so local runs take the same paths. Local wall time: | | Before | After | |---|---|---| | Suite | 84s | 27–35s | | `job_timeout` | 64s | 17s | | `reconnect` | 22s | 4.5s | | `capacity/serial` | 20s | 2s | | `cli_shutdown_drains` | 14s | 2.3s | | `kubernetes` | 31s | 21–23s | _Written by Claude (Opus 5.5)._ --------- Co-authored-by: bircni <bircni@icloud.com> Reviewed-on: https://gitea.com/gitea/runner/pulls/1363 Reviewed-by: bircni <bircni@icloud.com> Co-authored-by: silverwind <me@silverwind.io>
82 lines
2.1 KiB
Go
82 lines
2.1 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
//go:build e2e
|
|
|
|
package e2e
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func testRunCancellation(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := t.Context()
|
|
|
|
api, repo := newScenario(t)
|
|
err := api.CancelRun(ctx, repo, 0)
|
|
cancelSupported := !errors.Is(err, ErrCancelUnsupported)
|
|
var response statusError
|
|
if cancelSupported && (!errors.As(err, &response) || response.code != http.StatusNotFound) {
|
|
t.Fatalf("probe run cancellation: %v", err)
|
|
}
|
|
|
|
pushWorkflow(t, api, repo, "cancel.yml")
|
|
|
|
wfRun := waitForRun(t, api, repo)
|
|
waitForRunningJobLog(t, api, repo, wfRun.ID, "e2e-live-log-marker", 1)
|
|
if !cancelSupported {
|
|
requireSuccess(t, api, repo, wfRun.ID)
|
|
return
|
|
}
|
|
|
|
if err := api.CancelRun(ctx, repo, wfRun.ID); err != nil {
|
|
dumpRunLogs(t, api, repo, wfRun.ID)
|
|
t.Fatalf("cancel run: %v", err)
|
|
}
|
|
completed, err := api.WaitForRunConclusion(ctx, repo, wfRun.ID, time.Minute)
|
|
if err != nil {
|
|
dumpRunLogs(t, api, repo, wfRun.ID)
|
|
t.Fatalf("cancelled run did not finish promptly: %v", err)
|
|
}
|
|
if completed.Conclusion != "cancelled" {
|
|
dumpRunLogs(t, api, repo, wfRun.ID)
|
|
t.Fatalf("cancelled run concluded %q, want cancelled", completed.Conclusion)
|
|
}
|
|
}
|
|
|
|
func waitForRunningJobLog(t *testing.T, api *GiteaAPI, repo string, runID int64, prefix string, count int) {
|
|
t.Helper()
|
|
// The budget covers scheduling and the container start, which a loaded runner makes slow.
|
|
ctx, cancel := context.WithTimeout(t.Context(), runTimeout)
|
|
defer cancel()
|
|
|
|
for {
|
|
jobs, err := api.Jobs(ctx, repo, runID)
|
|
if err != nil {
|
|
t.Fatalf("list jobs: %v", err)
|
|
}
|
|
logged := 0
|
|
for _, job := range jobs {
|
|
if job.Status == "in_progress" {
|
|
if logs, err := api.JobLogs(ctx, repo, job.ID); err == nil && commandRow(logs, prefix) != "" {
|
|
logged++
|
|
}
|
|
}
|
|
}
|
|
if logged >= count {
|
|
return
|
|
}
|
|
select {
|
|
case <-ctx.Done():
|
|
dumpRunLogs(t, api, repo, runID)
|
|
t.Fatalf("%d of %d running jobs of run %d logged %q", logged, count, runID, prefix)
|
|
case <-time.After(pollInterval):
|
|
}
|
|
}
|
|
}
|