Skip to content

Commit

Permalink
Create and add deployment trace obj to datastore on event registering…
Browse files Browse the repository at this point in the history
… flow (#5622)

Signed-off-by: khanhtc1202 <[email protected]>
  • Loading branch information
khanhtc1202 authored Mar 5, 2025
1 parent b72972d commit b7ec95d
Show file tree
Hide file tree
Showing 17 changed files with 605 additions and 305 deletions.
58 changes: 44 additions & 14 deletions pkg/app/server/grpcapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ type apiEventStore interface {
Add(ctx context.Context, event model.Event) error
}

type apiDeploymentTraceStore interface {
Add(ctx context.Context, trace model.DeploymentTrace) error
}

type commandOutputGetter interface {
Get(ctx context.Context, commandID string) ([]byte, error)
}
Expand All @@ -76,13 +80,14 @@ type commandOutputGetter interface {
type API struct {
apiservice.UnimplementedAPIServiceServer

applicationStore apiApplicationStore
deploymentStore apiDeploymentStore
pipedStore apiPipedStore
eventStore apiEventStore
commandStore commandstore.Store
stageLogStore stagelogstore.Store
commandOutputGetter commandOutputGetter
applicationStore apiApplicationStore
deploymentStore apiDeploymentStore
pipedStore apiPipedStore
eventStore apiEventStore
deploymentTraceStore apiDeploymentTraceStore
commandStore commandstore.Store
stageLogStore stagelogstore.Store
commandOutputGetter commandOutputGetter

encryptionKeyCache cache.Cache
pipedStatCache cache.Cache
Expand All @@ -104,13 +109,14 @@ func NewAPI(
) *API {
w := datastore.PipectlCommander
a := &API{
applicationStore: datastore.NewApplicationStore(ds, w),
deploymentStore: datastore.NewDeploymentStore(ds, w),
pipedStore: datastore.NewPipedStore(ds, w),
eventStore: datastore.NewEventStore(ds, w),
commandStore: commandstore.NewStore(w, ds, sc, logger),
stageLogStore: stagelogstore.NewStore(fs, sc, logger),
commandOutputGetter: cog,
applicationStore: datastore.NewApplicationStore(ds, w),
deploymentStore: datastore.NewDeploymentStore(ds, w),
pipedStore: datastore.NewPipedStore(ds, w),
eventStore: datastore.NewEventStore(ds, w),
deploymentTraceStore: datastore.NewDeploymentTraceStore(ds, w),
commandStore: commandstore.NewStore(w, ds, sc, logger),
stageLogStore: stagelogstore.NewStore(fs, sc, logger),
commandOutputGetter: cog,
// Public key is variable but likely to be accessed multiple times in a short period.
encryptionKeyCache: memorycache.NewTTLCache(ctx, 5*time.Minute, 5*time.Minute),
pipedStatCache: psc,
Expand Down Expand Up @@ -815,6 +821,7 @@ func (a *API) RegisterEvent(ctx context.Context, req *apiservice.RegisterEventRe
Data: req.Data,
Labels: req.Labels,
Contexts: req.Contexts,
TriggerCommitHash: req.CommitHash,
EventKey: model.MakeEventKey(req.Name, req.Labels),
ProjectId: key.ProjectId,
Status: model.EventStatus_EVENT_NOT_HANDLED,
Expand All @@ -824,6 +831,29 @@ func (a *API) RegisterEvent(ctx context.Context, req *apiservice.RegisterEventRe
return nil, gRPCStoreError(err, fmt.Sprintf("add event %s", id))
}

// Create DeploymentTrace object and store to datastore
// if users send information of the commit that trigger this event.
if req.CommitHash != "" && req.CommitUrl != "" {
trace := model.DeploymentTrace{
Id: uuid.New().String(),
Title: req.CommitTitle,
Author: req.CommitAuthor,
CommitMessage: req.CommitMessage,
CommitHash: req.CommitHash,
CommitUrl: req.CommitUrl,
CommitTimestamp: time.Now().Unix(), // Use event sent time as default for commit timestamp.
}

if req.CommitTimestamp != 0 {
trace.CommitTimestamp = req.CommitTimestamp
}

err = a.deploymentTraceStore.Add(ctx, trace)
if err != nil {
a.logger.Error("failed to store deployment trace", zap.String("commit_hash", req.CommitHash), zap.Error(err))
}
}

return &apiservice.RegisterEventResponse{EventId: id}, nil
}

Expand Down
553 changes: 308 additions & 245 deletions pkg/app/server/service/apiservice/service.pb.go

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions pkg/app/server/service/apiservice/service.pb.validate.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/app/server/service/apiservice/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ message RegisterEventRequest {
string data = 2 [(validate.rules).string.min_len = 1];
map<string,string> labels = 3 [(validate.rules).map.keys.string.min_len = 1, (validate.rules).map.values.string.min_len = 1];
map<string,string> contexts = 4 [(validate.rules).map.keys.string.min_len = 1, (validate.rules).map.keys.string.pattern = "^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$", (validate.rules).map.values.string.min_len = 1];
// Information of the commit that trigger this event.
string commit_hash = 5;
string commit_url = 6;
string commit_title = 7;
string commit_message = 8;
string commit_author = 9;
int64 commit_timestamp = 10;
}

message RegisterEventResponse {
Expand Down
105 changes: 105 additions & 0 deletions pkg/datastore/deploymenttracestore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2025 The PipeCD Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package datastore

import (
"context"
"encoding/json"
"fmt"
"time"

"github.com/pipe-cd/pipecd/pkg/model"
)

type deploymentTraceCollection struct {
requestedBy Commander
}

func (d *deploymentTraceCollection) Kind() string {
return "DeploymentTrace"
}

func (d *deploymentTraceCollection) Factory() Factory {
return func() interface{} {
return &model.DeploymentTrace{}
}
}

func (d *deploymentTraceCollection) ListInUsedShards() []Shard {
return []Shard{
AgentShard,
}
}

func (d *deploymentTraceCollection) GetUpdatableShard() (Shard, error) {
switch d.requestedBy {
case PipedCommander:
return AgentShard, nil
default:
return "", ErrUnsupported
}
}

func (d *deploymentTraceCollection) Encode(entity interface{}) (map[Shard][]byte, error) {
const errFmt = "failed while encode Deployment Trace object: %s"

me, ok := entity.(*model.DeploymentTrace)
if !ok {
return nil, fmt.Errorf(errFmt, "type not matched")
}

data, err := json.Marshal(me)
if err != nil {
return nil, fmt.Errorf(errFmt, "unable to marshal entity data")
}
return map[Shard][]byte{
AgentShard: data,
}, nil
}

type DeploymentTraceStore interface {
Add(ctx context.Context, d model.DeploymentTrace) error
}

type deploymentTraceStore struct {
backend
commander Commander
nowFunc func() time.Time
}

func NewDeploymentTraceStore(ds DataStore, c Commander) DeploymentTraceStore {
return &deploymentTraceStore{
backend: backend{
ds: ds,
col: &deploymentTraceCollection{requestedBy: c},
},
commander: c,
nowFunc: time.Now,
}
}

func (s *deploymentTraceStore) Add(ctx context.Context, d model.DeploymentTrace) error {
now := s.nowFunc().Unix()
if d.CreatedAt == 0 {
d.CreatedAt = now
}
if d.UpdatedAt == 0 {
d.UpdatedAt = now
}
if err := d.Validate(); err != nil {
return fmt.Errorf("failed to validate deployment trace: %w: %w", ErrInvalidArgument, err)
}
return s.ds.Create(ctx, s.col, d.Id, &d)
}
13 changes: 13 additions & 0 deletions pkg/datastore/mysql/ensurer/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,16 @@ CREATE TABLE IF NOT EXISTS DeploymentChain (
CreatedAt INT(11) GENERATED ALWAYS AS (data->>"$.created_at") STORED NOT NULL,
UpdatedAt INT(11) GENERATED ALWAYS AS (data->>"$.updated_at") STORED NOT NULL
) ENGINE=InnoDB;

--
-- DeploymentTrace table
--

CREATE TABLE IF NOT EXISTS DeploymentTrace (
Id BINARY(16) PRIMARY KEY,
Data JSON NOT NULL,
ProjectId VARCHAR(50) GENERATED ALWAYS AS (data->>"$.project_id") STORED NOT NULL,
Extra VARCHAR(100) GENERATED ALWAYS AS (data->>"$._extra") STORED,
CreatedAt INT(11) GENERATED ALWAYS AS (data->>"$.created_at") STORED NOT NULL,
UpdatedAt INT(11) GENERATED ALWAYS AS (data->>"$.updated_at") STORED NOT NULL
) ENGINE=InnoDB;
19 changes: 19 additions & 0 deletions pkg/model/deployment_trace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2025 The PipeCD Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package model

func (d *DeploymentTrace) SetUpdatedAt(t int64) {
d.UpdatedAt = t
}
34 changes: 17 additions & 17 deletions pkg/model/deployment_trace.pb.go

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

4 changes: 2 additions & 2 deletions pkg/model/deployment_trace.pb.validate.go

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

6 changes: 3 additions & 3 deletions pkg/model/deployment_trace.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import "validate/validate.proto";
message DeploymentTrace {
string id = 1 [(validate.rules).string.min_len = 1];
string title = 2;
string commit_hash = 3 [(validate.rules).string.min_len = 1];
string commit_url = 4 [(validate.rules).string.min_len = 1];
string commit_message = 5;
string commit_message = 3;
string commit_hash = 4 [(validate.rules).string.min_len = 1];
string commit_url = 5 [(validate.rules).string.min_len = 1];
int64 commit_timestamp = 6 [(validate.rules).int64.gte = 0];
string author = 7;

Expand Down
Loading

0 comments on commit b7ec95d

Please sign in to comment.