b4aa51d130
Co-authored-by: nova28 <17953305+nova28@users.noreply.github.com> Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
219 lines
8.9 KiB
Go
219 lines
8.9 KiB
Go
package plugins
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/kandev/kandev/pkg/pluginsdk"
|
|
)
|
|
|
|
type webAppPageInfo struct {
|
|
NextCursor string `json:"next_cursor,omitempty"`
|
|
HasMore bool `json:"has_more"`
|
|
}
|
|
|
|
type webAppPage[T any] struct {
|
|
Items []T `json:"items"`
|
|
PageInfo webAppPageInfo `json:"page_info"`
|
|
}
|
|
|
|
func webAppPageFromSDK[T any](items []T, info *pluginsdk.PageInfo) webAppPage[T] {
|
|
page := webAppPage[T]{Items: items}
|
|
if info != nil {
|
|
page.PageInfo = webAppPageInfo{NextCursor: info.NextCursor, HasMore: info.HasMore}
|
|
}
|
|
return page
|
|
}
|
|
|
|
func writeWebAppJSON(w http.ResponseWriter, r *http.Request, status int, value any) {
|
|
body, err := json.Marshal(value)
|
|
if err != nil {
|
|
writeWebAppError(w, http.StatusInternalServerError, webAppRuntimeUnavailable)
|
|
return
|
|
}
|
|
if len(body) > webAppResponseLimit {
|
|
writeWebAppError(w, http.StatusInternalServerError, "response_too_large")
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
w.WriteHeader(status)
|
|
if r == nil || r.Method != http.MethodHead {
|
|
_, _ = w.Write(body)
|
|
}
|
|
}
|
|
|
|
func writeWebAppError(w http.ResponseWriter, status int, code string) {
|
|
body, err := json.Marshal(struct {
|
|
Error string `json:"error"`
|
|
}{Error: code})
|
|
if err != nil {
|
|
body = []byte(`{"error":"runtime_unavailable"}`)
|
|
}
|
|
w.Header().Set("Cache-Control", "no-store")
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
w.WriteHeader(status)
|
|
_, _ = w.Write(body)
|
|
}
|
|
|
|
type webAppTaskRepository struct {
|
|
ID string `json:"id"`
|
|
RepositoryID string `json:"repository_id"`
|
|
BaseBranch string `json:"base_branch"`
|
|
Position int32 `json:"position"`
|
|
CheckoutBranch string `json:"checkout_branch"`
|
|
}
|
|
|
|
type webAppPullRequest struct {
|
|
Number int64 `json:"number"`
|
|
URL string `json:"url"`
|
|
Title string `json:"title"`
|
|
State string `json:"state"`
|
|
HeadBranch string `json:"head_branch"`
|
|
BaseBranch string `json:"base_branch"`
|
|
IsDraft bool `json:"is_draft"`
|
|
Provider string `json:"provider"`
|
|
MergedAt *string `json:"merged_at,omitempty"`
|
|
ClosedAt *string `json:"closed_at,omitempty"`
|
|
ReviewState string `json:"review_state"`
|
|
ChecksState string `json:"checks_state"`
|
|
MergeableState string `json:"mergeable_state"`
|
|
UnresolvedReviewThreads int32 `json:"unresolved_review_threads"`
|
|
ChecksTotal int32 `json:"checks_total"`
|
|
ChecksPassing int32 `json:"checks_passing"`
|
|
Additions int32 `json:"additions"`
|
|
Deletions int32 `json:"deletions"`
|
|
AuthorLogin string `json:"author_login"`
|
|
}
|
|
|
|
type webAppTask struct {
|
|
ID string `json:"id"`
|
|
WorkspaceID string `json:"workspace_id"`
|
|
WorkflowID string `json:"workflow_id"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
State string `json:"state"`
|
|
Priority string `json:"priority"`
|
|
CreatedBy string `json:"created_by"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
StartedAt *string `json:"started_at,omitempty"`
|
|
CompletedAt *string `json:"completed_at,omitempty"`
|
|
ParentID *string `json:"parent_id,omitempty"`
|
|
Identifier string `json:"identifier"`
|
|
IsEphemeral bool `json:"is_ephemeral"`
|
|
Repositories []webAppTaskRepository `json:"repositories,omitempty"`
|
|
Metadata map[string]any `json:"metadata,omitempty"`
|
|
ArchivedAt *string `json:"archived_at,omitempty"`
|
|
PullRequests []webAppPullRequest `json:"pull_requests,omitempty"`
|
|
WorkflowStepID string `json:"workflow_step_id"`
|
|
Position int32 `json:"position"`
|
|
AssigneeAgentProfileID string `json:"assignee_agent_profile_id"`
|
|
Labels []string `json:"labels,omitempty"`
|
|
Autopilot bool `json:"autopilot"`
|
|
WIPAdmitted bool `json:"wip_admitted"`
|
|
QueuedForStepID string `json:"queued_for_step_id,omitempty"`
|
|
QueuedAt *string `json:"queued_at,omitempty"`
|
|
ProjectID string `json:"project_id,omitempty"`
|
|
ExternalID string `json:"external_id,omitempty"`
|
|
}
|
|
|
|
func webAppTaskFromSDK(task pluginsdk.Task) webAppTask {
|
|
result := webAppTask{
|
|
ID: task.ID,
|
|
WorkspaceID: task.WorkspaceID,
|
|
WorkflowID: task.WorkflowID,
|
|
Title: task.Title,
|
|
Description: task.Description,
|
|
State: task.State,
|
|
Priority: task.Priority,
|
|
CreatedBy: task.CreatedBy,
|
|
CreatedAt: task.CreatedAt,
|
|
UpdatedAt: task.UpdatedAt,
|
|
StartedAt: task.StartedAt,
|
|
CompletedAt: task.CompletedAt,
|
|
ParentID: task.ParentID,
|
|
Identifier: task.Identifier,
|
|
IsEphemeral: task.IsEphemeral,
|
|
Metadata: task.Metadata,
|
|
ArchivedAt: task.ArchivedAt,
|
|
WorkflowStepID: task.WorkflowStepID,
|
|
Position: task.Position,
|
|
AssigneeAgentProfileID: task.AssigneeAgentProfileID,
|
|
Labels: task.Labels, //nolint:staticcheck // retain API v1 label compatibility
|
|
Autopilot: task.Autopilot,
|
|
WIPAdmitted: task.WIPAdmitted,
|
|
QueuedForStepID: task.QueuedForStepID,
|
|
QueuedAt: task.QueuedAt,
|
|
ProjectID: task.ProjectID,
|
|
ExternalID: task.ExternalID,
|
|
}
|
|
if len(task.Repositories) > 0 {
|
|
result.Repositories = make([]webAppTaskRepository, len(task.Repositories))
|
|
for i, repository := range task.Repositories {
|
|
result.Repositories[i] = webAppTaskRepository{
|
|
ID: repository.ID, RepositoryID: repository.RepositoryID,
|
|
BaseBranch: repository.BaseBranch, Position: repository.Position,
|
|
CheckoutBranch: repository.CheckoutBranch,
|
|
}
|
|
}
|
|
}
|
|
if len(task.PullRequests) > 0 {
|
|
result.PullRequests = make([]webAppPullRequest, len(task.PullRequests))
|
|
for i, pullRequest := range task.PullRequests {
|
|
result.PullRequests[i] = webAppPullRequest{
|
|
Number: pullRequest.Number, URL: pullRequest.URL, Title: pullRequest.Title,
|
|
State: pullRequest.State, HeadBranch: pullRequest.HeadBranch,
|
|
BaseBranch: pullRequest.BaseBranch, IsDraft: pullRequest.IsDraft,
|
|
Provider: pullRequest.Provider, MergedAt: pullRequest.MergedAt,
|
|
ClosedAt: pullRequest.ClosedAt, ReviewState: pullRequest.ReviewState,
|
|
ChecksState: pullRequest.ChecksState, MergeableState: pullRequest.MergeableState,
|
|
UnresolvedReviewThreads: pullRequest.UnresolvedReviewThreads,
|
|
ChecksTotal: pullRequest.ChecksTotal, ChecksPassing: pullRequest.ChecksPassing,
|
|
Additions: pullRequest.Additions, Deletions: pullRequest.Deletions,
|
|
AuthorLogin: pullRequest.AuthorLogin,
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
type webAppWorkflow struct {
|
|
ID string `json:"id"`
|
|
WorkspaceID string `json:"workspace_id"`
|
|
Name string `json:"name"`
|
|
Description *string `json:"description,omitempty"`
|
|
SortOrder int32 `json:"sort_order"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
func webAppWorkflowFromSDK(workflow pluginsdk.Workflow) webAppWorkflow {
|
|
return webAppWorkflow{
|
|
ID: workflow.ID, WorkspaceID: workflow.WorkspaceID, Name: workflow.Name,
|
|
Description: workflow.Description, SortOrder: workflow.SortOrder,
|
|
CreatedAt: workflow.CreatedAt, UpdatedAt: workflow.UpdatedAt,
|
|
}
|
|
}
|
|
|
|
type webAppWorkflowStep struct {
|
|
ID string `json:"id"`
|
|
WorkflowID string `json:"workflow_id"`
|
|
Name string `json:"name"`
|
|
Position int32 `json:"position"`
|
|
StageType string `json:"stage_type"`
|
|
Color string `json:"color"`
|
|
IsStartStep bool `json:"is_start_step"`
|
|
WIPLimit int32 `json:"wip_limit"`
|
|
AgentProfileID string `json:"agent_profile_id"`
|
|
OnEnterActionTypes []string `json:"on_enter_action_types,omitempty"`
|
|
}
|
|
|
|
func webAppWorkflowStepFromSDK(step pluginsdk.WorkflowStep) webAppWorkflowStep {
|
|
return webAppWorkflowStep{
|
|
ID: step.ID, WorkflowID: step.WorkflowID, Name: step.Name,
|
|
Position: step.Position, StageType: step.StageType, Color: step.Color,
|
|
IsStartStep: step.IsStartStep, WIPLimit: step.WIPLimit,
|
|
AgentProfileID: step.AgentProfileID, OnEnterActionTypes: step.OnEnterActionTypes,
|
|
}
|
|
}
|