Skip to content

Commit 5bff3b7

Browse files
vistaarjunejaHarness
authored andcommitted
add ACM support in external mode (#140)
* fixed last run type * add ACM support in external mode
1 parent 26cc583 commit 5bff3b7

File tree

6 files changed

+507
-1
lines changed

6 files changed

+507
-1
lines changed

client/acm.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package client
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log/slog"
7+
8+
"github.com/harness/harness-mcp/client/dto"
9+
)
10+
11+
const (
12+
acmCreateTaskPath = "/api/v1/accounts/%s/tasks"
13+
acmRunTaskPath = "/api/v1/accounts/%s/executions"
14+
)
15+
16+
// ACMService provides methods to interact with the Autonomous Code Maintenance API
17+
type ACMService struct {
18+
Client *Client
19+
}
20+
21+
// CreateTask creates a new autonomous code maintenance task
22+
func (s *ACMService) CreateTask(ctx context.Context, scope dto.Scope, params *dto.CreateACMTaskRequest) (*dto.ACMTaskResponse, error) {
23+
// Build the path
24+
path := fmt.Sprintf(acmCreateTaskPath, scope.AccountID)
25+
26+
// Set up query parameters
27+
queryParams := make(map[string]string)
28+
29+
headers := make(map[string]string)
30+
addHarnessAccountToHeaders(scope, headers)
31+
32+
// Make the request
33+
result := new(dto.ACMTaskResponse)
34+
err := s.Client.Post(ctx, path, queryParams, params, headers, result)
35+
if err != nil {
36+
return nil, fmt.Errorf("failed to create ACM task: %w", err)
37+
}
38+
39+
return result, nil
40+
}
41+
42+
// ListTaskExecutions lists executions of an autonomous code maintenance task
43+
func (s *ACMService) ListTaskExecutions(ctx context.Context, scope dto.Scope, params *dto.GetACMExecutionsRequest) (*dto.ACMExecutionsListResponse, error) {
44+
// Build the path
45+
path := fmt.Sprintf(acmRunTaskPath, scope.AccountID)
46+
47+
// Set up query parameters
48+
queryParams := make(map[string]string)
49+
50+
headers := make(map[string]string)
51+
addHarnessAccountToHeaders(scope, headers)
52+
53+
// Add specific query parameters for this endpoint
54+
queryParams["task_id"] = params.TaskID
55+
queryParams["page"] = fmt.Sprintf("%d", params.Page)
56+
queryParams["limit"] = fmt.Sprintf("%d", params.Limit)
57+
58+
// Make the request
59+
result := new(dto.ACMExecutionsListResponse)
60+
err := s.Client.Get(ctx, path, queryParams, headers, result)
61+
if err != nil {
62+
return nil, fmt.Errorf("failed to list ACM task executions: %w", err)
63+
}
64+
65+
return result, nil
66+
}
67+
68+
// TriggerTaskExecution triggers execution of an autonomous code maintenance task
69+
func (s *ACMService) TriggerTaskExecution(ctx context.Context, scope dto.Scope, params *dto.TriggerACMTaskExecutionRequest) (*dto.ACMExecution, error) {
70+
// Build the path
71+
path := fmt.Sprintf(acmRunTaskPath, scope.AccountID)
72+
73+
// Set up query parameters
74+
queryParams := make(map[string]string)
75+
76+
headers := make(map[string]string)
77+
addHarnessAccountToHeaders(scope, headers)
78+
79+
slog.Info("triggering ACM task execution", "task_id", params.TaskID, "repository_id", params.RepositoryID, "source_branch", params.SourceBranch)
80+
81+
// Make the request
82+
result := new(dto.ACMExecution)
83+
err := s.Client.Post(ctx, path, queryParams, params, headers, result)
84+
if err != nil {
85+
return nil, fmt.Errorf("failed to trigger ACM task execution: %w", err)
86+
}
87+
88+
return result, nil
89+
}

