Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 82 additions & 42 deletions backend/internal/hub/routes/applications.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,42 @@ type updateApplicationRequest struct {
}

type applicationListResponse struct {
Id string `json:"id"`
HealthStatus string `json:"healthStatus"`
SyncStatus string `json:"syncStatus"`
Branch string `json:"branch"`
Commit string `json:"commit"`
LastSyncedAt *string `json:"lastSyncedAt"`
Id string `json:"id"`
Name string `json:"name"`
HealthStatus string `json:"healthStatus"`
SyncStatus string `json:"syncStatus"`
Branch string `json:"branch"`
Commit string `json:"commit"`
LastSyncedAt *string `json:"lastSyncedAt"`
Path string `json:"path"`
AgentName string `json:"agentName"`
RepositoryName string `json:"repositoryName"`
}

type applicationResponse struct {
Id string `json:"id"`
Name string `json:"name"`
RepositoryId string `json:"repositoryId"`
AgentId string `json:"agentId"`
SyncStatus string `json:"syncStatus"`
HealthStatus string `json:"healthStatus"`
Branch string `json:"branch"`
Commit string `json:"commit"`
CommitMessage string `json:"commitMessage"`
LastSyncedAt *string `json:"lastSyncedAt"`
Path string `json:"path"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Id string `json:"id"`
Name string `json:"name"`
RepositoryId string `json:"repositoryId"`
RepositoryName string `json:"repositoryName"`
AgentId string `json:"agentId"`
AgentName string `json:"agentName"`
SyncStatus string `json:"syncStatus"`
HealthStatus string `json:"healthStatus"`
Branch string `json:"branch"`
Commit string `json:"commit"`
CommitMessage string `json:"commitMessage"`
LastSyncedAt *string `json:"lastSyncedAt"`
Path string `json:"path"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}

