diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..6b1b3b6 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,48 @@ +name: GoTest and Build Docker Image Test + +on: + push: + branches: + - '**' + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: 1.23 + + - name: Cache Go modules + uses: actions/cache@v3 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Install dependencies + run: go mod tidy + + - name: Run unit tests + run: go test ./... -v + + docker-image-build: + runs-on: ubuntu-latest + needs: test + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Build Docker image + run: | + docker build -t server-controller:latest . + docker images server-controller:latest --format "Image Size: {{.Size}}" \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..92fed9e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM golang:1.23.0-alpine3.20 as builder +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download + +COPY ./ ./ +RUN CGO_ENABLED=0 GOOS=linux go build -o /main ./main.go + +FROM alpine:3.20 +WORKDIR /app + +COPY --from=builder /main ./main \ No newline at end of file diff --git a/app/grpc/grpc.go b/app/grpc/grpc.go index 0607002..36bfa66 100644 --- a/app/grpc/grpc.go +++ b/app/grpc/grpc.go @@ -12,6 +12,7 @@ import ( "github.com/ideagate/server-controller/domain/entrypoint" projectrepositorysql "github.com/ideagate/server-controller/domain/project/repository/sql" projectusecase "github.com/ideagate/server-controller/domain/project/usecase" + "github.com/ideagate/server-controller/domain/workflow" "github.com/ideagate/server-controller/infrastructure" "github.com/improbable-eng/grpc-web/go/grpcweb" "github.com/urfave/cli/v2" @@ -101,6 +102,7 @@ type DashboardServiceServer struct { usecaseProject projectusecase.ProjectUsecase usecaseApplication appusecase.ApplicationUsecase domainEntrypoint entrypoint.Domain + domainWorkflow workflow.Domain } func NewDashboardServiceServer(infra *infrastructure.Infrastructure) *DashboardServiceServer { @@ -114,6 +116,7 @@ func NewDashboardServiceServer(infra *infrastructure.Infrastructure) *DashboardS return &DashboardServiceServer{ domainEntrypoint: entrypoint.New(infra.Postgres), + domainWorkflow: workflow.New(infra.Postgres), // TODO: change using domain initialization like entrypoint usecaseProject: usecaseProject, diff --git a/app/grpc/workflow.go b/app/grpc/workflow.go new file mode 100644 index 0000000..231819f --- /dev/null +++ b/app/grpc/workflow.go @@ -0,0 +1,118 @@ +package grpc + +import ( + "context" + + "github.com/ideagate/core/utils" + "github.com/ideagate/core/utils/errors" + pbendpoint "github.com/ideagate/model/gen-go/core/endpoint" + "github.com/ideagate/model/gen-go/dashboard" + "github.com/ideagate/server-controller/domain/workflow/usecase" +) + +func (s *DashboardServiceServer) GetWorkflows(ctx context.Context, req *dashboard.GetWorkflowsRequest) (*dashboard.GetWorkflowsResponse, error) { + // Request validation + if req.GetProjectId() == "" || req.GetApplicationId() == "" || req.GetEntrypointId() == "" { + return nil, errors.New("project_id, application_id, entrypoint_id are required") + } + + // Check if getting a specific workflow + if req.GetVersion() != 0 { + resultWorkflow, err := s.domainWorkflow.GetWorkflow(ctx, &usecase.GetWorkflowRequest{ + ProjectID: req.GetProjectId(), + ApplicationID: req.GetApplicationId(), + EntrypointID: req.GetEntrypointId(), + Version: req.GetVersion(), + }) + if err != nil { + return nil, err + } + + return &dashboard.GetWorkflowsResponse{ + Workflows: []*pbendpoint.Workflow{resultWorkflow.Workflow}, + }, nil + } + + // Get list of workflows + requestWorkflows := &usecase.GetWorkflowsRequest{ + ProjectID: req.GetProjectId(), + ApplicationID: req.GetApplicationId(), + EntrypointID: req.GetEntrypointId(), + } + + resultWorkflows, err := s.domainWorkflow.GetWorkflows(ctx, requestWorkflows) + if err != nil { + return nil, err + } + + return &dashboard.GetWorkflowsResponse{ + Workflows: resultWorkflows.Workflows, + }, nil +} + +func (s *DashboardServiceServer) CreateWorkflow(ctx context.Context, req *dashboard.CreateWorkflowRequest) (*dashboard.CreateWorkflowResponse, error) { + // Request validation + if req.GetProjectId() == "" || req.GetApplicationId() == "" || req.GetEntrypointId() == "" { + return nil, errors.New("project_id, application_id, entrypoint_id are required") + } + + // Create workflow + requestCreate := &usecase.CreateWorkflowRequest{ + ProjectID: req.GetProjectId(), + ApplicationID: req.GetApplicationId(), + EntrypointID: req.GetEntrypointId(), + } + + if req.GetFromVersion() != 0 { + requestCreate.FromVersion = utils.ToPtr(req.GetFromVersion()) + } + + responseCreate, err := s.domainWorkflow.CreateWorkflow(ctx, requestCreate) + if err != nil { + return nil, err + } + + return &dashboard.CreateWorkflowResponse{ + Version: responseCreate.Version, + }, nil +} + +func (s *DashboardServiceServer) UpdateWorkflow(ctx context.Context, req *dashboard.UpdateWorkflowRequest) (*dashboard.UpdateWorkflowResponse, error) { + // Request validation + workflow := req.GetWorkflow() + if workflow.GetProjectId() == "" || workflow.GetApplicationId() == "" || workflow.GetEntrypointId() == "" { + return nil, errors.New("project_id, application_id, entrypoint_id are required") + } + + // Update workflow + requestUpdate := &usecase.UpdateWorkflowRequest{ + Workflow: workflow, + } + + if _, err := s.domainWorkflow.UpdateWorkflow(ctx, requestUpdate); err != nil { + return nil, err + } + + return &dashboard.UpdateWorkflowResponse{}, nil +} + +func (s *DashboardServiceServer) DeleteWorkflow(ctx context.Context, req *dashboard.DeleteWorkflowRequest) (*dashboard.DeleteWorkflowResponse, error) { + // Request validation + if req.GetProjectId() == "" || req.GetApplicationId() == "" || req.GetEntrypointId() == "" || req.GetVersion() == 0 { + return nil, errors.New("project_id, application_id, entrypoint_id and version are required") + } + + // Delete workflow + requestDelete := &usecase.DeleteWorkflowRequest{ + ProjectID: req.GetProjectId(), + ApplicationID: req.GetApplicationId(), + EntrypointID: req.GetEntrypointId(), + Version: req.GetVersion(), + } + + if err := s.domainWorkflow.DeleteWorkflow(ctx, requestDelete); err != nil { + return nil, err + } + + return &dashboard.DeleteWorkflowResponse{}, nil +} diff --git a/domain/application/model/application.go b/domain/application/model/application.go index e7e715f..65e987b 100644 --- a/domain/application/model/application.go +++ b/domain/application/model/application.go @@ -60,17 +60,3 @@ type Endpoint struct { func (e *Endpoint) TableName() string { return "endpoint" } - -type Workflow struct { - Version int - EndpointID string - ApplicationID string - ProjectID string - CreatedAt time.Time - UpdatedAt time.Time - Data pgtype.JSONB `gorm:"type:jsonb"` -} - -func (w *Workflow) TableName() string { - return "workflow" -} diff --git a/domain/entrypoint/model/error.go b/domain/entrypoint/model/error.go deleted file mode 100644 index 24b404a..0000000 --- a/domain/entrypoint/model/error.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -import "github.com/ideagate/core/utils/errors" - -var ( - ErrProjectIDRequired = errors.New("project_id is required") - ErrApplicationIDRequired = errors.New("application_id is required") - ErrEntrypointIDRequired = errors.New("entrypoint_id is required") - ErrEntrypointNotFound = errors.New("entrypoint not found") -) diff --git a/domain/entrypoint/usecase/usecase.go b/domain/entrypoint/usecase/usecase.go index a2cc1ba..3fd6951 100644 --- a/domain/entrypoint/usecase/usecase.go +++ b/domain/entrypoint/usecase/usecase.go @@ -4,9 +4,10 @@ import ( "context" "github.com/ideagate/core/utils" - pbEndpoint "github.com/ideagate/model/gen-go/core/endpoint" - "github.com/ideagate/server-controller/domain/entrypoint/model" + pbendpoint "github.com/ideagate/model/gen-go/core/endpoint" + modelentrypoint "github.com/ideagate/server-controller/domain/entrypoint/model" "github.com/ideagate/server-controller/domain/entrypoint/repository/sql" + "github.com/ideagate/server-controller/model" ) func New(repoSql sql.Repository) *Usecase { @@ -31,14 +32,14 @@ func (u *Usecase) GetListEntrypoint(ctx context.Context, req *GetListEntrypointR resultRepo, err := u.repoSql.GetListEntrypoint(ctx, &sql.GetListEntrypointRequest{ ProjectID: req.ProjectID, ApplicationID: req.ApplicationID, - Type: utils.ToPtr(model.EntryPointRest.String()), + Type: utils.ToPtr(modelentrypoint.EntryPointRest.String()), }) if err != nil { return nil, err } result := &GetListEntrypointResponse{ - Entrypoints: make([]*pbEndpoint.Endpoint, len(resultRepo)), + Entrypoints: make([]*pbendpoint.Endpoint, len(resultRepo)), } for i := 0; i < len(resultRepo); i++ { @@ -94,7 +95,7 @@ func (u *Usecase) CreateEntrypoint(ctx context.Context, req *CreateEntrypointReq } // Create entrypoint - var entrypointData model.Entrypoint + var entrypointData modelentrypoint.Entrypoint entrypointData.FromProto(req.Entrypoint) if err := u.repoSql.CreateEntrypoint(ctx, &sql.CreateEntrypointRequest{ diff --git a/domain/workflow/model/workflow.go b/domain/workflow/model/workflow.go new file mode 100644 index 0000000..786051e --- /dev/null +++ b/domain/workflow/model/workflow.go @@ -0,0 +1,68 @@ +package model + +import ( + "time" + + pbendpoint "github.com/ideagate/model/gen-go/core/endpoint" + "google.golang.org/protobuf/types/known/timestamppb" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +type Workflow struct { + Version int64 `json:"version"` + EntrypointID string `json:"entrypoint_id"` + ApplicationID string `json:"application_id"` + ProjectID string `json:"project_id"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Data datatypes.JSONType[WorkflowData] `json:"data"` +} + +type WorkflowData struct { + Steps []*pbendpoint.Step `json:"steps"` + Edges []*pbendpoint.Edge `json:"edges"` +} + +func (w *Workflow) TableName() string { + return "workflow" +} + +func (w *Workflow) BeforeCreate(_ *gorm.DB) error { + w.CreatedAt = time.Now() + w.UpdatedAt = time.Now() + return nil +} + +func (w *Workflow) BeforeUpdate(_ *gorm.DB) error { + w.UpdatedAt = time.Now() + return nil +} + +func (w *Workflow) ToProto() *pbendpoint.Workflow { + data := w.Data.Data() + + return &pbendpoint.Workflow{ + Version: w.Version, + EntrypointId: w.EntrypointID, + ApplicationId: w.ApplicationID, + ProjectId: w.ProjectID, + CreatedAt: timestamppb.New(w.CreatedAt), + UpdatedAt: timestamppb.New(w.UpdatedAt), + Steps: data.Steps, + Edges: data.Edges, + } +} + +func (w *Workflow) FromProto(workflow *pbendpoint.Workflow) { + w.Version = workflow.Version + w.EntrypointID = workflow.EntrypointId + w.ApplicationID = workflow.ApplicationId + w.ProjectID = workflow.ProjectId + w.CreatedAt = workflow.CreatedAt.AsTime() + w.UpdatedAt = workflow.UpdatedAt.AsTime() + w.Data = datatypes.NewJSONType(WorkflowData{ + Steps: workflow.Steps, + Edges: workflow.Edges, + }) +} diff --git a/domain/workflow/repository/sql/functions.go b/domain/workflow/repository/sql/functions.go new file mode 100644 index 0000000..bcb114e --- /dev/null +++ b/domain/workflow/repository/sql/functions.go @@ -0,0 +1,90 @@ +package sql + +import ( + "context" + + modelworkflow "github.com/ideagate/server-controller/domain/workflow/model" + "gorm.io/gorm" +) + +func New(db *gorm.DB) Repository { + return &repository{ + db: db, + } +} + +type repository struct { + db *gorm.DB +} + +func (r *repository) GetListWorkflow(ctx context.Context, req *GetListWorkflowRequest) ([]*modelworkflow.Workflow, error) { + session := r.db.WithContext(ctx). + Where("project_id = ?", req.ProjectID). + Where("application_id = ?", req.ApplicationID). + Where("entrypoint_id = ?", req.EntrypointID). + Order("version desc") + + if req.Limit != nil { + session = session.Limit(*req.Limit) + } + + var workflows []*modelworkflow.Workflow + if err := session.Find(&workflows).Error; err != nil { + return nil, err + } + + return workflows, nil +} + +func (r *repository) GetWorkflow(ctx context.Context, req *GetWorkflowRequest) (*modelworkflow.Workflow, error) { + session := r.db.WithContext(ctx). + Where("project_id = ?", req.ProjectID). + Where("application_id = ?", req.ApplicationID). + Where("entrypoint_id = ?", req.EntrypointID). + Where("version = ?", req.Version) + + var workflow modelworkflow.Workflow + if err := session.Take(&workflow).Error; err != nil { + return nil, err + } + + return &workflow, nil +} + +func (r *repository) CreateWorkflow(ctx context.Context, req *CreateWorkflowRequest) error { + session := r.db.WithContext(ctx) + + if err := session.Create(req.Workflow).Error; err != nil { + return err + } + + return nil +} + +func (r *repository) UpdateWorkflow(ctx context.Context, req *UpdateWorkflowRequest) error { + session := r.db.WithContext(ctx). + Where("project_id = ?", req.Workflow.ProjectID). + Where("application_id = ?", req.Workflow.ApplicationID). + Where("entrypoint_id = ?", req.Workflow.EntrypointID). + Where("version = ?", req.Workflow.Version) + + if err := session.Select("Data").Updates(req.Workflow).Error; err != nil { + return err + } + + return nil +} + +func (r *repository) DeleteWorkflow(ctx context.Context, req *DeleteWorkflowRequest) error { + session := r.db.WithContext(ctx). + Where("project_id = ?", req.ProjectID). + Where("application_id = ?", req.ApplicationID). + Where("entrypoint_id = ?", req.EntrypointID). + Where("version = ?", req.Version) + + if err := session.Delete(&modelworkflow.Workflow{}).Error; err != nil { + return err + } + + return nil +} diff --git a/domain/workflow/repository/sql/sql.go b/domain/workflow/repository/sql/sql.go new file mode 100644 index 0000000..76506df --- /dev/null +++ b/domain/workflow/repository/sql/sql.go @@ -0,0 +1,44 @@ +package sql + +import ( + "context" + + "github.com/ideagate/server-controller/domain/workflow/model" +) + +type Repository interface { + GetListWorkflow(ctx context.Context, req *GetListWorkflowRequest) ([]*model.Workflow, error) + GetWorkflow(ctx context.Context, req *GetWorkflowRequest) (*model.Workflow, error) + CreateWorkflow(ctx context.Context, req *CreateWorkflowRequest) error + UpdateWorkflow(ctx context.Context, req *UpdateWorkflowRequest) error + DeleteWorkflow(ctx context.Context, req *DeleteWorkflowRequest) error +} + +type GetListWorkflowRequest struct { + ProjectID string + ApplicationID string + EntrypointID string + Limit *int +} + +type GetWorkflowRequest struct { + ProjectID string + ApplicationID string + EntrypointID string + Version int64 +} + +type CreateWorkflowRequest struct { + Workflow *model.Workflow +} + +type UpdateWorkflowRequest struct { + Workflow *model.Workflow +} + +type DeleteWorkflowRequest struct { + ProjectID string + ApplicationID string + EntrypointID string + Version int64 +} diff --git a/domain/workflow/usecase/types.go b/domain/workflow/usecase/types.go new file mode 100644 index 0000000..4444c99 --- /dev/null +++ b/domain/workflow/usecase/types.go @@ -0,0 +1,51 @@ +package usecase + +import pbendpoint "github.com/ideagate/model/gen-go/core/endpoint" + +type GetWorkflowsRequest struct { + ProjectID string + ApplicationID string + EntrypointID string +} + +type GetWorkflowsResponse struct { + Workflows []*pbendpoint.Workflow +} + +type GetWorkflowRequest struct { + ProjectID string + ApplicationID string + EntrypointID string + Version int64 +} + +type GetWorkflowResponse struct { + Workflow *pbendpoint.Workflow +} + +type CreateWorkflowRequest struct { + ProjectID string + ApplicationID string + EntrypointID string + + // New workflow will be copied from this version. + // If not specified, then new workflow will be created from scratch. + FromVersion *int64 +} + +type CreateWorkflowResponse struct { + Version int64 +} + +type UpdateWorkflowRequest struct { + Workflow *pbendpoint.Workflow +} + +type UpdateWorkflowResponse struct{} + +type DeleteWorkflowRequest struct { + ProjectID string + ApplicationID string + EntrypointID string + Version int64 +} diff --git a/domain/workflow/usecase/usecase.go b/domain/workflow/usecase/usecase.go new file mode 100644 index 0000000..3dc10d2 --- /dev/null +++ b/domain/workflow/usecase/usecase.go @@ -0,0 +1,208 @@ +package usecase + +import ( + "context" + + "github.com/ideagate/core/utils" + pbendpoint "github.com/ideagate/model/gen-go/core/endpoint" + modelworkflow "github.com/ideagate/server-controller/domain/workflow/model" + "github.com/ideagate/server-controller/domain/workflow/repository/sql" + "github.com/ideagate/server-controller/model" +) + +func New(repoSql sql.Repository) *Usecase { + return &Usecase{ + repoSql: repoSql, + } +} + +type Usecase struct { + repoSql sql.Repository +} + +func (u *Usecase) GetWorkflows(ctx context.Context, req *GetWorkflowsRequest) (*GetWorkflowsResponse, error) { + if req.ProjectID == "" { + return nil, model.ErrProjectIDRequired + } + + if req.ApplicationID == "" { + return nil, model.ErrApplicationIDRequired + } + + if req.EntrypointID == "" { + return nil, model.ErrEntrypointIDRequired + } + + resultRepo, err := u.repoSql.GetListWorkflow(ctx, &sql.GetListWorkflowRequest{ + ProjectID: req.ProjectID, + ApplicationID: req.ApplicationID, + EntrypointID: req.EntrypointID, + }) + if err != nil { + return nil, err + } + + result := &GetWorkflowsResponse{ + Workflows: make([]*pbendpoint.Workflow, len(resultRepo)), + } + + for i := 0; i < len(resultRepo); i++ { + result.Workflows[i] = resultRepo[i].ToProto() + result.Workflows[i].Edges = nil + result.Workflows[i].Steps = nil + } + + return result, nil +} + +func (u *Usecase) GetWorkflow(ctx context.Context, req *GetWorkflowRequest) (*GetWorkflowResponse, error) { + if req.ProjectID == "" { + return nil, model.ErrProjectIDRequired + } + + if req.ApplicationID == "" { + return nil, model.ErrApplicationIDRequired + } + + if req.EntrypointID == "" { + return nil, model.ErrEntrypointIDRequired + } + + if req.Version == 0 { + return nil, model.ErrWorkflowVersionRequired + } + + resultRepo, err := u.repoSql.GetWorkflow(ctx, &sql.GetWorkflowRequest{ + ProjectID: req.ProjectID, + ApplicationID: req.ApplicationID, + EntrypointID: req.EntrypointID, + Version: req.Version, + }) + if err != nil { + return nil, err + } + + return &GetWorkflowResponse{ + Workflow: resultRepo.ToProto(), + }, nil +} + +func (u *Usecase) CreateWorkflow(ctx context.Context, req *CreateWorkflowRequest) (*CreateWorkflowResponse, error) { + if req.ProjectID == "" { + return nil, model.ErrProjectIDRequired + } + + if req.ApplicationID == "" { + return nil, model.ErrApplicationIDRequired + } + + if req.EntrypointID == "" { + return nil, model.ErrEntrypointIDRequired + } + + newWorkflow := &modelworkflow.Workflow{ + ProjectID: req.ProjectID, + ApplicationID: req.ApplicationID, + EntrypointID: req.EntrypointID, + Version: 1, + } + + // Copy workflow from existing version if specified + if req.FromVersion != nil { + resultRepo, err := u.repoSql.GetWorkflow(ctx, &sql.GetWorkflowRequest{ + ProjectID: req.ProjectID, + ApplicationID: req.ApplicationID, + EntrypointID: req.EntrypointID, + Version: *req.FromVersion, + }) + if err != nil { + return nil, err + } + newWorkflow = resultRepo + } + + // Determine the new version + resultRepoLast, err := u.repoSql.GetListWorkflow(ctx, &sql.GetListWorkflowRequest{ + ProjectID: req.ProjectID, + ApplicationID: req.ApplicationID, + EntrypointID: req.EntrypointID, + Limit: utils.ToPtr(1), + }) + if err != nil { + return nil, err + } + if len(resultRepoLast) > 0 { + newWorkflow.Version = resultRepoLast[0].Version + 1 + } + + // Create new version workflow + if err := u.repoSql.CreateWorkflow(ctx, &sql.CreateWorkflowRequest{ + Workflow: newWorkflow, + }); err != nil { + return nil, err + } + + return &CreateWorkflowResponse{ + Version: newWorkflow.Version, + }, nil +} + +func (u *Usecase) UpdateWorkflow(ctx context.Context, req *UpdateWorkflowRequest) (*UpdateWorkflowResponse, error) { + if req.Workflow.GetProjectId() == "" { + return nil, model.ErrProjectIDRequired + } + + if req.Workflow.GetApplicationId() == "" { + return nil, model.ErrApplicationIDRequired + } + + if req.Workflow.GetEntrypointId() == "" { + return nil, model.ErrEntrypointIDRequired + } + + if req.Workflow.Version == 0 { + return nil, model.ErrWorkflowVersionRequired + } + + newWorkflow := &modelworkflow.Workflow{} + newWorkflow.FromProto(req.Workflow) + + err := u.repoSql.UpdateWorkflow(ctx, &sql.UpdateWorkflowRequest{ + Workflow: newWorkflow, + }) + if err != nil { + return nil, err + } + + return &UpdateWorkflowResponse{}, nil +} + +func (u *Usecase) DeleteWorkflow(ctx context.Context, req *DeleteWorkflowRequest) error { + if req.ProjectID == "" { + return model.ErrProjectIDRequired + } + + if req.ApplicationID == "" { + return model.ErrApplicationIDRequired + } + + if req.EntrypointID == "" { + return model.ErrEntrypointIDRequired + } + + if req.Version == 0 { + return model.ErrWorkflowVersionRequired + } + + err := u.repoSql.DeleteWorkflow(ctx, &sql.DeleteWorkflowRequest{ + ProjectID: req.ProjectID, + ApplicationID: req.ApplicationID, + EntrypointID: req.EntrypointID, + Version: req.Version, + }) + if err != nil { + return err + } + + return nil +} diff --git a/domain/workflow/workflow.go b/domain/workflow/workflow.go new file mode 100644 index 0000000..dfa7ea6 --- /dev/null +++ b/domain/workflow/workflow.go @@ -0,0 +1,24 @@ +package workflow + +import ( + "context" + + "github.com/ideagate/server-controller/domain/workflow/repository/sql" + "github.com/ideagate/server-controller/domain/workflow/usecase" + "gorm.io/gorm" +) + +type Domain interface { + GetWorkflows(ctx context.Context, req *usecase.GetWorkflowsRequest) (*usecase.GetWorkflowsResponse, error) + GetWorkflow(ctx context.Context, req *usecase.GetWorkflowRequest) (*usecase.GetWorkflowResponse, error) + CreateWorkflow(ctx context.Context, req *usecase.CreateWorkflowRequest) (*usecase.CreateWorkflowResponse, error) + UpdateWorkflow(ctx context.Context, req *usecase.UpdateWorkflowRequest) (*usecase.UpdateWorkflowResponse, error) + DeleteWorkflow(ctx context.Context, req *usecase.DeleteWorkflowRequest) error +} + +var _ Domain = &usecase.Usecase{} + +func New(db *gorm.DB) Domain { + repoSql := sql.New(db) + return usecase.New(repoSql) +} diff --git a/go.mod b/go.mod index 8325fbe..c833055 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 require ( github.com/golang-migrate/migrate/v4 v4.18.1 github.com/ideagate/core v0.0.0-20250405234934-b97c52ec982f - github.com/ideagate/model/gen-go v0.0.0-20250412005306-2b119abd6dfe + github.com/ideagate/model/gen-go v0.0.12 github.com/improbable-eng/grpc-web v0.15.0 github.com/jackc/pgtype v1.14.0 github.com/urfave/cli/v2 v2.27.5 diff --git a/go.sum b/go.sum index f6fde6e..af47b4b 100644 --- a/go.sum +++ b/go.sum @@ -215,12 +215,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ideagate/core v0.0.0-20250405234934-b97c52ec982f h1:qBzD+diZCrmeMc1iFiAssLJtR4hFJ7BF1gKtwe0p0Q4= github.com/ideagate/core v0.0.0-20250405234934-b97c52ec982f/go.mod h1:BMtsNY436ios3Itf6naWavXmTt7RfTzt4HOAU2wymJY= -github.com/ideagate/model/gen-go v0.0.0-20250405233858-080667362b54 h1:J81wf34uvSlnvbd3PdyiLNf2Dn6FVGw1+H2FKcSuL/Q= -github.com/ideagate/model/gen-go v0.0.0-20250405233858-080667362b54/go.mod h1:yDi/2xwjTEV4IrYUk+M69hhvySZZqmHJ/Ec5n0bqB14= -github.com/ideagate/model/gen-go v0.0.0-20250411154742-e9842527aeea h1:ZziLsIBAseKvCsjcHSk4wNo+FacT2XOx7oV/eko6eis= -github.com/ideagate/model/gen-go v0.0.0-20250411154742-e9842527aeea/go.mod h1:yDi/2xwjTEV4IrYUk+M69hhvySZZqmHJ/Ec5n0bqB14= -github.com/ideagate/model/gen-go v0.0.0-20250412005306-2b119abd6dfe h1:tVOB3rE72P0KzUmFPpErZJzpTPQEi0/r7DYxR/wF0JI= -github.com/ideagate/model/gen-go v0.0.0-20250412005306-2b119abd6dfe/go.mod h1:yDi/2xwjTEV4IrYUk+M69hhvySZZqmHJ/Ec5n0bqB14= +github.com/ideagate/model/gen-go v0.0.12 h1:R7u18faUkUNqxfnAQNuvksfG8qWTI91FT5JbYznWUV0= +github.com/ideagate/model/gen-go v0.0.12/go.mod h1:yDi/2xwjTEV4IrYUk+M69hhvySZZqmHJ/Ec5n0bqB14= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= diff --git a/localdata/1_user.sql b/localdata/1_user.sql new file mode 100644 index 0000000..34b2492 --- /dev/null +++ b/localdata/1_user.sql @@ -0,0 +1,2 @@ +INSERT INTO "user" VALUES (1, NOW(), NOW(), 'Local User', 'local@user.com', '') +ON CONFLICT (id) DO NOTHING; diff --git a/localdata/2_project.sql b/localdata/2_project.sql new file mode 100644 index 0000000..1513dee --- /dev/null +++ b/localdata/2_project.sql @@ -0,0 +1,2 @@ +INSERT INTO project VALUES ('test-project', NOW(), NOW(), 'Test Project', 'Test Project Description') +ON CONFLICT (id) DO NOTHING; \ No newline at end of file diff --git a/localdata/3_application.sql b/localdata/3_application.sql new file mode 100644 index 0000000..99c47a4 --- /dev/null +++ b/localdata/3_application.sql @@ -0,0 +1,2 @@ +INSERT INTO application VALUES ('test-application', 'test-project', NOW(), NOW(), 'Test Application', 'Test Application Description') +ON CONFLICT (id, project_id) DO NOTHING; \ No newline at end of file diff --git a/model/error.go b/model/error.go new file mode 100644 index 0000000..e31c445 --- /dev/null +++ b/model/error.go @@ -0,0 +1,11 @@ +package model + +import "github.com/ideagate/core/utils/errors" + +var ( + ErrProjectIDRequired = errors.New("project_id is required") + ErrApplicationIDRequired = errors.New("application_id is required") + ErrEntrypointIDRequired = errors.New("entrypoint_id is required") + ErrEntrypointNotFound = errors.New("entrypoint not found") + ErrWorkflowVersionRequired = errors.New("workflow version is required") +)