Skip to content

Commit 0446ced

Browse files
authored
Merge pull request #2 from luojiyin1987/fix/start-runner-probe-fallback
fix: 容器模式下探测失败时回退到磁盘状态进行启动判断
2 parents 37d6cba + 321835d commit 0446ced

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

internal/handler/handler.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ func StartRunner(c echo.Context) error {
498498
if info == nil {
499499
return echo.NewHTTPError(http.StatusNotFound, "未找到该 runner")
500500
}
501+
originalStatus := info.Status
501502
probeFailed := false
502503
if cfg.Runners.ContainerMode {
503504
applyContainerStatusOne(c.Request().Context(), cfg, info)
@@ -506,8 +507,13 @@ func StartRunner(c echo.Context) error {
506507
log.Printf("[start] 容器 Runner 状态探测失败 name=%s,将继续尝试启动: %v", info.Name, info.Probe.Error)
507508
}
508509
}
509-
if info.Status != runner.StatusInstalled {
510-
return echo.NewHTTPError(http.StatusBadRequest, "仅已注册的 runner 可启动,当前状态: "+string(info.Status))
510+
// 容器模式下探测失败会把状态标记为 unknown;启动前资格判断应回退到磁盘原始状态。
511+
startStatus := info.Status
512+
if probeFailed {
513+
startStatus = originalStatus
514+
}
515+
if startStatus != runner.StatusInstalled {
516+
return echo.NewHTTPError(http.StatusBadRequest, "仅已注册的 runner 可启动,当前状态: "+string(startStatus))
511517
}
512518
if info.Running {
513519
return c.JSON(http.StatusOK, map[string]any{"message": "Runner 已在运行中"})

internal/handler/handler_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,48 @@ func TestUpdateRunner_TrimmedBodyNameAccepted(t *testing.T) {
164164
t.Errorf("expected 200 when body name trims to URL name, got %d body=%s", rec.Code, rec.Body.String())
165165
}
166166
}
167+
168+
func TestStartRunner_ProbeFailureFallsBackToInstalledStatus(t *testing.T) {
169+
dir := t.TempDir()
170+
cfgPath := filepath.Join(dir, "config.yaml")
171+
installDir := filepath.Join(dir, "r1")
172+
if err := os.MkdirAll(installDir, 0755); err != nil {
173+
t.Fatal(err)
174+
}
175+
// 标记为已注册状态
176+
if err := os.WriteFile(filepath.Join(installDir, ".runner"), []byte("ok"), 0644); err != nil {
177+
t.Fatal(err)
178+
}
179+
180+
cfg := &config.Config{
181+
Runners: config.RunnersConfig{
182+
BasePath: dir,
183+
ContainerMode: true,
184+
Items: []config.RunnerItem{
185+
{Name: "r1", TargetType: "org", Target: "o1"},
186+
},
187+
},
188+
}
189+
if err := cfg.Save(cfgPath); err != nil {
190+
t.Fatal(err)
191+
}
192+
193+
oldConfigPath := ConfigPath
194+
ConfigPath = cfgPath
195+
defer func() { ConfigPath = oldConfigPath }()
196+
197+
// 让容器状态探测失败(docker 命令不可执行)
198+
t.Setenv("PATH", "")
199+
// 启动阶段走容器模式快速失败分支:若到达此处说明没有被 400 提前拦截
200+
t.Setenv("DOCKER_HOST", "tcp://runner-dind:2375")
201+
202+
e := echo.New()
203+
e.POST("/api/runners/:name/start", StartRunner)
204+
req := httptest.NewRequest(http.MethodPost, "/api/runners/r1/start", nil)
205+
rec := httptest.NewRecorder()
206+
e.ServeHTTP(rec, req)
207+
208+
if rec.Code != http.StatusInternalServerError {
209+
t.Fatalf("expected 500 when start is attempted after probe failure, got %d body=%s", rec.Code, rec.Body.String())
210+
}
211+
}

0 commit comments

Comments
 (0)