Point the wizard's task runner at the venv python automatically
coordinator / test (push) Canceled after 0s
python / test (push) Canceled after 0s
release / binaries (amd64, darwin) (push) Canceled after 0s
release / binaries (amd64, linux) (push) Canceled after 0s
release / binaries (amd64, windows) (push) Canceled after 0s
release / binaries (arm64, darwin) (push) Canceled after 0s
release / binaries (arm64, linux) (push) Canceled after 0s
release / binaries (arm64, windows) (push) Canceled after 0s
release / wheel (push) Canceled after 0s
release / image (push) Canceled after 0s
users / test (push) Canceled after 0s
release / release (push) Canceled after 0s
coordinator / test (push) Canceled after 0s
python / test (push) Canceled after 0s
release / binaries (amd64, darwin) (push) Canceled after 0s
release / binaries (amd64, linux) (push) Canceled after 0s
release / binaries (amd64, windows) (push) Canceled after 0s
release / binaries (arm64, darwin) (push) Canceled after 0s
release / binaries (arm64, linux) (push) Canceled after 0s
release / binaries (arm64, windows) (push) Canceled after 0s
release / wheel (push) Canceled after 0s
release / image (push) Canceled after 0s
users / test (push) Canceled after 0s
release / release (push) Canceled after 0s
This commit is contained in:
@@ -300,6 +300,25 @@ type statusView struct {
|
|||||||
TokenSet bool `json:"token_set"`
|
TokenSet bool `json:"token_set"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensureVenvTaskRunner rewrites the saved config so its task runner uses the
|
||||||
|
// managed venv python when one exists and the config does not already pin one.
|
||||||
|
func (s *Server) ensureVenvTaskRunner() {
|
||||||
|
raw, err := os.ReadFile(s.cfgPath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var file agent.ConfigFile
|
||||||
|
if json.Unmarshal(raw, &file) != nil || len(file.TaskRunner) > 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if venv := s.venvPython(); venv != "" {
|
||||||
|
file.TaskRunner = []string{venv, "-m", "scimesh.worker.task"}
|
||||||
|
if payload, err := json.MarshalIndent(file, "", " "); err == nil {
|
||||||
|
_ = os.WriteFile(s.cfgPath, append(payload, '\n'), 0o600)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) handleStatus(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
view := statusView{ConfigPath: s.cfgPath, LogPath: s.logPath, Running: s.sup.Alive(), Pid: s.sup.Pid()}
|
view := statusView{ConfigPath: s.cfgPath, LogPath: s.logPath, Running: s.sup.Alive(), Pid: s.sup.Pid()}
|
||||||
if raw, err := os.ReadFile(s.cfgPath); err == nil {
|
if raw, err := os.ReadFile(s.cfgPath); err == nil {
|
||||||
@@ -365,6 +384,14 @@ func (s *Server) handleSaveConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
if file.CPUCount < 1 {
|
if file.CPUCount < 1 {
|
||||||
file.CPUCount = 1
|
file.CPUCount = 1
|
||||||
}
|
}
|
||||||
|
// The wizard UI bakes the venv python into the runner after an install;
|
||||||
|
// an API-driven or scripted flow may not, so the server guarantees it:
|
||||||
|
// workloads execute through scimesh's task runner, which lives in the venv.
|
||||||
|
if len(file.TaskRunner) == 0 {
|
||||||
|
if venv := s.venvPython(); venv != "" {
|
||||||
|
file.TaskRunner = []string{venv, "-m", "scimesh.worker.task"}
|
||||||
|
}
|
||||||
|
}
|
||||||
if err := agent.SaveConfigFile(s.cfgPath, file); err != nil {
|
if err := agent.SaveConfigFile(s.cfgPath, file); err != nil {
|
||||||
s.log.Error("save wizard config", "err", err)
|
s.log.Error("save wizard config", "err", err)
|
||||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "could not write the config file"})
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "could not write the config file"})
|
||||||
@@ -393,6 +420,7 @@ func (s *Server) handleStart(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "no configuration saved yet"})
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "no configuration saved yet"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.ensureVenvTaskRunner()
|
||||||
pid, err := s.sup.Start(s.cfgPath, s.logPath)
|
pid, err := s.sup.Start(s.cfgPath, s.logPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeJSON(w, http.StatusConflict, map[string]string{"error": err.Error()})
|
writeJSON(w, http.StatusConflict, map[string]string{"error": err.Error()})
|
||||||
@@ -514,6 +542,20 @@ func (s *Server) handleInstallRuntime(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeJSON(w, http.StatusOK, installRuntimeResponse{OK: true, Python: venvPython, Installed: true})
|
writeJSON(w, http.StatusOK, installRuntimeResponse{OK: true, Python: venvPython, Installed: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// venvPython returns the managed venv python when the runtime installer has
|
||||||
|
// created one, so the task runner can be pointed at it automatically.
|
||||||
|
func (s *Server) venvPython() string {
|
||||||
|
for _, candidate := range []string{
|
||||||
|
filepath.Join(s.dir, "venv", "bin", "python"),
|
||||||
|
filepath.Join(s.dir, "venv", "Scripts", "python.exe"),
|
||||||
|
} {
|
||||||
|
if _, err := os.Stat(candidate); err == nil {
|
||||||
|
return candidate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// installScimeshWithPip installs the package with the venv's own pip,
|
// installScimeshWithPip installs the package with the venv's own pip,
|
||||||
// streaming into the agent log so a long build is not silent.
|
// streaming into the agent log so a long build is not silent.
|
||||||
func installScimeshWithPip(ctx context.Context, venvPython, pkg string) error {
|
func installScimeshWithPip(ctx context.Context, venvPython, pkg string) error {
|
||||||
|
|||||||
@@ -409,3 +409,48 @@ func TestInstallRuntimeWheelDownloadFailureIsExplained(t *testing.T) {
|
|||||||
t.Errorf("error = %v, want a SCIMESH_PIP_PACKAGE hint", data["error"])
|
t.Errorf("error = %v, want a SCIMESH_PIP_PACKAGE hint", data["error"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStartPinsTheVenvTaskRunner(t *testing.T) {
|
||||||
|
sup := &fakeSup{}
|
||||||
|
server, base := newTestServer(t, sup)
|
||||||
|
postJSON(t, base, "/api/config", map[string]any{
|
||||||
|
"coordinator_url": "http://coord:8080", "token": "t", "work_dir": ".",
|
||||||
|
})
|
||||||
|
// Simulate the runtime installer: create the venv python marker.
|
||||||
|
venvPython := filepath.Join(server.dir, "venv", "bin", "python")
|
||||||
|
_ = os.MkdirAll(filepath.Dir(venvPython), 0o755)
|
||||||
|
_ = os.WriteFile(venvPython, []byte("#!/bin/sh\nexit 0\n"), 0o755)
|
||||||
|
|
||||||
|
rec, _ := postJSON(t, base, "/api/start", map[string]any{})
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Fatalf("start: got %d, want 200", rec.Code)
|
||||||
|
}
|
||||||
|
config, err := agent.LoadConfigFile(server.cfgPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(config.TaskRunner) != 3 || config.TaskRunner[0] != venvPython || config.TaskRunner[1] != "-m" || config.TaskRunner[2] != "scimesh.worker.task" {
|
||||||
|
t.Errorf("task runner = %v, want the venv python runner", config.TaskRunner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSaveConfigPinsVenvRunnerWhenPresent(t *testing.T) {
|
||||||
|
server, base := newTestServer(t, &fakeSup{})
|
||||||
|
venvPython := filepath.Join(server.dir, "venv", "bin", "python")
|
||||||
|
_ = os.MkdirAll(filepath.Dir(venvPython), 0o755)
|
||||||
|
_ = os.WriteFile(venvPython, []byte("#!/bin/sh\nexit 0\n"), 0o755)
|
||||||
|
|
||||||
|
rec, _ := postJSON(t, base, "/api/config", map[string]any{
|
||||||
|
"coordinator_url": "http://coord:8080", "token": "t", "work_dir": ".",
|
||||||
|
})
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Fatalf("config: got %d", rec.Code)
|
||||||
|
}
|
||||||
|
config, err := agent.LoadConfigFile(server.cfgPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(config.TaskRunner) != 3 || config.TaskRunner[0] != venvPython {
|
||||||
|
t.Errorf("task runner = %v, want the venv python", config.TaskRunner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user