client/dto/acm.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package dto
2+
3+
// CreateACMTaskRequest represents the request to create an autonomous code maintenance task
4+
type CreateACMTaskRequest struct {
5+
Name string `json:"name"`
6+
Identifier string `json:"identifier"`
7+
Instructions string `json:"instructions"`
8+
Path string `json:"path"` // project and org path
9+
}
10+
11+
// ACMTaskResponse represents the response from creating an autonomous code maintenance task
12+
type ACMTaskResponse struct {
13+
ID string `json:"id"`
14+
SpaceID string `json:"space_id"`
15+
Identifier string `json:"identifier"`
16+
Name string `json:"name"`
17+
CreatedBy TriggeredBy `json:"created_by"`
18+
Created int64 `json:"created"`
19+
Updated int64 `json:"updated"`
20+
Instructions string `json:"instructions"`
21+
ExecutionCount int `json:"execution_count"`
22+
LastRun *ACMExecution `json:"last_run"`
23+
}
24+
25+
// TriggerACMTaskExecutionRequest represents the request to trigger execution of an autonomous code maintenance task
26+
type TriggerACMTaskExecutionRequest struct {
27+
TaskID string `json:"task_id"`
28+
RepositoryID string `json:"repository_id"`
29+
SourceBranch string `json:"source_branch"`
30+
}
31+
32+
// GetACMExecutionsRequest represents the request to get executions of an autonomous code maintenance task
33+
type GetACMExecutionsRequest struct {
34+
TaskID string `json:"task_id"`
35+
Page int `json:"page"`
36+
Limit int `json:"limit"`
37+
}
38+
39+
// ACMExecution represents a single execution of an autonomous code maintenance task
40+
type ACMExecution struct {
41+
ID string `json:"id"`
42+
TaskID string `json:"task_id"`
43+
TaskType string `json:"task_type"`
44+
TriggeredBy TriggeredBy `json:"triggered_by"`
45+
Triggered int64 `json:"triggered"`
46+
Started int64 `json:"started"`
47+
Completed int64 `json:"completed,omitempty"`
48+
Input TaskInput `json:"input"`
49+
Output TaskOutput `json:"output"`
50+
Status string `json:"status"`
51+
}
52+
53+
// TriggeredBy represents the entity who triggered the execution
54+
type TriggeredBy struct {
55+
UUID string `json:"uuid"`
56+
Name string `json:"name"`
57+
Email string `json:"email"`
58+
Type string `json:"type"`
59+
}
60+
61+
// TaskInput represents the input parameters for a task execution
62+
type TaskInput struct {
63+
Name string `json:"name"`
64+
Instructions string `json:"instructions"`
65+
RepositoryID string `json:"repository_id"`
66+
SourceBranch string `json:"source_branch"`
67+
TargetBranch string `json:"target_branch"`
68+
}
69+
70+
type TaskOutput struct {
71+
// Can be expanded with specific fields as needed
72+
}
73+
74+
// ACMExecutionsListResponse represents the response from listing executions of an autonomous code maintenance task
75+
type ACMExecutionsListResponse []ACMExecution

pkg/harness/tools.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ func initLegacyToolsets(config *config.Config, tsg *toolsets.ToolsetGroup) error
271271
if err := modules.RegisterInfrastructure(config, tsg); err != nil {
272272
return err
273273
}
274+
if err := modules.RegisterACM(config, tsg); err != nil {
275+
return err
276+
}
274277
} else {
275278
// Register specified toolsets
276279
for _, toolset := range config.Toolsets {
@@ -367,6 +370,10 @@ func initLegacyToolsets(config *config.Config, tsg *toolsets.ToolsetGroup) error
367370
if err := modules.RegisterInfrastructure(config, tsg); err != nil {
368371
return err
369372
}
373+
case "acm":
374+
if err := modules.RegisterACM(config, tsg); err != nil {
375+
return err
376+
}
370377
}
371378
}
372379
}
@@ -424,4 +431,3 @@ func RegisterDefault(config *config.Config, tsg *toolsets.ToolsetGroup) error {
424431
tsg.AddToolset(defaultToolset)
425432
return nil
426433
}
427-

0 commit comments

Comments
 (0)