diff --git a/internal/app/db.go b/internal/app/db.go index 19641ae..c1951e7 100644 --- a/internal/app/db.go +++ b/internal/app/db.go @@ -23,7 +23,6 @@ func (a *App) migrate(ctx context.Context) error { repo_private BOOLEAN NOT NULL DEFAULT true, service_name TEXT NOT NULL, route_host TEXT NOT NULL DEFAULT '', - target_port INT NOT NULL DEFAULT 8000, deploy_token TEXT NOT NULL DEFAULT '', provision_state TEXT NOT NULL DEFAULT 'provisioned', provision_error TEXT NOT NULL DEFAULT '', @@ -48,7 +47,6 @@ func (a *App) migrate(ctx context.Context) error { } alter := []string{ `ALTER TABLE projects ADD COLUMN IF NOT EXISTS route_host TEXT NOT NULL DEFAULT '';`, - `ALTER TABLE projects ADD COLUMN IF NOT EXISTS target_port INT NOT NULL DEFAULT 8000;`, `ALTER TABLE projects ADD COLUMN IF NOT EXISTS workspace_id BIGINT REFERENCES workspaces(id) ON DELETE RESTRICT;`, `ALTER TABLE projects ADD COLUMN IF NOT EXISTS deploy_token TEXT NOT NULL DEFAULT '';`, `ALTER TABLE projects ADD COLUMN IF NOT EXISTS repo_private BOOLEAN NOT NULL DEFAULT true;`, @@ -63,6 +61,9 @@ func (a *App) migrate(ctx context.Context) error { return err } } + if _, err := a.db.ExecContext(ctx, `ALTER TABLE projects DROP COLUMN IF EXISTS target_port;`); err != nil { + return err + } rows, err := a.db.QueryContext(ctx, `SELECT id FROM projects WHERE deploy_token=''`) if err != nil { return err diff --git a/internal/app/deploy_service.go b/internal/app/deploy_service.go index e69fd91..e4db077 100644 --- a/internal/app/deploy_service.go +++ b/internal/app/deploy_service.go @@ -57,9 +57,9 @@ func (a *App) handleDeployWebhook(w http.ResponseWriter, r *http.Request) { func (a *App) getProjectForWebhook(ctx context.Context, projectID int64, token string) (Project, error) { var p Project - err := a.db.QueryRowContext(ctx, `SELECT p.id, p.user_id, p.name, p.slug, p.description, p.repo_url, p.service_name, p.route_host, p.target_port, p.workspace_id, w.name, w.unix_user, p.deploy_token, p.created_at + err := a.db.QueryRowContext(ctx, `SELECT p.id, p.user_id, p.name, p.slug, p.description, p.repo_url, p.service_name, p.route_host, p.workspace_id, w.name, w.unix_user, p.deploy_token, p.created_at FROM projects p JOIN workspaces w ON w.id=p.workspace_id WHERE p.id=$1 AND p.deploy_token=$2`, projectID, token). - Scan(&p.ID, &p.UserID, &p.Name, &p.Slug, &p.Description, &p.RepoURL, &p.ServiceName, &p.RouteHost, &p.TargetPort, &p.WorkspaceID, &p.Workspace, &p.UnixUser, &p.DeployToken, &p.CreatedAt) + Scan(&p.ID, &p.UserID, &p.Name, &p.Slug, &p.Description, &p.RepoURL, &p.ServiceName, &p.RouteHost, &p.WorkspaceID, &p.Workspace, &p.UnixUser, &p.DeployToken, &p.CreatedAt) if err != nil { if errors.Is(err, sql.ErrNoRows) { return Project{}, errors.New("project not found") diff --git a/internal/app/project_service.go b/internal/app/project_service.go index cf115c1..71b92cf 100644 --- a/internal/app/project_service.go +++ b/internal/app/project_service.go @@ -9,7 +9,7 @@ import ( ) func (a *App) listProjects(ctx context.Context, userID string) ([]Project, error) { - rows, err := a.db.QueryContext(ctx, `SELECT p.id, p.user_id, p.name, p.slug, p.description, p.repo_url, p.repo_private, p.service_name, p.route_host, p.target_port, p.workspace_id, w.name, w.unix_user, p.deploy_token, p.provision_state, p.provision_error, p.db_name, p.db_user, p.db_password, p.created_at + rows, err := a.db.QueryContext(ctx, `SELECT p.id, p.user_id, p.name, p.slug, p.description, p.repo_url, p.repo_private, p.service_name, p.route_host, p.workspace_id, w.name, w.unix_user, p.deploy_token, p.provision_state, p.provision_error, p.db_name, p.db_user, p.db_password, p.created_at FROM projects p JOIN workspaces w ON w.id = p.workspace_id WHERE p.user_id=$1 ORDER BY p.created_at DESC`, userID) @@ -20,7 +20,7 @@ func (a *App) listProjects(ctx context.Context, userID string) ([]Project, error var out []Project for rows.Next() { var p Project - if err := rows.Scan(&p.ID, &p.UserID, &p.Name, &p.Slug, &p.Description, &p.RepoURL, &p.RepoPrivate, &p.ServiceName, &p.RouteHost, &p.TargetPort, &p.WorkspaceID, &p.Workspace, &p.UnixUser, &p.DeployToken, &p.ProvisionState, &p.ProvisionError, &p.DBName, &p.DBUser, &p.DBPassword, &p.CreatedAt); err != nil { + if err := rows.Scan(&p.ID, &p.UserID, &p.Name, &p.Slug, &p.Description, &p.RepoURL, &p.RepoPrivate, &p.ServiceName, &p.RouteHost, &p.WorkspaceID, &p.Workspace, &p.UnixUser, &p.DeployToken, &p.ProvisionState, &p.ProvisionError, &p.DBName, &p.DBUser, &p.DBPassword, &p.CreatedAt); err != nil { return nil, err } p.WebhookURL = a.deployWebhookURL(p.ID, p.DeployToken) @@ -30,7 +30,7 @@ func (a *App) listProjects(ctx context.Context, userID string) ([]Project, error return out, rows.Err() } -func (a *App) createProject(ctx context.Context, user User, workspaceID int64, name, description string, private bool, existingRepoURL string, targetPort int) (Project, error) { +func (a *App) createProject(ctx context.Context, user User, workspaceID int64, name, description string, private bool, existingRepoURL string) (Project, error) { slug := slugify(name) if slug == "" { return Project{}, errors.New("project name must include letters or numbers") @@ -55,9 +55,9 @@ func (a *App) createProject(ctx context.Context, user User, workspaceID int64, n } defer tx.Rollback() - err = tx.QueryRowContext(ctx, `INSERT INTO projects (user_id, workspace_id, name, slug, description, repo_url, repo_private, service_name, route_host, target_port, deploy_token, provision_state, provision_error) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,'pending','') RETURNING id, user_id, name, slug, description, repo_url, repo_private, service_name, route_host, target_port, workspace_id, deploy_token, provision_state, provision_error, db_name, db_user, db_password, created_at`, - user.Username, workspaceID, name, slug, description, repoURL, private, serviceName, routeHost, targetPort, deployToken, - ).Scan(&p.ID, &p.UserID, &p.Name, &p.Slug, &p.Description, &p.RepoURL, &p.RepoPrivate, &p.ServiceName, &p.RouteHost, &p.TargetPort, &p.WorkspaceID, &p.DeployToken, &p.ProvisionState, &p.ProvisionError, &p.DBName, &p.DBUser, &p.DBPassword, &p.CreatedAt) + err = tx.QueryRowContext(ctx, `INSERT INTO projects (user_id, workspace_id, name, slug, description, repo_url, repo_private, service_name, route_host, deploy_token, provision_state, provision_error) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,'pending','') RETURNING id, user_id, name, slug, description, repo_url, repo_private, service_name, route_host, workspace_id, deploy_token, provision_state, provision_error, db_name, db_user, db_password, created_at`, + user.Username, workspaceID, name, slug, description, repoURL, private, serviceName, routeHost, deployToken, + ).Scan(&p.ID, &p.UserID, &p.Name, &p.Slug, &p.Description, &p.RepoURL, &p.RepoPrivate, &p.ServiceName, &p.RouteHost, &p.WorkspaceID, &p.DeployToken, &p.ProvisionState, &p.ProvisionError, &p.DBName, &p.DBUser, &p.DBPassword, &p.CreatedAt) if err != nil { if strings.Contains(err.Error(), "duplicate key") { return Project{}, errors.New("project with this name already exists") @@ -144,9 +144,9 @@ func (a *App) provisionProject(ctx context.Context, p *Project) error { func (a *App) getProject(ctx context.Context, userID string, projectID int64) (Project, error) { var p Project - err := a.db.QueryRowContext(ctx, `SELECT p.id, p.user_id, p.name, p.slug, p.description, p.repo_url, p.repo_private, p.service_name, p.route_host, p.target_port, p.workspace_id, w.name, w.unix_user, p.deploy_token, p.provision_state, p.provision_error, p.db_name, p.db_user, p.db_password, p.created_at + err := a.db.QueryRowContext(ctx, `SELECT p.id, p.user_id, p.name, p.slug, p.description, p.repo_url, p.repo_private, p.service_name, p.route_host, p.workspace_id, w.name, w.unix_user, p.deploy_token, p.provision_state, p.provision_error, p.db_name, p.db_user, p.db_password, p.created_at FROM projects p JOIN workspaces w ON w.id=p.workspace_id WHERE p.user_id=$1 AND p.id=$2`, userID, projectID). - Scan(&p.ID, &p.UserID, &p.Name, &p.Slug, &p.Description, &p.RepoURL, &p.RepoPrivate, &p.ServiceName, &p.RouteHost, &p.TargetPort, &p.WorkspaceID, &p.Workspace, &p.UnixUser, &p.DeployToken, &p.ProvisionState, &p.ProvisionError, &p.DBName, &p.DBUser, &p.DBPassword, &p.CreatedAt) + Scan(&p.ID, &p.UserID, &p.Name, &p.Slug, &p.Description, &p.RepoURL, &p.RepoPrivate, &p.ServiceName, &p.RouteHost, &p.WorkspaceID, &p.Workspace, &p.UnixUser, &p.DeployToken, &p.ProvisionState, &p.ProvisionError, &p.DBName, &p.DBUser, &p.DBPassword, &p.CreatedAt) if err != nil { if errors.Is(err, sql.ErrNoRows) { return Project{}, errors.New("project not found") diff --git a/internal/app/routes_handlers.go b/internal/app/routes_handlers.go index cf3a4ea..d3877f4 100644 --- a/internal/app/routes_handlers.go +++ b/internal/app/routes_handlers.go @@ -79,7 +79,6 @@ func (a *App) handleProjects(w http.ResponseWriter, r *http.Request, user User) Description string `json:"description"` RepoPrivate bool `json:"repo_private"` RepoURL string `json:"repo_url"` - TargetPort int `json:"target_port"` WorkspaceID int64 `json:"workspace_id"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { @@ -99,14 +98,7 @@ func (a *App) handleProjects(w http.ResponseWriter, r *http.Request, user User) http.Error(w, "repo_url must be a valid repo URL (https://..., ssh://..., or git@...)", http.StatusBadRequest) return } - if req.TargetPort == 0 { - req.TargetPort = 8000 - } - if req.TargetPort < 1 || req.TargetPort > 65535 { - http.Error(w, "target_port must be 1-65535", http.StatusBadRequest) - return - } - project, err := a.createProject(r.Context(), user, req.WorkspaceID, req.Name, req.Description, req.RepoPrivate, req.RepoURL, req.TargetPort) + project, err := a.createProject(r.Context(), user, req.WorkspaceID, req.Name, req.Description, req.RepoPrivate, req.RepoURL) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return diff --git a/internal/app/types.go b/internal/app/types.go index 3c9638b..0182c24 100644 --- a/internal/app/types.go +++ b/internal/app/types.go @@ -55,7 +55,6 @@ type Project struct { ServiceName string `json:"service_name"` RouteHost string `json:"route_host"` AppURL string `json:"app_url"` - TargetPort int `json:"target_port"` WorkspaceID int64 `json:"workspace_id"` Workspace string `json:"workspace"` UnixUser string `json:"unix_user"` diff --git a/web/app.js b/web/app.js index 390cf27..f39a58f 100644 --- a/web/app.js +++ b/web/app.js @@ -53,7 +53,7 @@ function renderProjects() {

${escapeHtml(p.name)}

workspace: ${escapeHtml(p.workspace)} (${escapeHtml(p.unix_user)})

slug: ${escapeHtml(p.slug)} | service: ${escapeHtml(p.service_name)}

-

app target: 127.0.0.1:${escapeHtml(p.target_port)} | route host: ${escapeHtml(p.route_host || 'not set')}

+

route host: ${escapeHtml(p.route_host || 'not set')}

app url: ${p.app_url ? `${escapeHtml(p.app_url)}` : 'not set'}

deploy webhook: ${escapeHtml(p.webhook_url || 'n/a')}

provisioning: ${escapeHtml(p.provision_state || 'unknown')}${p.provision_error ? ` | error: ${escapeHtml(p.provision_error)}` : ''}

@@ -156,8 +156,7 @@ async function createProject(e) { name: form.name.value, description: form.description.value, repo_url: form.repo_url.value.trim(), - repo_private: form.repo_private.checked, - target_port: Number(form.target_port.value || 8000) + repo_private: form.repo_private.checked }; const msg = document.getElementById('createMsg'); msg.textContent = 'Creating project...'; diff --git a/web/index.html b/web/index.html index ccbb17e..df272e1 100644 --- a/web/index.html +++ b/web/index.html @@ -34,7 +34,6 @@ -