func ListApplicationsHandler(c *gin.Context) {
applications, err := gorm.G[models.Application](db.DB).Order("created_at ASC").Find(c.Request.Context())
applications, err := gorm.G[models.Application](db.DB).
Preload("Repository", nil).
Preload("Agent", nil).
Order("created_at ASC").
Find(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
return
Expand All @@ -71,7 +81,11 @@ func ListApplicationsHandler(c *gin.Context) {
func GetApplicationHandler(c *gin.Context) {
id := c.Param("id")

application, err := gorm.G[models.Application](db.DB).Where("id = ?", id).First(c.Request.Context())
application, err := gorm.G[models.Application](db.DB).
Preload("Repository", nil).
Preload("Agent", nil).
Where("id = ?", id).
First(c.Request.Context())
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "application not found"})
Expand Down Expand Up @@ -133,7 +147,17 @@ func CreateApplicationHandler(c *gin.Context) {
return
}

c.JSON(http.StatusCreated, toApplicationResponse(&application))
createdApplication, err := gorm.G[models.Application](db.DB).
Preload("Repository", nil).
Preload("Agent", nil).
Where("id = ?", application.Id).
First(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
return
}

c.JSON(http.StatusCreated, toApplicationResponse(&createdApplication))
}

func UpdateApplicationHandler(c *gin.Context) {
Expand Down Expand Up @@ -190,7 +214,17 @@ func UpdateApplicationHandler(c *gin.Context) {
return
}

c.JSON(http.StatusOK, toApplicationResponse(&application))
updatedApplication, err := gorm.G[models.Application](db.DB).
Preload("Repository", nil).
Preload("Agent", nil).
Where("id = ?", id).
First(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
return
}

c.JSON(http.StatusOK, toApplicationResponse(&updatedApplication))
}

func DeleteApplicationHandler(c *gin.Context) {
Expand All @@ -211,30 +245,36 @@ func DeleteApplicationHandler(c *gin.Context) {

func toApplicationListResponse(app *models.Application) applicationListResponse {
return applicationListResponse{
Id: app.Id,
HealthStatus: string(app.HealthStatus),
SyncStatus: string(app.SyncStatus),
Branch: app.Branch,
Commit: app.Commit,
LastSyncedAt: formatTimestamp(app.LastSyncedAt),
Id: app.Id,
Name: app.Name.String(),
HealthStatus: string(app.HealthStatus),
SyncStatus: string(app.SyncStatus),
Branch: app.Branch,
Commit: app.Commit,
LastSyncedAt: formatTimestamp(app.LastSyncedAt),
Path: app.Path,
RepositoryName: app.Repository.Name,
AgentName: app.Agent.Name.String(),
}
}

func toApplicationResponse(app *models.Application) applicationResponse {
return applicationResponse{
Id: app.Id,
Name: app.Name.String(),
RepositoryId: app.RepositoryId,
AgentId: app.AgentId,
SyncStatus: string(app.SyncStatus),
HealthStatus: string(app.HealthStatus),
Branch: app.Branch,
Commit: app.Commit,
CommitMessage: app.CommitMessage,
LastSyncedAt: formatTimestamp(app.LastSyncedAt),
Path: app.Path,
CreatedAt: app.CreatedAt.Format(time.RFC3339),
UpdatedAt: app.UpdatedAt.Format(time.RFC3339),
Id: app.Id,
Name: app.Name.String(),
RepositoryId: app.RepositoryId,
RepositoryName: app.Repository.Name,
AgentId: app.AgentId,
AgentName: app.Agent.Name.String(),
SyncStatus: string(app.SyncStatus),
HealthStatus: string(app.HealthStatus),
Branch: app.Branch,
Commit: app.Commit,
CommitMessage: app.CommitMessage,
LastSyncedAt: formatTimestamp(app.LastSyncedAt),
Path: app.Path,
CreatedAt: app.CreatedAt.Format(time.RFC3339),
UpdatedAt: app.UpdatedAt.Format(time.RFC3339),
}
}

Expand Down
33 changes: 31 additions & 2 deletions backend/internal/hub/routes/applications_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,14 @@ func TestListApplicationsHandler_ReturnsSummaryFields(t *testing.T) {
if item["commit"] != "abcdef123" {
t.Errorf("expected commit %q, got %v", "abcdef123", item["commit"])
}
if _, ok := item["name"]; ok {
t.Error("list response should not include name field")
if item["name"] != "Summary App" {
t.Errorf("expected name %q, got %v", "Summary App", item["name"])
}
if item["repositoryName"] != repo.Name {
t.Errorf("expected repositoryName %q, got %v", repo.Name, item["repositoryName"])
}
if item["agentName"] != "agent-summary" {
t.Errorf("expected agentName %q, got %v", "agent-summary", item["agentName"])
}
}

Expand Down Expand Up @@ -222,6 +228,12 @@ func TestGetApplicationHandler_ReturnsAllFields(t *testing.T) {
if body.AgentId != agent.Id {
t.Errorf("expected agentId %q, got %q", agent.Id, body.AgentId)
}
if body.RepositoryName != repo.Name {
t.Errorf("expected repositoryName %q, got %q", repo.Name, body.RepositoryName)
}
if body.AgentName != "agent-detail" {
t.Errorf("expected agentName %q, got %q", "agent-detail", body.AgentName)
}
if body.CommitMessage != "initial commit" {
t.Errorf("expected commitMessage %q, got %q", "initial commit", body.CommitMessage)
}
Expand Down Expand Up @@ -300,6 +312,12 @@ func TestCreateApplicationHandler_Success(t *testing.T) {
if body.Name != "Billing Service" {
t.Errorf("expected name %q, got %q", "Billing Service", body.Name)
}
if body.RepositoryName != repo.Name {
t.Errorf("expected repositoryName %q, got %q", repo.Name, body.RepositoryName)
}
if body.AgentName != "agent-create" {
t.Errorf("expected agentName %q, got %q", "agent-create", body.AgentName)
}
if body.SyncStatus != string(models.UnknownSync) {
t.Errorf("expected syncStatus %q, got %q", models.UnknownSync, body.SyncStatus)
}
Expand Down Expand Up @@ -553,6 +571,17 @@ func TestUpdateApplicationHandler_Success(t *testing.T) {
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
}

var body applicationResponse
if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
t.Fatalf("invalid JSON: %v", err)
}
if body.RepositoryName != newRepo.Name {
t.Errorf("expected repositoryName %q, got %q", newRepo.Name, body.RepositoryName)
}
if body.AgentName != "agent-update-2" {
t.Errorf("expected agentName %q, got %q", "agent-update-2", body.AgentName)
}

updated, err := gorm.G[models.Application](db.DB).Where("id = ?", app.Id).First(t.Context())
if err != nil {
t.Fatalf("failed to load updated application: %v", err)
Expand Down
Loading
Loading