feat: agent deploy pipeline — passwordless SSH (alarm/desk/blanc-nas via tailnet IPs in ssh config), gitea write token to workers, secrets mounts, gitconfig, APPEND_SYSTEM guide

This commit is contained in:
Raphael Westphal
2026-08-20 09:42:58 +02:00
parent 6d10877e34
commit b35eca40c3
4 changed files with 48 additions and 22 deletions
+32 -14
View File
@@ -353,6 +353,36 @@ func (s *Spawner) cloneOrUpdate(ctx context.Context, repo, branch, slug string)
return nil
}
// giteaTokenEnv returns LVMH_GITEA_TOKEN=<pat> when a PAT is stored.
func giteaTokenEnv(store *Store) string {
if pat, ok, _ := store.GetSetting(settingGitLabToken); ok && pat != "" {
return "LVMH_GITEA_TOKEN=" + pat
}
return ""
}
// workerEnv assembles the env for a spawned worker container.
func workerEnv(s *Spawner, repo, sessionID string) []string {
env := []string{
envProviderAPIKey + "=" + os.Getenv(envProviderAPIKey),
envToken + "=" + daemonToken,
"LVMH_URL=" + s.containerURL,
envLVMHSessionID + "=" + sessionID,
envLVMHAgent + "=1",
// other provider keys (empty ones are harmless)
"OPENAI_API_KEY=" + os.Getenv("OPENAI_API_KEY"),
"GEMINI_API_KEY=" + os.Getenv("GEMINI_API_KEY"),
"DEEPSEEK_KEY=" + os.Getenv("DEEPSEEK_KEY"),
"ANTHROPIC_API_KEY=" + os.Getenv("ANTHROPIC_API_KEY"),
envLVMHRepo + "=" + repo,
}
// Gitea token (write scope) so agents can push and open PRs.
if e := giteaTokenEnv(s.store); e != "" {
env = append(env, e)
}
return env
}
// cloneURL builds the clean https clone URL (never credential-bearing).
func (s *Spawner) cloneURL(repo string) (string, error) {
u, err := url.Parse(s.baseURL + "/" + repo + ".git")
@@ -536,20 +566,8 @@ func (s *Spawner) createAndStart(ctx context.Context, repo, slug, sessionID stri
)
}
cfg := &container.Config{
Image: image,
Env: []string{
envProviderAPIKey + "=" + os.Getenv(envProviderAPIKey),
envToken + "=" + daemonToken,
"LVMH_URL=" + s.containerURL,
envLVMHSessionID + "=" + sessionID,
envLVMHAgent + "=1",
// other provider keys (empty ones are harmless)
"OPENAI_API_KEY=" + os.Getenv("OPENAI_API_KEY"),
"GEMINI_API_KEY=" + os.Getenv("GEMINI_API_KEY"),
"DEEPSEEK_KEY=" + os.Getenv("DEEPSEEK_KEY"),
"ANTHROPIC_API_KEY=" + os.Getenv("ANTHROPIC_API_KEY"),
envLVMHRepo + "=" + repo,
},
Image: image,
Env: workerEnv(s, repo, sessionID),
Labels: map[string]string{labelSession: sessionID},
}
hostCfg := &container.HostConfig{
+1
View File
@@ -72,6 +72,7 @@ func TestSpawnerStartHappyPath(t *testing.T) {
passthrough := map[string]bool{
"OPENAI_API_KEY": true, "GEMINI_API_KEY": true,
"DEEPSEEK_KEY": true, "ANTHROPIC_API_KEY": true,
"LVMH_GITEA_TOKEN": true,
}
for _, e := range c.Env {
if name, _, ok := strings.Cut(e, "="); ok && passthrough[name] {