Skip to content

Commit e6f9f07

Browse files
authored
feat(contract): detect unchanged status in apply (#2821)
Signed-off-by: Sylwester Piskozub <sylwesterpiskozub@gmail.com>
1 parent 4479d73 commit e6f9f07

11 files changed

Lines changed: 88 additions & 29 deletions

‎app/cli/cmd/apply.go‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ Supports multi-document YAML files. Each document must have a 'kind' field.`,
3939
return err
4040
}
4141

42-
logger.Info().Msgf("%d contracts applied", len(results))
42+
for _, r := range results {
43+
status := "applied"
44+
if r.Unchanged {
45+
status = "unchanged"
46+
}
47+
logger.Info().Msgf("%s/%s %s", r.Kind, r.Name, status)
48+
}
4349

4450
return nil
4551
},

‎app/cli/cmd/workflow_contract_apply.go‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,16 @@ or update it if it already exists.`,
4848
desc = &description
4949
}
5050

51-
res, err := action.NewWorkflowContractApply(ActionOpts).Run(cmd.Context(), contractName, contractPath, desc, projectName)
51+
res, unchanged, err := action.NewWorkflowContractApply(ActionOpts).Run(cmd.Context(), contractName, contractPath, desc, projectName)
5252
if err != nil {
5353
return err
5454
}
5555

56-
logger.Info().Msg("Contract applied!")
56+
status := "applied"
57+
if unchanged {
58+
status = "unchanged"
59+
}
60+
logger.Info().Msgf("Contract/%s %s", contractName, status)
5761
return output.EncodeOutput(flagOutputFormat, res, contractItemTableOutput)
5862
},
5963
}

