Files
Runner/e2e/cancel_test.go
T
bircni 8260e2def2 test: add end-to-end Gitea compatibility suite (#1180)
Adds a real-Gitea compatibility suite against stable and nightly to catch runner and API drift before release.

The suite shares one Gitea and regular runner, using repository runners only for cache v1/v2 and ephemeral behavior. It covers registration, payload and log encoding, secrets, variables, services, artifacts, outputs, matrices, cache, dispatch, live logs, cancellation, and ephemeral teardown.

CI runs both images in parallel. Warm local timings:

| Image | Before | After |
| --- | ---: | ---: |
| `gitea/gitea:latest` | ~70s | 26.54s |
| `gitea/gitea:main-nightly` | ~54s | 22.53s |

The former serial matrix took about 2 minutes. Parallel suite execution is now bounded by the slower ~26.5-second variant.

Shared Renovate matcher: https://gitea.com/gitea/renovate-config/pulls/552

---------

Co-authored-by: silverwind <me@silverwind.io>
Reviewed-on: https://gitea.com/gitea/runner/pulls/1180
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
Co-authored-by: bircni <bircni@icloud.com>
2026-08-23 12:32:22 +00:00

75 lines
1.9 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")
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, substr string) {
t.Helper()
ctx, cancel := context.WithTimeout(t.Context(), time.Minute)
defer cancel()
for {
jobs, err := api.Jobs(ctx, repo, runID)
if err != nil {
t.Fatalf("list jobs: %v", err)
}
if len(jobs) > 0 && jobs[0].Status == "in_progress" {
logs, err := api.JobLogs(ctx, repo, jobs[0].ID)
if err == nil && commandRow(logs, substr) == substr {
return
}
}
select {
case <-ctx.Done():
t.Fatalf("running job for run %d never logged %q", runID, substr)
case <-time.After(pollInterval):
}
}
}