Skip to content
This repository was archived by the owner on Jul 7, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions gqlgen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ models:
AlertID:
model:
- github.com/m-mizutani/alertchain/pkg/domain/types.AlertID
ActionID:
model:
- github.com/m-mizutani/alertchain/pkg/domain/types.ActionID
Timestamp:
model:
- github.com/99designs/gqlgen/graphql.Time
Expand Down
4 changes: 3 additions & 1 deletion graphql/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
scalar Timestamp # Represents time.Time
scalar WorkflowID # Represents uuid.UUID
scalar AlertID # Represents uuid.UUID
scalar ActionID # Represents uuid.UUID
type WorkflowRecord {
id: WorkflowID!
createdAt: Timestamp!
Expand Down Expand Up @@ -41,7 +42,8 @@ type ReferenceRecord {
}

type ActionRecord {
id: String!
id: ActionID!
workflow_id: WorkflowID!
seq: Int!
uses: String!
args: [ArgumentRecord!]!
Expand Down
85 changes: 81 additions & 4 deletions pkg/controller/graphql/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions pkg/domain/interfaces/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,16 @@ type TxProc func(ctx *model.Context, input model.Attributes) (model.Attributes,
type Database interface {
GetAttrs(ctx *model.Context, ns types.Namespace) (model.Attributes, error)
PutAttrs(ctx *model.Context, ns types.Namespace, attrs model.Attributes) error

PutWorkflow(ctx *model.Context, workflow model.WorkflowRecord) error
GetWorkflows(ctx *model.Context, offset, limit int) ([]model.WorkflowRecord, error)
GetWorkflow(ctx *model.Context, id types.WorkflowID) (*model.WorkflowRecord, error)

PutAction(ctx *model.Context, action model.ActionRecord) error
GetAction(ctx *model.Context, id types.ActionID) (*model.ActionRecord, error)
GetActions(ctx *model.Context, ids []types.ActionID) ([]model.ActionRecord, error)
GetActionByWorkflowID(ctx *model.Context, workflowID types.WorkflowID) ([]model.ActionRecord, error)

Lock(ctx *model.Context, ns types.Namespace, timeout time.Time) error
Unlock(ctx *model.Context, ns types.Namespace) error
Close() error
Expand Down
3 changes: 2 additions & 1 deletion pkg/domain/model/graphql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/domain/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ func NewWorkflowID() WorkflowID {

func (x AlertID) String() string { return string(x) }
func (x WorkflowID) String() string { return string(x) }
func (x ActionID) String() string { return string(x) }
117 changes: 114 additions & 3 deletions pkg/infra/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ func TestMemory(t *testing.T) {
func TestFirestore(t *testing.T) {
var (
projectID string
collection string
databaseID string
)

if err := utils.LoadEnv(
utils.EnvDef("TEST_FIRESTORE_PROJECT_ID", &projectID),
utils.EnvDef("TEST_FIRESTORE_COLLECTION_PREFIX", &collection),
utils.EnvDef("TEST_FIRESTORE_DATABASE_ID", &databaseID),
); err != nil {
t.Skipf("Skip test due to missing env: %v", err)
}

ctx := model.NewContext()
client := gt.R1(firestore.New(ctx, projectID, collection)).NoError(t)
client := gt.R1(firestore.New(ctx, projectID, databaseID)).NoError(t)

testClient(t, client)
}
Expand All @@ -52,6 +52,9 @@ func testClient(t *testing.T, client interfaces.Database) {
t.Run("Workflow", func(t *testing.T) {
testWorkflow(t, client)
})
t.Run("Action", func(t *testing.T) {
testAction(t, client)
})
}

func testPutGet(t *testing.T, client interfaces.Database) {
Expand Down Expand Up @@ -245,3 +248,111 @@ func testWorkflow(t *testing.T, client interfaces.Database) {
gt.V(t, resp.Alert.ID).Equal(workflows[2].Alert.ID)
})
}

func testAction(t *testing.T, db interfaces.Database) {
ctx := model.NewContext()
workflow1 := model.WorkflowRecord{
ID: types.NewWorkflowID(),
CreatedAt: time.Now(),
}
workflow2 := model.WorkflowRecord{
ID: types.NewWorkflowID(),
CreatedAt: time.Now(),
}

gt.NoError(t, db.PutWorkflow(ctx, workflow1))

actions := []model.ActionRecord{
{
ID: types.NewActionID(),
WorkflowID: workflow1.ID,
Seq: 0,
Uses: "test1",
Args: []*model.ArgumentRecord{
{
Key: "key1",
Value: "value1",
},
},
},
{
ID: types.NewActionID(),
WorkflowID: workflow1.ID,
Seq: 1,
Uses: "test2",
Args: []*model.ArgumentRecord{
{
Key: "key2",
Value: "value2",
},
},
},
{
ID: types.NewActionID(),
WorkflowID: workflow1.ID,
Seq: 2,
Uses: "test3",
Args: []*model.ArgumentRecord{},
Next: []*model.NextRecord{},
StartedAt: time.Now(),
FinishedAt: time.Now(),
},
{
ID: types.NewActionID(),
WorkflowID: workflow2.ID,
Seq: 0,
Uses: "test4",
Args: []*model.ArgumentRecord{},
Next: []*model.NextRecord{},
StartedAt: time.Now(),
FinishedAt: time.Now(),
},
}

for _, action := range actions {
gt.NoError(t, db.PutAction(ctx, action))
}

t.Run("GetAction", func(t *testing.T) {
resp := gt.R1(db.GetAction(ctx, actions[1].ID)).NoError(t)
gt.V(t, resp).Must().NotNil()
gt.V(t, resp.Uses).Equal("test2")
})

t.Run("GetActionByWorkflowID", func(t *testing.T) {
resp := gt.R1(db.GetActionByWorkflowID(ctx, types.WorkflowID(workflow1.ID))).NoError(t)
gt.A(t, resp).Length(3).
MatchThen(func(v model.ActionRecord) bool {
return v.ID == actions[0].ID
}, func(t testing.TB, v model.ActionRecord) {
gt.V(t, v.Uses).Equal("test1")
}).
MatchThen(func(v model.ActionRecord) bool {
return v.ID == actions[1].ID
}, func(t testing.TB, v model.ActionRecord) {
gt.V(t, v.Uses).Equal("test2")
}).
MatchThen(func(v model.ActionRecord) bool {
return v.ID == actions[2].ID
}, func(t testing.TB, v model.ActionRecord) {
gt.V(t, v.Uses).Equal("test3")
})
})

t.Run("GetActions", func(t *testing.T) {
resp := gt.R1(db.GetActions(ctx, []types.ActionID{actions[0].ID, actions[3].ID})).NoError(t)
gt.A(t, resp).Length(2).
MatchThen(func(v model.ActionRecord) bool {
return v.ID == actions[0].ID
}, func(t testing.TB, v model.ActionRecord) {
gt.V(t, v.Uses).Equal("test1")
gt.V(t, v.WorkflowID).Equal(workflow1.ID)
}).
MatchThen(func(v model.ActionRecord) bool {
return v.ID == actions[3].ID
}, func(t testing.TB, v model.ActionRecord) {
gt.V(t, v.Uses).Equal("test4")
gt.V(t, v.WorkflowID).Equal(workflow2.ID)
})
})
}
Loading