From 461b4d1061727e0ccf162f101dd53bf3108ef928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20C=2E=20M=C3=BCller?= Date: Tue, 15 Jul 2025 09:24:35 -0400 Subject: [PATCH 1/3] feat: replace hostname/server name with project name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Which is the host/server name + the name of the project if defined, otherwise CWD. Signed-off-by: Juan C. Müller --- schemas/process-compose-schema.json | 2 +- src/api/pc_api.go | 18 +++---- src/api/routes.go | 2 +- src/app/project_interface.go | 2 +- src/app/project_runner.go | 34 ++++++++---- src/app/project_runner_test.go | 41 +++++++++++++++ src/client/client.go | 4 +- src/client/status.go | 6 +-- src/cmd/state.go | 2 +- src/docs/docs.go | 72 ++++++++++++------------- src/docs/swagger.json | 82 ++++++++++++++--------------- src/docs/swagger.yaml | 52 +++++++++--------- src/tui/stat-table.go | 20 +++---- src/types/project.go | 1 + src/types/project_state.go | 2 +- 15 files changed, 195 insertions(+), 145 deletions(-) diff --git a/schemas/process-compose-schema.json b/schemas/process-compose-schema.json index ec933813..35f53e2f 100644 --- a/schemas/process-compose-schema.json +++ b/schemas/process-compose-schema.json @@ -1 +1 @@ -{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://github.com/f1bonacc1/process-compose/src/types/project","$ref":"#/$defs/Project","$defs":{"DependsOnConfig":{"additionalProperties":{"$ref":"#/$defs/ProcessDependency"},"type":"object"},"EnvCmd":{"additionalProperties":{"type":"string"},"type":"object"},"Environment":{"items":{"type":"string"},"type":"array"},"ExecProbe":{"properties":{"command":{"type":"string"},"working_dir":{"type":"string"}},"type":"object"},"HttpProbe":{"properties":{"host":{"type":"string"},"path":{"type":"string"},"scheme":{"type":"string"},"port":{"type":"string"},"num_port":{"type":"integer"}},"type":"object"},"LogRotationConfig":{"properties":{"directory":{"type":"string"},"filename":{"type":"string"},"max_size_mb":{"type":"integer"},"max_backups":{"type":"integer"},"max_age_days":{"type":"integer"},"compress":{"type":"boolean"}},"type":"object"},"LoggerConfig":{"properties":{"rotation":{"$ref":"#/$defs/LogRotationConfig"},"fields_order":{"items":{"type":"string"},"type":"array"},"disable_json":{"type":"boolean"},"timestamp_format":{"type":"string"},"no_color":{"type":"boolean"},"no_metadata":{"type":"boolean"},"add_timestamp":{"type":"boolean"},"flush_each_line":{"type":"boolean"}},"type":"object"},"Probe":{"properties":{"exec":{"$ref":"#/$defs/ExecProbe"},"http_get":{"$ref":"#/$defs/HttpProbe"},"initial_delay_seconds":{"type":"integer"},"period_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"success_threshold":{"type":"integer"},"failure_threshold":{"type":"integer"}},"type":"object"},"ProcessConfig":{"properties":{"name":{"type":"string"},"disabled":{"type":"boolean"},"is_daemon":{"type":"boolean"},"command":{"type":"string"},"entrypoint":{"items":{"type":"string"},"type":"array"},"log_location":{"type":"string"},"log_configuration":{"$ref":"#/$defs/LoggerConfig"},"environment":{"$ref":"#/$defs/Environment"},"availability":{"$ref":"#/$defs/RestartPolicyConfig"},"depends_on":{"$ref":"#/$defs/DependsOnConfig"},"liveness_probe":{"$ref":"#/$defs/Probe"},"readiness_probe":{"$ref":"#/$defs/Probe"},"ready_log_line":{"type":"string"},"shutdown":{"$ref":"#/$defs/ShutDownParams"},"disable_ansi_colors":{"type":"boolean"},"working_dir":{"type":"string"},"namespace":{"type":"string"},"replicas":{"type":"integer"},"description":{"type":"string"},"vars":{"$ref":"#/$defs/Vars"},"is_foreground":{"type":"boolean"},"is_tty":{"type":"boolean"},"is_elevated":{"type":"boolean"},"launch_timeout_seconds":{"type":"integer"},"is_disabled":{"type":"string"},"is_dotenv_disabled":{"type":"boolean"},"original_config":{"type":"string"},"replica_num":{"type":"integer"},"replica_name":{"type":"string"},"executable":{"type":"string"},"args":{"items":{"type":"string"},"type":"array"}},"type":"object","required":["name","original_config","replica_num","replica_name","executable","args"]},"ProcessDependency":{"properties":{"condition":{"type":"string"}},"type":"object"},"Processes":{"additionalProperties":{"$ref":"#/$defs/ProcessConfig"},"type":"object"},"Project":{"properties":{"version":{"type":"string"},"log_location":{"type":"string"},"log_level":{"type":"string"},"log_length":{"type":"integer"},"log_configuration":{"$ref":"#/$defs/LoggerConfig"},"log_format":{"type":"string"},"processes":{"$ref":"#/$defs/Processes"},"environment":{"$ref":"#/$defs/Environment"},"shell":{"$ref":"#/$defs/ShellConfig"},"is_strict":{"type":"boolean"},"vars":{"$ref":"#/$defs/Vars"},"disable_env_expansion":{"type":"boolean"},"is_tui_disabled":{"type":"boolean"},"extends":{"type":"string"},"env_cmds":{"$ref":"#/$defs/EnvCmd"},"file_names":{"items":{"type":"string"},"type":"array"},"env_file_names":{"items":{"type":"string"},"type":"array"},"dot_env_vars":{"additionalProperties":{"type":"string"},"type":"object"}},"type":"object","required":["version","processes","file_names","env_file_names","dot_env_vars"]},"RestartPolicyConfig":{"properties":{"restart":{"type":"string"},"backoff_seconds":{"type":"integer"},"max_restarts":{"type":"integer"},"exit_on_end":{"type":"boolean"},"exit_on_skipped":{"type":"boolean"}},"type":"object"},"ShellConfig":{"properties":{"shell_command":{"type":"string"},"shell_argument":{"type":"string"},"elevated_shell_command":{"type":"string"},"elevated_shell_argument":{"type":"string"}},"type":"object","required":["shell_command","shell_argument"]},"ShutDownParams":{"properties":{"command":{"type":"string"},"timeout_seconds":{"type":"integer"},"signal":{"type":"integer"},"parent_only":{"type":"boolean"}},"type":"object"},"Vars":{"type":"object"}}} \ No newline at end of file +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://github.com/f1bonacc1/process-compose/src/types/project","$ref":"#/$defs/Project","$defs":{"DependsOnConfig":{"additionalProperties":{"$ref":"#/$defs/ProcessDependency"},"type":"object"},"EnvCmd":{"additionalProperties":{"type":"string"},"type":"object"},"Environment":{"items":{"type":"string"},"type":"array"},"ExecProbe":{"properties":{"command":{"type":"string"},"working_dir":{"type":"string"}},"type":"object"},"HttpProbe":{"properties":{"host":{"type":"string"},"path":{"type":"string"},"scheme":{"type":"string"},"port":{"type":"string"},"num_port":{"type":"integer"}},"type":"object"},"LogRotationConfig":{"properties":{"directory":{"type":"string"},"filename":{"type":"string"},"max_size_mb":{"type":"integer"},"max_backups":{"type":"integer"},"max_age_days":{"type":"integer"},"compress":{"type":"boolean"}},"type":"object"},"LoggerConfig":{"properties":{"rotation":{"$ref":"#/$defs/LogRotationConfig"},"fields_order":{"items":{"type":"string"},"type":"array"},"disable_json":{"type":"boolean"},"timestamp_format":{"type":"string"},"no_color":{"type":"boolean"},"no_metadata":{"type":"boolean"},"add_timestamp":{"type":"boolean"},"flush_each_line":{"type":"boolean"}},"type":"object"},"Probe":{"properties":{"exec":{"$ref":"#/$defs/ExecProbe"},"http_get":{"$ref":"#/$defs/HttpProbe"},"initial_delay_seconds":{"type":"integer"},"period_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"success_threshold":{"type":"integer"},"failure_threshold":{"type":"integer"}},"type":"object"},"ProcessConfig":{"properties":{"name":{"type":"string"},"disabled":{"type":"boolean"},"is_daemon":{"type":"boolean"},"command":{"type":"string"},"entrypoint":{"items":{"type":"string"},"type":"array"},"log_location":{"type":"string"},"log_configuration":{"$ref":"#/$defs/LoggerConfig"},"environment":{"$ref":"#/$defs/Environment"},"availability":{"$ref":"#/$defs/RestartPolicyConfig"},"depends_on":{"$ref":"#/$defs/DependsOnConfig"},"liveness_probe":{"$ref":"#/$defs/Probe"},"readiness_probe":{"$ref":"#/$defs/Probe"},"ready_log_line":{"type":"string"},"shutdown":{"$ref":"#/$defs/ShutDownParams"},"disable_ansi_colors":{"type":"boolean"},"working_dir":{"type":"string"},"namespace":{"type":"string"},"replicas":{"type":"integer"},"description":{"type":"string"},"vars":{"$ref":"#/$defs/Vars"},"is_foreground":{"type":"boolean"},"is_tty":{"type":"boolean"},"is_elevated":{"type":"boolean"},"launch_timeout_seconds":{"type":"integer"},"is_disabled":{"type":"string"},"is_dotenv_disabled":{"type":"boolean"},"original_config":{"type":"string"},"replica_num":{"type":"integer"},"replica_name":{"type":"string"},"executable":{"type":"string"},"args":{"items":{"type":"string"},"type":"array"}},"type":"object","required":["name","original_config","replica_num","replica_name","executable","args"]},"ProcessDependency":{"properties":{"condition":{"type":"integer"}},"type":"object"},"Processes":{"additionalProperties":{"$ref":"#/$defs/ProcessConfig"},"type":"object"},"Project":{"properties":{"version":{"type":"string"},"name":{"type":"string"},"log_location":{"type":"string"},"log_level":{"type":"string"},"log_length":{"type":"integer"},"log_configuration":{"$ref":"#/$defs/LoggerConfig"},"log_format":{"type":"string"},"processes":{"$ref":"#/$defs/Processes"},"environment":{"$ref":"#/$defs/Environment"},"shell":{"$ref":"#/$defs/ShellConfig"},"is_strict":{"type":"boolean"},"vars":{"$ref":"#/$defs/Vars"},"disable_env_expansion":{"type":"boolean"},"is_tui_disabled":{"type":"boolean"},"extends":{"type":"string"},"env_cmds":{"$ref":"#/$defs/EnvCmd"},"file_names":{"items":{"type":"string"},"type":"array"},"env_file_names":{"items":{"type":"string"},"type":"array"},"dot_env_vars":{"additionalProperties":{"type":"string"},"type":"object"}},"type":"object","required":["version","processes","file_names","env_file_names","dot_env_vars"]},"RestartPolicyConfig":{"properties":{"restart":{"type":"integer"},"backoff_seconds":{"type":"integer"},"max_restarts":{"type":"integer"},"exit_on_end":{"type":"boolean"},"exit_on_skipped":{"type":"boolean"}},"type":"object"},"ShellConfig":{"properties":{"shell_command":{"type":"string"},"shell_argument":{"type":"string"},"elevated_shell_command":{"type":"string"},"elevated_shell_argument":{"type":"string"}},"type":"object","required":["shell_command","shell_argument"]},"ShutDownParams":{"properties":{"command":{"type":"string"},"timeout_seconds":{"type":"integer"},"signal":{"type":"integer"},"parent_only":{"type":"boolean"}},"type":"object"},"Vars":{"type":"object"}}} \ No newline at end of file diff --git a/src/api/pc_api.go b/src/api/pc_api.go index 499d2b0f..b4797f7b 100644 --- a/src/api/pc_api.go +++ b/src/api/pc_api.go @@ -289,22 +289,22 @@ func (api *PcApi) IsAlive(c *gin.Context) { } // @Schemes -// @Id GetHostName -// @Description Get process compose hostname -// @Tags Hostname -// @Summary Get Hostname +// @Id GetProjectName +// @Description Get process compose project name +// @Tags ProjectName +// @Summary Get Project Name // @Produce json -// @Success 200 {object} map[string]string "Hostname" +// @Success 200 {object} map[string]string "ProjectName" // @Failure 400 {object} map[string]string -// @Router /hostname [get] -func (api *PcApi) GetHostName(c *gin.Context) { - name, err := api.project.GetHostName() +// @Router /project/name [get] +func (api *PcApi) GetProjectName(c *gin.Context) { + name, err := api.project.GetProjectName() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } - c.JSON(http.StatusOK, gin.H{"name": name}) + c.JSON(http.StatusOK, gin.H{"projectName": name}) } // @Schemes diff --git a/src/api/routes.go b/src/api/routes.go index 07c7fdc7..16d103c8 100644 --- a/src/api/routes.go +++ b/src/api/routes.go @@ -24,7 +24,6 @@ func InitRoutes(useLogger bool, handler *PcApi) *gin.Engine { }) r.GET("/live", handler.IsAlive) - r.GET("/hostname", handler.GetHostName) r.GET("/processes", handler.GetProcesses) r.GET("/process/:name", handler.GetProcess) r.GET("/process/info/:name", handler.GetProcessInfo) @@ -39,6 +38,7 @@ func InitRoutes(useLogger bool, handler *PcApi) *gin.Engine { r.POST("/project/stop", handler.ShutDownProject) r.POST("/project", handler.UpdateProject) r.POST("/project/configuration", handler.ReloadProject) + r.GET("/project/name", handler.GetProjectName) r.GET("/project/state", handler.GetProjectState) r.PATCH("/process/scale/:name/:scale", handler.ScaleProcess) diff --git a/src/app/project_interface.go b/src/app/project_interface.go index 96317cfa..1158e20d 100644 --- a/src/app/project_interface.go +++ b/src/app/project_interface.go @@ -10,7 +10,7 @@ type IProject interface { ShutDownProject() error IsRemote() bool ErrorForSecs() int - GetHostName() (string, error) + GetProjectName() (string, error) GetProjectState(checkMem bool) (*types.ProjectState, error) GetLogLength() int diff --git a/src/app/project_runner.go b/src/app/project_runner.go index 5d1be1da..41bb229a 100644 --- a/src/app/project_runner.go +++ b/src/app/project_runner.go @@ -14,6 +14,7 @@ import ( "github.com/f1bonacc1/process-compose/src/types" "os" "os/user" + "path" "runtime" "slices" "strings" @@ -596,8 +597,23 @@ func (p *ProjectRunner) ErrorForSecs() int { return 0 } -func (p *ProjectRunner) GetHostName() (string, error) { - return p.projectState.HostName, nil +func (p *ProjectRunner) GetProjectName() (string, error) { + hostname, err := os.Hostname() + if err != nil { + log.Err(err).Msg("Failed get hostname") + hostname = "unknown" + } + + name := p.project.Name + if name == "" { + name, err = os.Getwd() + if err != nil { + log.Err(err).Msg("Failed get CWD") + name = "unknown" + } + } + + return fmt.Sprintf("%s/%s", hostname, path.Base(name)), nil } func (p *ProjectRunner) getProcessLog(name string) (*pclog.ProcessLogBuffer, error) { @@ -908,12 +924,6 @@ func bToMb(b uint64) uint64 { } func NewProjectRunner(opts *ProjectOpts) (*ProjectRunner, error) { - - hostname, err := os.Hostname() - if err != nil { - log.Err(err).Msg("Failed get hostname") - hostname = "unknown" - } current, err := user.Current() username := "unknown-user" if err != nil { @@ -935,11 +945,17 @@ func NewProjectRunner(opts *ProjectOpts) (*ProjectRunner, error) { FileNames: opts.project.FileNames, StartTime: time.Now(), UserName: username, - HostName: hostname, Version: config.Version, }, } + name, err := runner.GetProjectName() + if err != nil { + log.Err(err).Msg("Failed get project name") + } else { + runner.projectState.ProjectName = name + } + if opts.noDeps { err = runner.selectRunningProcessesNoDeps(opts.processesToRun) } else { diff --git a/src/app/project_runner_test.go b/src/app/project_runner_test.go index 06ffc77f..0adc319b 100644 --- a/src/app/project_runner_test.go +++ b/src/app/project_runner_test.go @@ -3,6 +3,7 @@ package app import ( "github.com/f1bonacc1/process-compose/src/types" "reflect" + "strings" "testing" ) @@ -252,3 +253,43 @@ func TestProject_GetDependenciesOrderNames(t *testing.T) { }) } } + +func TestProjectRunner_GetProjectName(t *testing.T) { + type fields struct{ Name string } + tests := []struct { + name string + fields fields + want string + wantErr bool + }{ + { + name: "ShouldContain_project name", + fields: fields{Name: "project name"}, + want: "project name", + }, + { + name: "ShouldContain_app", + want: "app", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &ProjectRunner{ + project: &types.Project{ + Name: tt.fields.Name, + }, + } + + got, err := p.GetProjectName() + if (err != nil) != tt.wantErr { + t.Errorf("ProjectRunner.GetProjectName() error = %v, wantErr %v", err, nil) + return + } + + if !strings.Contains(got, tt.want) { + t.Errorf("ProjectRunner.GetProjectName() = %s, want %s", got, tt.want) + } + }) + } +} diff --git a/src/client/client.go b/src/client/client.go index 739a9ce3..e70afcb9 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -67,8 +67,8 @@ func (p *PcClient) IsRemote() bool { return true } -func (p *PcClient) GetHostName() (string, error) { - return p.getHostName() +func (p *PcClient) GetProjectName() (string, error) { + return p.getProjectName() } func (p *PcClient) GetLogLength() int { diff --git a/src/client/status.go b/src/client/status.go index d59a2eb6..eb0bb4fd 100644 --- a/src/client/status.go +++ b/src/client/status.go @@ -20,8 +20,8 @@ func (p *PcClient) isAlive() error { return nil } -func (p *PcClient) getHostName() (string, error) { - url := fmt.Sprintf("http://%s/hostname", p.address) +func (p *PcClient) getProjectName() (string, error) { + url := fmt.Sprintf("http://%s/project/name", p.address) resp, err := p.client.Get(url) if err != nil { return "", err @@ -37,5 +37,5 @@ func (p *PcClient) getHostName() (string, error) { log.Err(err).Send() return "", err } - return nameMap["name"], nil + return nameMap["projectName"], nil } diff --git a/src/cmd/state.go b/src/cmd/state.go index ab0ed6c2..bfc1fe25 100644 --- a/src/cmd/state.go +++ b/src/cmd/state.go @@ -35,7 +35,7 @@ func printState(state *types.ProjectState) { green := col.SprintFunc() longestKey := len("Running Processes") - printStateLine("Hostname", state.HostName, longestKey, green) + printStateLine("Project", state.ProjectName, longestKey, green) printStateLine("User", state.UserName, longestKey, green) printStateLine("Version", state.Version, longestKey, green) printStateLine("Up Time", state.UpTime.Round(time.Second).String(), longestKey, green) diff --git a/src/docs/docs.go b/src/docs/docs.go index 5ac95f10..91466669 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -22,39 +22,6 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/hostname": { - "get": { - "description": "Get process compose hostname", - "produces": [ - "application/json" - ], - "tags": [ - "Hostname" - ], - "summary": "Get Hostname", - "operationId": "GetHostName", - "responses": { - "200": { - "description": "Hostname", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, "/live": { "get": { "description": "Check if server is responding", @@ -669,6 +636,39 @@ const docTemplate = `{ } } }, + "/project/name": { + "get": { + "description": "Get process compose project name", + "produces": [ + "application/json" + ], + "tags": [ + "ProjectName" + ], + "summary": "Get Project Name", + "operationId": "GetProjectName", + "responses": { + "200": { + "description": "ProjectName", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, "/project/state": { "get": { "description": "Retrieves project state information", @@ -1091,15 +1091,15 @@ const docTemplate = `{ "type": "string" } }, - "hostName": { - "type": "string" - }, "memoryState": { "$ref": "#/definitions/types.MemoryState" }, "processNum": { "type": "integer" }, + "projectName": { + "type": "string" + }, "runningProcessNum": { "type": "integer" }, diff --git a/src/docs/swagger.json b/src/docs/swagger.json index 635a6301..574ac966 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -366,15 +366,15 @@ }, "type": "array" }, - "hostName": { - "type": "string" - }, "memoryState": { "$ref": "#/components/schemas/types.MemoryState" }, "processNum": { "type": "integer" }, + "projectName": { + "type": "string" + }, "runningProcessNum": { "type": "integer" }, @@ -454,44 +454,6 @@ }, "openapi": "3.0.3", "paths": { - "/hostname": { - "get": { - "description": "Get process compose hostname", - "operationId": "GetHostName", - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - } - } - }, - "description": "Hostname" - }, - "400": { - "content": { - "application/json": { - "schema": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - } - } - }, - "description": "Bad Request" - } - }, - "summary": "Get Hostname", - "tags": [ - "Hostname" - ] - } - }, "/live": { "get": { "description": "Check if server is responding", @@ -1207,6 +1169,44 @@ ] } }, + "/project/name": { + "get": { + "description": "Get process compose project name", + "operationId": "GetProjectName", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + } + } + }, + "description": "ProjectName" + }, + "400": { + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get Project Name", + "tags": [ + "ProjectName" + ] + } + }, "/project/state": { "get": { "description": "Retrieves project state information", diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index 29a0eb18..d2e81c75 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -246,12 +246,12 @@ components: items: type: string type: array - hostName: - type: string memoryState: $ref: '#/components/schemas/types.MemoryState' processNum: type: integer + projectName: + type: string runningProcessNum: type: integer startTime: @@ -304,30 +304,6 @@ info: version: "1.0" openapi: 3.0.3 paths: - /hostname: - get: - description: Get process compose hostname - operationId: GetHostName - responses: - "200": - content: - application/json: - schema: - additionalProperties: - type: string - type: object - description: Hostname - "400": - content: - application/json: - schema: - additionalProperties: - type: string - type: object - description: Bad Request - summary: Get Hostname - tags: - - Hostname /live: get: description: Check if server is responding @@ -781,6 +757,30 @@ paths: summary: Reload project tags: - Project + /project/name: + get: + description: Get process compose project name + operationId: GetProjectName + responses: + "200": + content: + application/json: + schema: + additionalProperties: + type: string + type: object + description: ProjectName + "400": + content: + application/json: + schema: + additionalProperties: + type: string + type: object + description: Bad Request + summary: Get Project Name + tags: + - ProjectName /project/state: get: description: Retrieves project state information diff --git a/src/tui/stat-table.go b/src/tui/stat-table.go index e37ef566..81aad0d8 100644 --- a/src/tui/stat-table.go +++ b/src/tui/stat-table.go @@ -19,10 +19,9 @@ func (pv *pcView) createStatTable() *tview.Table { table.SetCell(0, 1, tview.NewTableCell(config.Version). SetSelectable(false).SetExpansion(1)) - table.SetCell(1, 0, tview.NewTableCell(pv.getHostNameTitle()). + table.SetCell(1, 0, tview.NewTableCell("Project:"). SetSelectable(false)) - hostname := pv.getHostName() - table.SetCell(1, 1, tview.NewTableCell(hostname). + table.SetCell(1, 1, tview.NewTableCell(pv.getProjectName()). SetSelectable(false). SetExpansion(1)) @@ -63,21 +62,14 @@ func (pv *pcView) getPcTitle() string { } } -func (pv *pcView) getHostName() string { - name, err := pv.project.GetHostName() +func (pv *pcView) getProjectName() string { + name, err := pv.project.GetProjectName() if err != nil { - log.Err(err).Msg("Unable to retrieve hostname") + log.Err(err).Msg("Unable to retrieve name") return "Unknown" } - return name -} -func (pv *pcView) getHostNameTitle() string { - if pv.project.IsRemote() { - return "Server Name:" - } else { - return "Hostname:" - } + return name } // AttentionMessage shows an attention message in the status table diff --git a/src/types/project.go b/src/types/project.go index 5bdbab1e..a898e5d5 100644 --- a/src/types/project.go +++ b/src/types/project.go @@ -10,6 +10,7 @@ type Vars map[string]any type Project struct { Version string `yaml:"version"` + Name string `yaml:"name,omitempty"` LogLocation string `yaml:"log_location,omitempty"` LogLevel string `yaml:"log_level,omitempty"` LogLength int `yaml:"log_length,omitempty"` diff --git a/src/types/project_state.go b/src/types/project_state.go index ba9eccb4..348212cb 100644 --- a/src/types/project_state.go +++ b/src/types/project_state.go @@ -9,8 +9,8 @@ type ProjectState struct { ProcessNum int `json:"processNum"` RunningProcessNum int `json:"runningProcessNum"` UserName string `json:"userName"` - HostName string `json:"hostName"` Version string `json:"version"` + ProjectName string `json:"projectName"` MemoryState *MemoryState `json:"memoryState,omitempty"` } From 66e80ca0a9c07539a8187b0249ff4aacc52d98f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20C=2E=20M=C3=BCller?= Date: Tue, 15 Jul 2025 09:25:14 -0400 Subject: [PATCH 2/3] feat: set the terminal title to the project name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Juan C. Müller --- src/cmd/project_runner.go | 2 ++ src/tui/view.go | 4 ++++ src/util/terminal.go | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 src/util/terminal.go diff --git a/src/cmd/project_runner.go b/src/cmd/project_runner.go index 4e480101..55b51522 100644 --- a/src/cmd/project_runner.go +++ b/src/cmd/project_runner.go @@ -6,6 +6,7 @@ import ( "github.com/f1bonacc1/process-compose/src/config" "github.com/f1bonacc1/process-compose/src/loader" "github.com/f1bonacc1/process-compose/src/tui" + "github.com/f1bonacc1/process-compose/src/util" "github.com/rs/zerolog/log" "os" "os/signal" @@ -68,6 +69,7 @@ func setSignal(signalHandler func()) { } func runHeadless(project *app.ProjectRunner) error { + util.SetProjectNameAsTerminalTitle(project) setSignal(func() { _ = project.ShutDownProject() }) diff --git a/src/tui/view.go b/src/tui/view.go index 4271bb6d..b585c983 100644 --- a/src/tui/view.go +++ b/src/tui/view.go @@ -17,6 +17,7 @@ import ( "syscall" "time" + "github.com/f1bonacc1/process-compose/src/util" "github.com/f1bonacc1/process-compose/src/app" "github.com/rivo/tview" ) @@ -141,6 +142,7 @@ func newPcView(project app.IProject) *pcView { pv.appView.SetRoot(pv.pages, true).EnableMouse(true).SetInputCapture(pv.onAppKey) pv.recreateHelpDialog() pv.loadThemes() + util.SetProjectNameAsTerminalTitle(pv.project) if len(pv.procNames) > 0 { name := pv.procNames[0] @@ -513,12 +515,14 @@ func (pv *pcView) startMonitoring() { isErrorDetected := false for { if err := pcClient.IsAlive(); err != nil { + util.SetTerminalTitle("unknown") pv.handleConnectivityError() isErrorDetected = true } else { if isErrorDetected { isErrorDetected = false pv.hideAttentionMessage() + util.SetProjectNameAsTerminalTitle(pv.project) } } time.Sleep(time.Second) diff --git a/src/util/terminal.go b/src/util/terminal.go new file mode 100644 index 00000000..af4094cc --- /dev/null +++ b/src/util/terminal.go @@ -0,0 +1,21 @@ +package util + +import ( + "fmt" + + "github.com/rs/zerolog/log" +) + +type projectNamer interface{ GetProjectName() (string, error) } + +func SetProjectNameAsTerminalTitle(n projectNamer) { + name, err := n.GetProjectName() + if err != nil { + log.Err(err).Msgf("Failed to set terminal title: %v", err) + return + } + + SetTerminalTitle(name) +} + +func SetTerminalTitle(title string) { fmt.Printf("\033]0;process-compose: %s\007", title) } From 303fc9da33e76f3f60239b1ce0f9262840e63215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20C=2E=20M=C3=BCller?= Date: Tue, 15 Jul 2025 09:25:35 -0400 Subject: [PATCH 3/3] docs: commit missing swagger attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Juan C. Müller --- src/docs/docs.go | 36 ++++++++++++++++++++++++++++++++++-- src/docs/swagger.json | 36 ++++++++++++++++++++++++++++++++++-- src/docs/swagger.yaml | 30 ++++++++++++++++++++++++++++-- 3 files changed, 96 insertions(+), 6 deletions(-) diff --git a/src/docs/docs.go b/src/docs/docs.go index 91466669..65744066 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -878,6 +878,23 @@ const docTemplate = `{ } } }, + "types.ProcessCondition": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4 + ], + "x-enum-varnames": [ + "ProcessConditionCompleted", + "ProcessConditionCompletedSuccessfully", + "ProcessConditionHealthy", + "ProcessConditionStarted", + "ProcessConditionLogReady" + ] + }, "types.ProcessConfig": { "type": "object", "properties": { @@ -993,7 +1010,7 @@ const docTemplate = `{ "type": "object", "properties": { "condition": { - "type": "string" + "$ref": "#/definitions/types.ProcessCondition" }, "extensions": { "type": "object", @@ -1117,6 +1134,21 @@ const docTemplate = `{ } } }, + "types.RestartPolicy": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3 + ], + "x-enum-varnames": [ + "RestartPolicyNo", + "RestartPolicyAlways", + "RestartPolicyOnFailure", + "RestartPolicyExitOnFailure" + ] + }, "types.RestartPolicyConfig": { "type": "object", "properties": { @@ -1133,7 +1165,7 @@ const docTemplate = `{ "type": "integer" }, "restart": { - "type": "string" + "$ref": "#/definitions/types.RestartPolicy" } } }, diff --git a/src/docs/swagger.json b/src/docs/swagger.json index 574ac966..0869d884 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -154,6 +154,23 @@ }, "type": "object" }, + "types.ProcessCondition": { + "enum": [ + 0, + 1, + 2, + 3, + 4 + ], + "type": "integer", + "x-enum-varnames": [ + "ProcessConditionCompleted", + "ProcessConditionCompletedSuccessfully", + "ProcessConditionHealthy", + "ProcessConditionStarted", + "ProcessConditionLogReady" + ] + }, "types.ProcessConfig": { "properties": { "args": { @@ -268,7 +285,7 @@ "types.ProcessDependency": { "properties": { "condition": { - "type": "string" + "$ref": "#/components/schemas/types.ProcessCondition" }, "extensions": { "additionalProperties": true, @@ -393,6 +410,21 @@ }, "type": "object" }, + "types.RestartPolicy": { + "enum": [ + 0, + 1, + 2, + 3 + ], + "type": "integer", + "x-enum-varnames": [ + "RestartPolicyNo", + "RestartPolicyAlways", + "RestartPolicyOnFailure", + "RestartPolicyExitOnFailure" + ] + }, "types.RestartPolicyConfig": { "properties": { "backoffSeconds": { @@ -408,7 +440,7 @@ "type": "integer" }, "restart": { - "type": "string" + "$ref": "#/components/schemas/types.RestartPolicy" } }, "type": "object" diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index d2e81c75..60975aff 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -105,6 +105,20 @@ components: totalAllocated: type: integer type: object + types.ProcessCondition: + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + type: integer + x-enum-varnames: + - ProcessConditionCompleted + - ProcessConditionCompletedSuccessfully + - ProcessConditionHealthy + - ProcessConditionStarted + - ProcessConditionLogReady types.ProcessConfig: properties: args: @@ -182,7 +196,7 @@ components: types.ProcessDependency: properties: condition: - type: string + $ref: '#/components/schemas/types.ProcessCondition' extensions: additionalProperties: true type: object @@ -263,6 +277,18 @@ components: version: type: string type: object + types.RestartPolicy: + enum: + - 0 + - 1 + - 2 + - 3 + type: integer + x-enum-varnames: + - RestartPolicyNo + - RestartPolicyAlways + - RestartPolicyOnFailure + - RestartPolicyExitOnFailure types.RestartPolicyConfig: properties: backoffSeconds: @@ -274,7 +300,7 @@ components: maxRestarts: type: integer restart: - type: string + $ref: '#/components/schemas/types.RestartPolicy' type: object types.ShutDownParams: properties: