This commit is contained in:
pavel 2026-05-15 00:01:40 +02:00
commit 8d9b05608f
5 changed files with 59 additions and 11 deletions

View file

@ -61,9 +61,24 @@ func (a *App) migrate(ctx context.Context) error {
return err return err
} }
} }
if _, err := a.db.ExecContext(ctx, `ALTER TABLE projects DROP COLUMN IF EXISTS target_port;`); err != nil { if _, err := a.db.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS schema_migrations (
key TEXT PRIMARY KEY,
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);`); err != nil {
return err return err
} }
var dropDone bool
if err := a.db.QueryRowContext(ctx, `SELECT EXISTS(SELECT 1 FROM schema_migrations WHERE key='drop_projects_target_port')`).Scan(&dropDone); err != nil {
return err
}
if !dropDone {
if _, err := a.db.ExecContext(ctx, `ALTER TABLE projects DROP COLUMN IF EXISTS target_port;`); err != nil {
return err
}
if _, err := a.db.ExecContext(ctx, `INSERT INTO schema_migrations(key) VALUES ('drop_projects_target_port') ON CONFLICT (key) DO NOTHING`); err != nil {
return err
}
}
rows, err := a.db.QueryContext(ctx, `SELECT id FROM projects WHERE deploy_token=''`) rows, err := a.db.QueryContext(ctx, `SELECT id FROM projects WHERE deploy_token=''`)
if err != nil { if err != nil {
return err return err

View file

@ -81,7 +81,8 @@ func (a *App) deployProjectFromMain(_ context.Context, p Project) error {
if err := a.syncProjectRepoFromMain(p, projectDir); err != nil { if err := a.syncProjectRepoFromMain(p, projectDir); err != nil {
return err return err
} }
if err := a.buildProjectBinary(p); err != nil { repoDir := filepath.Join(projectDir, "repo")
if err := a.buildProjectBinaryFromRepoDir(p, repoDir); err != nil {
return err return err
} }
return runSystemctlUser(p.UnixUser, "restart", p.ServiceName) return runSystemctlUser(p.UnixUser, "restart", p.ServiceName)
@ -99,6 +100,14 @@ func (a *App) buildProjectBinary(p Project) error {
return err return err
} }
repoDir := filepath.Join(projectDir, "repo") repoDir := filepath.Join(projectDir, "repo")
return a.buildProjectBinaryFromRepoDir(p, repoDir)
}
func (a *App) buildProjectBinaryFromRepoDir(p Project, repoDir string) error {
projectDir, err := a.projectDirFor(p)
if err != nil {
return err
}
binDir := filepath.Join(projectDir, "bin") binDir := filepath.Join(projectDir, "bin")
if err := os.MkdirAll(binDir, 0o755); err != nil { if err := os.MkdirAll(binDir, 0o755); err != nil {
return err return err
@ -121,20 +130,30 @@ func (a *App) buildProjectBinary(p Project) error {
func (a *App) syncProjectRepoFromMain(p Project, projectDir string) error { func (a *App) syncProjectRepoFromMain(p Project, projectDir string) error {
repoDir := filepath.Join(projectDir, "repo") repoDir := filepath.Join(projectDir, "repo")
plainRepoURL := strings.TrimSpace(p.RepoURL)
repoCloneURL := a.repoURLForGitAuth(p.RepoURL) repoCloneURL := a.repoURLForGitAuth(p.RepoURL)
if _, err := os.Stat(repoDir); os.IsNotExist(err) { if _, err := os.Stat(repoDir); os.IsNotExist(err) {
if err := runCmd("git", "clone", "--branch", "main", "--single-branch", repoCloneURL, repoDir); err != nil { if err := os.MkdirAll(repoDir, 0o755); err != nil {
return err
}
if err := runCmd("git", "-C", repoDir, "init"); err != nil {
return err
}
if err := runCmd("git", "-C", repoDir, "remote", "add", "origin", plainRepoURL); err != nil {
return err
}
if err := runCmd("git", "-C", repoDir, "fetch", repoCloneURL, "main", "--prune"); err != nil {
return err
}
if err := runCmd("git", "-C", repoDir, "reset", "--hard", "FETCH_HEAD"); err != nil {
return err return err
} }
return nil return nil
} }
if err := runCmd("git", "-C", repoDir, "remote", "set-url", "origin", repoCloneURL); err != nil { if err := runCmd("git", "-C", repoDir, "fetch", repoCloneURL, "main", "--prune"); err != nil {
return err return err
} }
if err := runCmd("git", "-C", repoDir, "fetch", "origin", "main", "--prune"); err != nil { if err := runCmd("git", "-C", repoDir, "reset", "--hard", "FETCH_HEAD"); err != nil {
return err
}
if err := runCmd("git", "-C", repoDir, "reset", "--hard", "origin/main"); err != nil {
return err return err
} }
return nil return nil

View file

@ -44,7 +44,10 @@ func (a *App) createForgejoRepo(ctx context.Context, name, description string, p
HTMLURL string `json:"html_url"` HTMLURL string `json:"html_url"`
} }
if err := json.Unmarshal(respBody, &parsed); err != nil { if err := json.Unmarshal(respBody, &parsed); err != nil {
return "", nil return "", fmt.Errorf("forgejo create repo parse failed: %w", err)
}
if strings.TrimSpace(parsed.HTMLURL) == "" {
return "", errors.New("forgejo create repo response missing html_url")
} }
return parsed.HTMLURL, nil return parsed.HTMLURL, nil
} }

View file

@ -271,6 +271,13 @@ func (a *App) handleCaddyConfig(w http.ResponseWriter, r *http.Request, _ User)
if a.cfg.CaddyRouteEnabled && strings.TrimSpace(a.cfg.CaddyFragmentPath) != "" { if a.cfg.CaddyRouteEnabled && strings.TrimSpace(a.cfg.CaddyFragmentPath) != "" {
content, err := os.ReadFile(a.cfg.CaddyFragmentPath) content, err := os.ReadFile(a.cfg.CaddyFragmentPath)
if err != nil { if err != nil {
if os.IsNotExist(err) {
writeJSON(w, http.StatusOK, map[string]any{
"format": "caddyfile",
"content": "# Managed by project-manager. No routes provisioned yet.\n",
})
return
}
http.Error(w, err.Error(), http.StatusBadGateway) http.Error(w, err.Error(), http.StatusBadGateway)
return return
} }

View file

@ -107,8 +107,12 @@ WantedBy=default.target
if err := ensureOwnedByUnixUser(servicePath, p.UnixUser, 0o644); err != nil { if err := ensureOwnedByUnixUser(servicePath, p.UnixUser, 0o644); err != nil {
return err return err
} }
_ = runSystemctlUser(p.UnixUser, "daemon-reload") if err := runSystemctlUser(p.UnixUser, "daemon-reload"); err != nil {
_ = runSystemctlUser(p.UnixUser, "enable", "--now", p.ServiceName) return err
}
if err := runSystemctlUser(p.UnixUser, "enable", "--now", p.ServiceName); err != nil {
return err
}
return nil return nil
} }