Skip to content

Commit

Permalink
feat: Extend ApprovalTask with approval details
Browse files Browse the repository at this point in the history
- Add `approvedBy` and `comment` fields to the `ApprovalTask` spec
- Include `approvedBy`, `comment`, and `approve` fields in the `CustomRun` results
  • Loading branch information
zmotso committed Oct 7, 2024
1 parent 12f089b commit f8cb96f
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 5 deletions.
14 changes: 14 additions & 0 deletions api/v1alpha1/approvaltask_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ type ApprovalTaskSpec struct {
// +optional
// +kubebuilder:default=Proceed
Description string `json:"description,omitempty"`

// Approve is the approval information.
// +optional
Approve *Approve `json:"approve,omitempty"`
}

type Approve struct {
// ApprovedBy is indicating the identity of the approver.
// +required
ApprovedBy string `json:"approvedBy"`

// Comment is the comment provided by the approver.
// +optional
Comment string `json:"comment,omitempty"`
}

type PipelineRef struct {
Expand Down
22 changes: 21 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

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

12 changes: 12 additions & 0 deletions config/crd/bases/edp.epam.com_approvaltasks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ spec:
- Rejected
- Canceled
type: string
approve:
description: Approve is the approval information.
properties:
approvedBy:
description: ApprovedBy is indicating the identity of the approver.
type: string
comment:
description: Comment is the comment provided by the approver.
type: string
required:
- approvedBy
type: object
description:
default: Proceed
description: Description that is shown to the user for the approval
Expand Down
12 changes: 12 additions & 0 deletions deploy-templates/crds/edp.epam.com_approvaltasks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ spec:
- Rejected
- Canceled
type: string
approve:
description: Approve is the approval information.
properties:
approvedBy:
description: ApprovedBy is indicating the identity of the approver.
type: string
comment:
description: Comment is the comment provided by the approver.
type: string
required:
- approvedBy
type: object
description:
default: Proceed
description: Description that is shown to the user for the approval
Expand Down
41 changes: 41 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ ApprovalTaskSpec defines the desired state of ApprovalTask
<i>Default</i>: Pending<br/>
</td>
<td>false</td>
</tr><tr>
<td><b><a href="#approvaltaskspecapprove">approve</a></b></td>
<td>object</td>
<td>
Approve is the approval information.<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>description</b></td>
<td>string</td>
Expand All @@ -104,3 +111,37 @@ ApprovalTaskSpec defines the desired state of ApprovalTask
<td>false</td>
</tr></tbody>
</table>


### ApprovalTask.spec.approve
<sup><sup>[↩ Parent](#approvaltaskspec)</sup></sup>



Approve is the approval information.

<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody><tr>
<td><b>approvedBy</b></td>
<td>string</td>
<td>
ApprovedBy is indicating the identity of the approver.<br/>
</td>
<td>true</td>
</tr><tr>
<td><b>comment</b></td>
<td>string</td>
<td>
Comment is the comment provided by the approver.<br/>
</td>
<td>false</td>
</tr></tbody>
</table>
57 changes: 53 additions & 4 deletions internal/controller/customrun_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package controller
import (
"context"
"fmt"
"strconv"
"time"

customTasksApi "github.com/KubeRocketCI/tekton-custom-task/api/v1alpha1"
Expand Down Expand Up @@ -96,11 +97,20 @@ func (r *ReconcileCustomRun) setRunningStatus(ctx context.Context, run *tektonPi
return nil
}

func (r *ReconcileCustomRun) setSucceededStatus(ctx context.Context, run *tektonPipelineApi.CustomRun) error {
func (r *ReconcileCustomRun) setSucceededStatus(
ctx context.Context,
run *tektonPipelineApi.CustomRun,
results []tektonPipelineApi.CustomRunResult,
) error {
now := metav1.Now()
run.Status.CompletionTime = &now
run.Status.MarkCustomRunSucceeded("Approved", "Pipeline run was approved")

run.Status.Results = append(
run.Status.Results,
results...,
)

if err := r.client.Status().Update(ctx, run); err != nil {
return fmt.Errorf("failed to update CustomRun status: %w", err)
}
Expand All @@ -112,9 +122,15 @@ func (r *ReconcileCustomRun) setFailedStatus(
ctx context.Context,
run *tektonPipelineApi.CustomRun,
reason, message string,
results []tektonPipelineApi.CustomRunResult,
) error {
run.Status.MarkCustomRunFailed(reason, message)

run.Status.Results = append(
run.Status.Results,
results...,
)

if err := r.client.Status().Update(ctx, run); err != nil {
return fmt.Errorf("failed to update CustomRun status: %w", err)
}
Expand Down Expand Up @@ -147,7 +163,7 @@ func (r *ReconcileCustomRun) processApprovalTask(ctx context.Context, run *tekto
if task.IsApproved() {
log.Info("ApprovalTask is approved")

if err = r.setSucceededStatus(ctx, run); err != nil {
if err = r.setSucceededStatus(ctx, run, getResults(task)); err != nil {
return err
}

Expand All @@ -157,7 +173,7 @@ func (r *ReconcileCustomRun) processApprovalTask(ctx context.Context, run *tekto
if task.IsRejected() {
log.Info("ApprovalTask is rejected")

if err = r.setFailedStatus(ctx, run, "Rejected", "Pipeline run was rejected"); err != nil {
if err = r.setFailedStatus(ctx, run, "Rejected", "Pipeline run was rejected", getResults(task)); err != nil {
return err
}

Expand Down Expand Up @@ -217,7 +233,7 @@ func (r *ReconcileCustomRun) cancelApprovalTask(ctx context.Context, run *tekton
log.Info("ApprovalTask canceled")
}

if err = r.setFailedStatus(ctx, run, "Canceled", "Pipeline run was canceled"); err != nil {
if err = r.setFailedStatus(ctx, run, "Canceled", "Pipeline run was canceled", getResults(task)); err != nil {
return err
}

Expand Down Expand Up @@ -305,3 +321,36 @@ func getApprovalTaskDescription(run *tektonPipelineApi.CustomRun) string {

return ""
}

func getResults(task *customTasksApi.ApprovalTask) []tektonPipelineApi.CustomRunResult {
if task == nil {
return []tektonPipelineApi.CustomRunResult{
{
Name: "approved",
Value: "false",
},
}
}

r := []tektonPipelineApi.CustomRunResult{
{
Name: "approved",
Value: strconv.FormatBool(task.IsApproved()),
},
}

if task.Spec.Approve != nil {
r = append(r,
tektonPipelineApi.CustomRunResult{
Name: "approvedBy",
Value: task.Spec.Approve.ApprovedBy,
},
tektonPipelineApi.CustomRunResult{
Name: "comment",
Value: task.Spec.Approve.Comment,
},
)
}

return r
}
14 changes: 14 additions & 0 deletions internal/controller/customrun_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ var _ = Describe("CodebaseIntegration controller", func() {

By("Approving ApprovalTask")
task.Spec.Action = customTasksApi.TaskApproved
task.Spec.Approve = &customTasksApi.Approve{
ApprovedBy: "admin",
Comment: "ok",
}
g.Expect(k8sClient.Update(ctx, task)).Should(Succeed())
}).WithTimeout(time.Second * 5).WithPolling(time.Second).Should(Succeed())
By("Checking CustomRun completion")
Expand All @@ -86,6 +90,8 @@ var _ = Describe("CodebaseIntegration controller", func() {
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(createdRun.IsSuccessful()).Should(BeTrue())
g.Expect(createdRun.Status.CompletionTime).ShouldNot(BeNil())
g.Expect(createdRun.Status.Results).Should(HaveLen(3))
g.Expect(createdRun.Status.Results[0].Value).Should(Equal("true"))
}).WithTimeout(time.Second * 20).WithPolling(time.Second).Should(Succeed())
})
It("Should process CustomRun with reject ApprovalTask", func() {
Expand All @@ -111,6 +117,10 @@ var _ = Describe("CodebaseIntegration controller", func() {

By("Rejecting ApprovalTask")
task.Spec.Action = customTasksApi.TaskRejected
task.Spec.Approve = &customTasksApi.Approve{
ApprovedBy: "admin",
Comment: "not ok",
}
g.Expect(k8sClient.Update(ctx, task)).Should(Succeed())
}).WithTimeout(time.Second * 5).WithPolling(time.Second).Should(Succeed())
By("Checking CustomRun completion")
Expand All @@ -122,6 +132,8 @@ var _ = Describe("CodebaseIntegration controller", func() {
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(createdRun.IsSuccessful()).Should(BeFalse())
g.Expect(createdRun.Status.CompletionTime).ShouldNot(BeNil())
g.Expect(createdRun.Status.Results).Should(HaveLen(3))
g.Expect(createdRun.Status.Results[0].Value).Should(Equal("false"))
}).WithTimeout(time.Second * 20).WithPolling(time.Second).Should(Succeed())
})
It("Should cancel ApprovalTask after canceling CustomRun", func() {
Expand Down Expand Up @@ -171,6 +183,8 @@ var _ = Describe("CodebaseIntegration controller", func() {
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(createdRun.IsSuccessful()).Should(BeFalse())
g.Expect(createdRun.Status.CompletionTime).ShouldNot(BeNil())
g.Expect(createdRun.Status.Results).Should(HaveLen(1))
g.Expect(createdRun.Status.Results[0].Value).Should(Equal("false"))
}).WithTimeout(time.Second * 20).WithPolling(time.Second).Should(Succeed())
})
It("Should skip CustomRun without ApprovalTask ref", func() {
Expand Down

0 comments on commit f8cb96f

Please sign in to comment.