‎app/cli/pkg/action/apply.go‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ const (
3636

3737
// ApplyResult holds the outcome of a successfully applied resource document
3838
type ApplyResult struct {
39-
Kind string
40-
Name string
39+
Kind string
40+
Name string
41+
Unchanged bool
4142
}
4243

4344
// YAMLDoc holds a parsed YAML document with its kind and raw bytes
@@ -67,16 +68,16 @@ func (a *Apply) Run(ctx context.Context, path string) ([]*ApplyResult, error) {
6768
// Apply contracts
6869
var results []*ApplyResult
6970
for _, doc := range docs {
70-
result := &ApplyResult{Kind: doc.Kind, Name: doc.Name}
7171
switch doc.Kind {
7272
case KindContract:
73-
if err := ApplyContractFromRawData(ctx, a.cfg.CPConnection, doc.RawData); err != nil {
73+
unchanged, err := ApplyContractFromRawData(ctx, a.cfg.CPConnection, doc.RawData)
74+
if err != nil {
7475
return results, fmt.Errorf("%s/%s: %w", doc.Kind, doc.Name, err)
7576
}
77+
results = append(results, &ApplyResult{Kind: doc.Kind, Name: doc.Name, Unchanged: unchanged})
7678
default:
7779
return results, fmt.Errorf("unsupported kind %q", doc.Kind)
7880
}
79-
results = append(results, result)
8081
}
8182

8283
return results, nil
@@ -113,17 +114,17 @@ func ParseYAMLPath(path string) ([]*YAMLDoc, error) {
113114
}
114115

115116
// ApplyContractFromRawData applies a single contract document using the gRPC client.
116-
func ApplyContractFromRawData(ctx context.Context, conn *grpc.ClientConn, rawData []byte) error {
117+
func ApplyContractFromRawData(ctx context.Context, conn *grpc.ClientConn, rawData []byte) (bool, error) {
117118
client := pb.NewWorkflowContractServiceClient(conn)
118119

119-
_, err := client.Apply(ctx, &pb.WorkflowContractServiceApplyRequest{
120+
resp, err := client.Apply(ctx, &pb.WorkflowContractServiceApplyRequest{
120121
RawSchema: rawData,
121122
})
122123
if err != nil {
123-
return fmt.Errorf("failed to apply contract: %w", err)
124+
return false, fmt.Errorf("failed to apply contract: %w", err)
124125
}
125126

126-
return nil
127+
return resp.GetUnchanged(), nil
127128
}
128129

129130
// CollectYAMLFiles returns YAML file paths from the given path.

‎app/cli/pkg/action/workflow_contract_apply.go‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func NewWorkflowContractApply(cfg *ActionsOpts) *WorkflowContractApply {
3030
return &WorkflowContractApply{cfg}
3131
}
3232

33-
func (action *WorkflowContractApply) Run(ctx context.Context, contractName string, contractPath string, description *string, projectName string) (*WorkflowContractItem, error) {
33+
func (action *WorkflowContractApply) Run(ctx context.Context, contractName string, contractPath string, description *string, projectName string) (*WorkflowContractItem, bool, error) {
3434
client := pb.NewWorkflowContractServiceClient(action.cfg.CPConnection)
3535

3636
// Try to describe the specific contract first to determine if we should create or update
@@ -43,14 +43,16 @@ func (action *WorkflowContractApply) Run(ctx context.Context, contractName strin
4343
raw, err := LoadFileOrURL(contractPath)
4444
if err != nil {
4545
action.cfg.Logger.Debug().Err(err).Msg("loading the contract")
46-
return nil, err
46+
return nil, false, err
4747
}
4848
rawContract = raw
4949
}
5050

51-
_, err := client.Describe(ctx, describeReq)
51+
describeRes, err := client.Describe(ctx, describeReq)
5252
if err == nil {
5353
// Contract exists, perform update
54+
prevRevision := describeRes.Result.GetRevision().GetRevision()
55+
5456
updateReq := &pb.WorkflowContractServiceUpdateRequest{
5557
Name: contractName,
5658
Description: description,
@@ -59,10 +61,12 @@ func (action *WorkflowContractApply) Run(ctx context.Context, contractName strin
5961

6062
res, err := client.Update(ctx, updateReq)
6163
if err != nil {
62-
return nil, fmt.Errorf("failed to update existing contract '%s': %w", contractName, err)
64+
return nil, false, fmt.Errorf("failed to update existing contract '%s': %w", contractName, err)
6365
}
6466

65-
return pbWorkflowContractItemToAction(res.Result.Contract), nil
67+
unchanged := prevRevision == res.Result.GetRevision().GetRevision()
68+
69+
return pbWorkflowContractItemToAction(res.Result.Contract), unchanged, nil
6670
}
6771

6872
// Contract doesn't exist, perform create
@@ -80,8 +84,8 @@ func (action *WorkflowContractApply) Run(ctx context.Context, contractName strin
8084

8185
res, err := client.Create(ctx, createReq)
8286
if err != nil {
83-
return nil, fmt.Errorf("failed to create new contract '%s': %w", contractName, err)
87+
return nil, false, fmt.Errorf("failed to create new contract '%s': %w", contractName, err)
8488
}
8589

86-
return pbWorkflowContractItemToAction(res.Result), nil
90+
return pbWorkflowContractItemToAction(res.Result), false, nil
8791
}

‎app/controlplane/api/controlplane/v1/workflow_contract.pb.go‎

Lines changed: 14 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎app/controlplane/api/controlplane/v1/workflow_contract.proto‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,6 @@ message WorkflowContractServiceApplyRequest {
123123

124124
message WorkflowContractServiceApplyResponse {
125125
WorkflowContractItem result = 1;
126+
// Whether the resource was unchanged
127+
bool unchanged = 2;
126128
}

‎app/controlplane/api/gen/frontend/controlplane/v1/workflow_contract.ts‎

Lines changed: 19 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceApplyResponse.jsonschema.json‎

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceApplyResponse.schema.json‎

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎app/controlplane/internal/service/workflowcontract.go‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,10 @@ func (s *WorkflowContractService) Apply(ctx context.Context, req *pb.WorkflowCon
275275
return nil, handleUseCaseErr(err, s.log)
276276
}
277277

278-
return &pb.WorkflowContractServiceApplyResponse{Result: bizWorkFlowContractToPb(schemaWithVersion.Contract)}, nil
278+
return &pb.WorkflowContractServiceApplyResponse{
279+
Result: bizWorkFlowContractToPb(schemaWithVersion.Contract),
280+
Unchanged: schemaWithVersion.Unchanged,
281+
}, nil
279282
}
280283

281284
// Contract does not exist we create

0 commit comments

Comments
 (0)