Skip to content

Commit

Permalink
🎨 Implement redo pipeline trigger changes in the CLI (#1215)
Browse files Browse the repository at this point in the history
  • Loading branch information
Munklinde96 authored Sep 13, 2024
1 parent 880614b commit 5ee7164
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 88 deletions.
248 changes: 165 additions & 83 deletions cmd/common/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import (
"google.golang.org/protobuf/types/known/durationpb"
)

// var conditionTypes = []string{
// "Time Alive",
// }

func PromptPipelines(
prompter Prompter,
pipelines []*model.Pipeline,
Expand Down Expand Up @@ -160,12 +164,17 @@ func updatePipeline(
pipeline.Phases = append(pipeline.Phases, phase)
fields = slices.Insert(fields, len(fields)-3, fmt.Sprintf("Phase %s", phase.GetEnvironmentId()))
case len(fields) - 2:
header := []string{"Environment", "Triggers", "Fixed Fields"}
header := []string{"Environment", "Manual Trigger", "Auto Trigger", "Field Prefixes"}
rows := [][]string{}
for _, p := range pipeline.Phases {
var triggers []string
for _, t := range p.GetTriggers() {
triggers = append(triggers, triggerToString(t))
manualTrigger := "None"
if p.GetTriggers().GetManual() != nil {
manualTrigger = triggerToString(p.GetTriggers().GetManual())
}

autoTrigger := "None"
if p.GetTriggers().GetAutomatic() != nil {
autoTrigger = triggerToString(p.GetTriggers().GetAutomatic())
}

fieldsString := ""
Expand All @@ -178,8 +187,9 @@ func updatePipeline(
fieldsString += strings.Join(p.GetFieldPrefixes().GetPrefixes(), "/n")
}

rows = append(rows, []string{p.GetEnvironmentId(), strings.Join(triggers, "\n"),
fieldsString})
rows = append(rows, []string{
p.GetEnvironmentId(), manualTrigger, autoTrigger, fieldsString,
})
}
i, err := prompter.TableSelect("Select the phase to update (CTRL + C to cancel)", rows, header)
if err != nil {
Expand Down Expand Up @@ -333,127 +343,197 @@ func updateFieldPrefixes(prompter Prompter, prefixes *model.FieldPrefixes) (*mod
}
}

func updateTriggers(prompter Prompter, triggers []*model.PromotionTrigger) ([]*model.PromotionTrigger, error) {
if len(triggers) == 0 {
fmt.Println("No triggers configured - Let's configure one!")
t, err := updateTrigger(prompter, nil)
if err != nil {
return nil, err
}

return []*model.PromotionTrigger{
t,
}, nil
func updateTriggers(prompter Prompter, triggers *model.Triggers) (*model.Triggers, error) {
if triggers == nil {
triggers = &model.Triggers{}
}
triggers = proto.Clone(triggers).(*model.Triggers)

triggerToLabel := func(t *model.Trigger) string {
if t == nil {
return "None"
}

triggerToRow := func(t *model.PromotionTrigger) []string {
details := "None"
if t.GetCondition() != nil {
var conditions []string
for _, t := range t.GetConditions() {
switch v := t.GetCondition().(type) {
case *model.PromotionTrigger_TimeAlive:
details = fmt.Sprintf("Time Alive: %s", v.TimeAlive.AsDuration().String())
default:
details = "Unknown"
case *model.Trigger_Condition_TimeAlive:
conditions = append(conditions, fmt.Sprintf("Time Alive: %s", v.TimeAlive.AsDuration().String()))
}
}

triggerType := "Manual"
if t.GetAutomatic() {
triggerType = "Auto"
triggerType := "one-of"
if t.GetRequireAll() {
triggerType = "all-of"
}

return []string{triggerType, details}
return fmt.Sprintf("%s (%s)", triggerType, strings.Join(conditions, ", "))
}

header := []string{"Type", "Details"}
var triggerRows [][]string
for _, t := range triggers {
triggerRows = append(triggerRows, triggerToRow(t))
triggerLabels := []string{
"Auto " + triggerToLabel(triggers.GetAutomatic()),
"Manual " + triggerToLabel(triggers.GetManual()),
"Done",
}
triggerRows = append(triggerRows, []string{"Add new trigger", ""})
triggerRows = append(triggerRows, []string{"Remove trigger", ""})
triggerRows = append(triggerRows, []string{"Done", ""})

for {
i, err := prompter.TableSelect("Select the trigger to update (CTRL + C to cancel)", triggerRows, header)
i, _, err := prompter.Select("Select the trigger to update (CTRL + C to cancel)", triggerLabels)
if err != nil {
return nil, err
}

switch i {
case len(triggerRows) - 1:
case 2:
return triggers, nil
case len(triggerRows) - 2:
// Remove trigger
i, err := prompter.TableSelect("Select the trigger to remove (CTRL + C to cancel)",
triggerRows[:len(triggerRows)-3], header)
case 1:
t, err := updateTrigger(prompter, triggers.GetManual())
if err != nil {
if ErrIsAborted(err) {
continue
}
return nil, err
}

triggerRows = append(triggerRows[:i], triggerRows[i+1:]...)
triggers = append(triggers[:i], triggers[i+1:]...)
case len(triggerRows) - 3:
triggers.Manual = t
triggerLabels[1] = "Manual " + triggerToLabel(t)
case 0:
// Add new trigger
t, err := updateTrigger(prompter, nil)
t, err := updateTrigger(prompter, triggers.GetAutomatic())
if err != nil {
if ErrIsAborted(err) {
continue
}
return nil, err
}

triggers = append(triggers, t)
triggerRows = slices.Insert(triggerRows, len(triggerRows)-3, triggerToRow(t))
default:
// Update trigger
t, err := updateTrigger(prompter, triggers[i])
triggers.Automatic = t
triggerLabels[0] = "Auto " + triggerToLabel(t)
}
}
}

func updateTrigger(prompter Prompter, trigger *model.Trigger) (*model.Trigger, error) {
if trigger == nil {
trigger = &model.Trigger{}
}
trigger = proto.Clone(trigger).(*model.Trigger)

require := "Require all conditions"
if trigger.GetRequireAll() {
require = "Require any condition"
}

fields := []string{
require,
"Conditions",
"Clear",
"Done",
}

for {
i, _, err := prompter.Select("Select the field to update (CTRL + C to cancel)", fields)
if err != nil {
return nil, err
}

switch i {
case 0:
trigger.RequireAll = !trigger.RequireAll
fields[0] = "Require all conditions"
if trigger.GetRequireAll() {
fields[0] = "Require any condition"
}
case 1:
conditions, err := updateConditions(prompter, trigger.GetConditions())
if err != nil {
if ErrIsAborted(err) {
continue
}
return nil, err
}

triggers[i] = t
triggerRows[i] = triggerToRow(t)
trigger.Conditions = conditions
case 2:
return nil, nil
case 3:
return trigger, nil
}
}
}

func updateTrigger(prompter Prompter, trigger *model.PromotionTrigger) (*model.PromotionTrigger, error) {
if trigger == nil {
trigger = &model.PromotionTrigger{}
}
trigger = proto.Clone(trigger).(*model.PromotionTrigger)
func updateConditions(prompter Prompter, conditions []*model.Trigger_Condition) ([]*model.Trigger_Condition, error) {
conditionToLabel := func(c *model.Trigger_Condition) string {
switch v := c.GetCondition().(type) {
case *model.Trigger_Condition_TimeAlive:
return fmt.Sprintf("Time Alive: %s", v.TimeAlive.AsDuration().String())
}

types := []string{"Auto", "Manual"}
i, _, err := prompter.Select("Select the trigger type", types)
if err != nil {
return nil, err
return "None"
}

if i == 0 {
trigger.Automatic = true
} else {
trigger.Automatic = false
conditionLabels := []string{}
for _, c := range conditions {
conditionLabels = append(conditionLabels, conditionToLabel(c))
}
conditionLabels = append(conditionLabels, "Add", "Remove", "Done")

hasCondition, err := prompter.Confirm("Is this trigger condition based?", false)
if err != nil {
return nil, err
for {
i, _, err := prompter.Select("Select the condition to update (CTRL + C to cancel)", conditionLabels)
if err != nil {
return nil, err
}

switch i {
case len(conditionLabels) - 3:
// When we have more, we should switch on types
c, err := updateTimeAliveCondition(prompter, nil)
if err != nil {
if ErrIsAborted(err) {
continue
}
return nil, err
}

conditions = append(conditions, c)

conditionLabels = slices.Insert(conditionLabels,
len(conditionLabels)-3, conditionToLabel(conditions[len(conditions)-1]))
case len(conditionLabels) - 2:
i, _, err := prompter.Select("Select the condition to remove", conditionLabels[:len(conditionLabels)-3])
if err != nil {
if ErrIsAborted(err) {
continue
}
return nil, err
}

conditions = append(conditions[:i], conditions[i+1:]...)
conditionLabels = append(conditionLabels[:i], conditionLabels[i+1:]...)
case len(conditionLabels) - 1:
return conditions, nil
default:
c, err := updateTimeAliveCondition(prompter, conditions[i])
if err != nil {
if ErrIsAborted(err) {
continue
}
return nil, err
}

conditions[i] = c
conditionLabels[i] = conditionToLabel(c)
}
}
}

if !hasCondition {
trigger.Condition = nil
return trigger, nil
func updateTimeAliveCondition(prompter Prompter, c *model.Trigger_Condition) (*model.Trigger_Condition, error) {
if c == nil {
c = &model.Trigger_Condition{}
}

c = proto.Clone(c).(*model.Trigger_Condition)
d, err := prompter.Input("Enter the time alive", ValidateDurationOpt,
InputDefaultOpt(trigger.GetTimeAlive().AsDuration().String()))
InputDefaultOpt(c.GetTimeAlive().AsDuration().String()))
if err != nil {
return nil, err
}
Expand All @@ -463,25 +543,27 @@ func updateTrigger(prompter Prompter, trigger *model.PromotionTrigger) (*model.P
return nil, err
}

trigger.Condition = &model.PromotionTrigger_TimeAlive{
c.Condition = &model.Trigger_Condition_TimeAlive{
TimeAlive: durationpb.New(dur),
}

return trigger, nil
return c, nil
}

func triggerToString(t *model.PromotionTrigger) string {
str := "manual"
if t.GetAutomatic() {
str = "auto"
func triggerToString(t *model.Trigger) string {
require := "one-of"
if t.GetRequireAll() {
require = "all-of"
}

if t.GetCondition() != nil {
switch v := t.GetCondition().(type) {
case *model.PromotionTrigger_TimeAlive:
str = str + fmt.Sprintf(" (%s)", v.TimeAlive.AsDuration().String())
conditions := []string{}

for _, c := range t.GetConditions() {
switch v := c.GetCondition().(type) {
case *model.Trigger_Condition_TimeAlive:
conditions = append(conditions, fmt.Sprintf("Time Alive (%s)", v.TimeAlive.AsDuration().String()))
}
}

return str
return fmt.Sprintf("%s: %s)", require, strings.Join(conditions, ", "))
}
2 changes: 1 addition & 1 deletion cmd/rig/cmd/capsule/pipeline/progress.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (c *Cmd) progress(ctx context.Context, cmd *cobra.Command, args []string) e
return err
}

resp, err := c.Rig.Capsule().ProgressPipeline(ctx, connect.NewRequest(&capsule_api.ProgressPipelineRequest{
resp, err := c.Rig.Capsule().PromotePipeline(ctx, connect.NewRequest(&capsule_api.PromotePipelineRequest{
ExecutionId: pipelineID,
DryRun: dryRun,
}))
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ require (
github.com/nyaruka/phonenumbers v1.1.7
github.com/pkg/errors v0.9.1
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.70.0
github.com/rigdev/rig-go-api v0.0.0-20240912093741-f27a73d5eed6
github.com/rigdev/rig-go-api v0.0.0-20240913070422-446ab5e22615
github.com/rigdev/rig-go-sdk v0.0.0-20240612092526-69df8621bc22
github.com/rivo/tview v0.0.0-20240524063012-037df494fb76
github.com/robfig/cron v1.2.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,8 @@ github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+a
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
github.com/prometheus/procfs v0.14.0 h1:Lw4VdGGoKEZilJsayHf0B+9YgLGREba2C6xr+Fdfq6s=
github.com/prometheus/procfs v0.14.0/go.mod h1:XL+Iwz8k8ZabyZfMFHPiilCniixqQarAy5Mu67pHlNQ=
github.com/rigdev/rig-go-api v0.0.0-20240912093741-f27a73d5eed6 h1:NWNK514FRXVxUIaN/rbFJ25+z8ccr6bVcU+9qH7gc+0=
github.com/rigdev/rig-go-api v0.0.0-20240912093741-f27a73d5eed6/go.mod h1:boVP47XBT/EkpqjVXkZCcF31Nw5RMRANwQuaVvgw9dM=
github.com/rigdev/rig-go-api v0.0.0-20240913070422-446ab5e22615 h1:Sj/rul1RGG/TJuVBTpsMh4l022OCeocsfNYZIdlRvg8=
github.com/rigdev/rig-go-api v0.0.0-20240913070422-446ab5e22615/go.mod h1:boVP47XBT/EkpqjVXkZCcF31Nw5RMRANwQuaVvgw9dM=
github.com/rigdev/rig-go-sdk v0.0.0-20240612092526-69df8621bc22 h1:NFjBY/F42lcgqnqru+h1q3RrzRk645HUilCvbZD7exI=
github.com/rigdev/rig-go-sdk v0.0.0-20240612092526-69df8621bc22/go.mod h1:bmASl5RyuOoEddGeaOxHB27W3KDI4sBxqfnR1cRTstY=
github.com/rivo/tview v0.0.0-20240524063012-037df494fb76 h1:iqvDlgyjmqleATtFbA7c14djmPh2n4mCYUv7JlD/ruA=
Expand Down
2 changes: 1 addition & 1 deletion pkg/rbac/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ var CapsuleActionMap = map[string]string{
capsuleconnect.ServiceListPipelineStatusesProcedure: ActionCapsuleView,
capsuleconnect.ServiceGetPipelineStatusProcedure: ActionCapsuleView,
capsuleconnect.ServiceAbortPipelineProcedure: ActionCapsuleDeploy,
capsuleconnect.ServiceProgressPipelineProcedure: ActionCapsuleDeploy,
capsuleconnect.ServicePromotePipelineProcedure: ActionCapsuleDeploy,
capsuleconnect.ServiceStartPipelineProcedure: ActionCapsuleDeploy,
}

Expand Down

0 comments on commit 5ee7164

Please sign in to comment.