Skip to content

Commit 925aea5

Browse files
add confirmation to deployment after preview
1 parent 0f51a9b commit 925aea5

4 files changed

Lines changed: 147 additions & 87 deletions

File tree

cmd/stack.go

Lines changed: 68 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import (
4343
stack_new "github.com/nitrictech/cli/pkg/view/tui/commands/stack/new"
4444
stack_preview "github.com/nitrictech/cli/pkg/view/tui/commands/stack/preview"
4545
stack_select "github.com/nitrictech/cli/pkg/view/tui/commands/stack/select"
46+
stack_up "github.com/nitrictech/cli/pkg/view/tui/commands/stack/up"
4647
"github.com/nitrictech/cli/pkg/view/tui/components/list"
4748
"github.com/nitrictech/cli/pkg/view/tui/components/listprompt"
4849
"github.com/nitrictech/cli/pkg/view/tui/components/view"
@@ -371,9 +372,7 @@ var stackUpdateCmd = &cobra.Command{
371372
}
372373
}
373374

374-
// Check if the thing is active
375-
376-
confirmModel := listprompt.NewListPrompt(listprompt.ListPromptArgs{
375+
confirmModel := stack_preview.NewConfirmDeployment(listprompt.ListPromptArgs{
377376
Items: list.StringsToListItems([]string{"confirm deployment", "cancel"}),
378377
Tag: "deploy",
379378
Prompt: "Finished preview. Would you like to perform the deployment?",
@@ -382,84 +381,76 @@ var stackUpdateCmd = &cobra.Command{
382381
selection, err := teax.NewProgram(confirmModel).Run()
383382
tui.CheckErr(err)
384383

385-
v := view.New()
386-
v.Break()
387-
fmt.Println("")
388-
389-
stackSelection = selection.(listprompt.ListPrompt).Choice()
384+
stackSelection = selection.(stack_preview.ConfirmDeploymentModel).Choice()
390385
if stackSelection == "cancel" {
391-
v.Addln("Cancelling deployment")
392-
fmt.Println(v.Render())
386+
fmt.Println("Cancelled")
393387
return
394388
}
395389

396-
v.Addln("Deployed")
397-
fmt.Println(v.Render())
390+
eventChan, errorChan := deploymentClient.Up(&deploymentspb.DeploymentUpRequest{
391+
Spec: spec,
392+
Attributes: attributesStruct,
393+
Interactive: true,
394+
})
395+
396+
// Step 5d. Communicate with server to share progress of update
397+
if isNonInteractive() {
398+
providerErrorDetected := false
399+
400+
fmt.Printf("Deploying %s stack with provider %s\n", stackConfig.Name, stackConfig.Provider)
401+
go func() {
402+
for update := range errorChan {
403+
fmt.Printf("Error: %s\n", update)
404+
providerErrorDetected = true
405+
}
406+
}()
407+
408+
go func() {
409+
for outMessage := range providerStdout {
410+
fmt.Printf("%s: %s\n", stackConfig.Provider, outMessage)
411+
}
412+
}()
413+
414+
// non-interactive environment
415+
for update := range eventChan {
416+
switch content := update.Content.(type) {
417+
case *deploymentspb.DeploymentUpEvent_Message:
418+
fmt.Printf("%s\n", content.Message)
419+
case *deploymentspb.DeploymentUpEvent_Update:
420+
updateResType := ""
421+
updateResName := ""
422+
if content.Update.Id != nil {
423+
updateResType = content.Update.Id.Type.String()
424+
updateResName = content.Update.Id.Name
425+
}
426+
427+
if updateResType == "" {
428+
updateResType = "Stack"
429+
}
430+
if updateResName == "" {
431+
updateResName = stackConfig.Name
432+
}
433+
if content.Update.SubResource != "" {
434+
updateResName = fmt.Sprintf("%s:%s", updateResName, content.Update.SubResource)
435+
}
436+
437+
fmt.Printf("%s:%s [%s]:%s %s\n", updateResType, updateResName, content.Update.Action, content.Update.Status, content.Update.Message)
438+
case *deploymentspb.DeploymentUpEvent_Result:
439+
fmt.Printf("\nResult: %s\n", content.Result.GetText())
440+
}
441+
}
398442

399-
// eventChan, errorChan := deploymentClient.Up(&deploymentspb.DeploymentUpRequest{
400-
// Spec: spec,
401-
// Attributes: attributesStruct,
402-
// Interactive: true,
403-
// })
404-
405-
// // Step 5d. Communicate with server to share progress of update
406-
// if isNonInteractive() {
407-
// providerErrorDetected := false
408-
409-
// fmt.Printf("Deploying %s stack with provider %s\n", stackConfig.Name, stackConfig.Provider)
410-
// go func() {
411-
// for update := range errorChan {
412-
// fmt.Printf("Error: %s\n", update)
413-
// providerErrorDetected = true
414-
// }
415-
// }()
416-
417-
// go func() {
418-
// for outMessage := range providerStdout {
419-
// fmt.Printf("%s: %s\n", stackConfig.Provider, outMessage)
420-
// }
421-
// }()
422-
423-
// // non-interactive environment
424-
// for update := range eventChan {
425-
// switch content := update.Content.(type) {
426-
// case *deploymentspb.DeploymentUpEvent_Message:
427-
// fmt.Printf("%s\n", content.Message)
428-
// case *deploymentspb.DeploymentUpEvent_Update:
429-
// updateResType := ""
430-
// updateResName := ""
431-
// if content.Update.Id != nil {
432-
// updateResType = content.Update.Id.Type.String()
433-
// updateResName = content.Update.Id.Name
434-
// }
435-
436-
// if updateResType == "" {
437-
// updateResType = "Stack"
438-
// }
439-
// if updateResName == "" {
440-
// updateResName = stackConfig.Name
441-
// }
442-
// if content.Update.SubResource != "" {
443-
// updateResName = fmt.Sprintf("%s:%s", updateResName, content.Update.SubResource)
444-
// }
445-
446-
// fmt.Printf("%s:%s [%s]:%s %s\n", updateResType, updateResName, content.Update.Action, content.Update.Status, content.Update.Message)
447-
// case *deploymentspb.DeploymentUpEvent_Result:
448-
// fmt.Printf("\nResult: %s\n", content.Result.GetText())
449-
// }
450-
// }
451-
452-
// // ensure the process exits with a non-zero status code after all messages are processed
453-
// if providerErrorDetected {
454-
// os.Exit(1)
455-
// }
456-
// } else {
457-
// // interactive environment
458-
// // Step 5e. Start the stack up view
459-
// stackUp := stack_up.New(stackConfig.Provider, stackConfig.Name, eventChan, providerStdout, errorChan)
460-
// _, err = teax.NewProgram(stackUp).Run()
461-
// tui.CheckErr(err)
462-
// }
443+
// ensure the process exits with a non-zero status code after all messages are processed
444+
if providerErrorDetected {
445+
os.Exit(1)
446+
}
447+
} else {
448+
// interactive environment
449+
// Step 5e. Start the stack up view
450+
stackUp := stack_up.New(stackConfig.Provider, stackConfig.Name, eventChan, providerStdout, errorChan)
451+
_, err = teax.NewProgram(stackUp).Run()
452+
tui.CheckErr(err)
453+
}
463454
},
464455
Args: cobra.MinimumNArgs(0),
465456
Aliases: []string{"up"},
@@ -990,7 +981,7 @@ func init() {
990981
stackUpdateCmd.Flags().BoolVarP(&noBuilder, "no-builder", "", false, "don't create a buildx container")
991982
stackUpdateCmd.Flags().StringVarP(&envFile, "env-file", "e", "", "--env-file config/.my-env")
992983
stackUpdateCmd.Flags().BoolVarP(&forceStack, "force", "f", false, "force override previous deployment")
993-
stackUpdateCmd.Flags().BoolVarP(&skipPreview, "skip-preview", "", false, "ignore preview")
984+
stackUpdateCmd.Flags().BoolVarP(&skipPreview, "skip-preview", "", false, "skips the preview step of the deployment")
994985
tui.CheckErr(AddOptions(stackUpdateCmd, false))
995986

996987
// Delete Stack (Down)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package stack_preview
2+
3+
import (
4+
"github.com/charmbracelet/bubbles/key"
5+
tea "github.com/charmbracelet/bubbletea"
6+
tui "github.com/nitrictech/cli/pkg/view/tui"
7+
"github.com/nitrictech/cli/pkg/view/tui/components/listprompt"
8+
"github.com/nitrictech/cli/pkg/view/tui/teax"
9+
)
10+
11+
type ConfirmDeploymentModel struct {
12+
windowSize tea.WindowSizeMsg
13+
14+
confirmPrompt listprompt.ListPrompt
15+
}
16+
17+
// Init initializes the model, used by Bubbletea
18+
func (m ConfirmDeploymentModel) Init() tea.Cmd {
19+
return nil
20+
}
21+
22+
// Update the model based on a message
23+
func (m ConfirmDeploymentModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
24+
var cmd tea.Cmd
25+
26+
switch msg := msg.(type) {
27+
case tea.WindowSizeMsg:
28+
m.windowSize = msg
29+
30+
if m.windowSize.Height < 7 {
31+
m.confirmPrompt.SetMinimized(true)
32+
m.confirmPrompt.SetMaxDisplayedItems(m.windowSize.Height - 1)
33+
} else {
34+
m.confirmPrompt.SetMinimized(false)
35+
maxItems := ((m.windowSize.Height - 1) / 3) // make room for the exit message
36+
m.confirmPrompt.SetMaxDisplayedItems(maxItems)
37+
}
38+
39+
return m, nil
40+
case tea.KeyMsg:
41+
switch {
42+
case key.Matches(msg, tui.KeyMap.Quit):
43+
return m, teax.Quit
44+
}
45+
}
46+
47+
m.confirmPrompt, cmd = m.confirmPrompt.UpdateListPrompt(msg)
48+
if m.confirmPrompt.IsComplete() {
49+
return m, teax.Quit
50+
}
51+
52+
return m, cmd
53+
}
54+
55+
func (m ConfirmDeploymentModel) View() string {
56+
return m.confirmPrompt.View()
57+
}
58+
59+
func (m ConfirmDeploymentModel) Choice() string {
60+
return m.confirmPrompt.Choice()
61+
}
62+
63+
func NewConfirmDeployment(args listprompt.ListPromptArgs) *ConfirmDeploymentModel {
64+
confirmPrompt := listprompt.NewListPrompt(args)
65+
66+
return &ConfirmDeploymentModel{
67+
confirmPrompt: confirmPrompt,
68+
}
69+
}

pkg/view/tui/commands/stack/preview/stack_preview.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// See the License for the specific language governing permissions and
1515
// limitations under the License.
1616

17-
package stack_up
17+
package stack_preview
1818

1919
import (
2020
"fmt"
@@ -207,17 +207,19 @@ func (m Model) View() string {
207207
currentNode := statusTree.AddNode(child.Name, "")
208208

209209
for _, grandchild := range child.Children {
210-
resourceTime := lo.Ternary(grandchild.FinishTime.IsZero(), time.Since(grandchild.StartTime).Round(time.Second), grandchild.FinishTime.Sub(grandchild.StartTime))
211-
212210
statusColor := tui.Colors.Blue
213-
if grandchild.Status == deploymentspb.ResourceDeploymentStatus_FAILED {
211+
if grandchild.Action == deploymentspb.ResourceDeploymentAction_DELETE {
214212
statusColor = tui.Colors.Red
215-
} else if grandchild.Status == deploymentspb.ResourceDeploymentStatus_SUCCESS || grandchild.Action == deploymentspb.ResourceDeploymentAction_SAME {
213+
} else if grandchild.Action == deploymentspb.ResourceDeploymentAction_CREATE {
216214
statusColor = tui.Colors.Green
215+
} else if grandchild.Action == deploymentspb.ResourceDeploymentAction_SAME {
216+
statusColor = tui.Colors.Gray
217217
}
218218

219-
statusText := fmt.Sprintf("%s (%s)", stack.VerbMap[grandchild.Action][grandchild.Status], resourceTime.Round(time.Second))
220-
currentNode.AddNode(grandchild.Name, lipgloss.NewStyle().Foreground(statusColor).Render(statusText))
219+
// Always uses the pending verbage to show it will happen, not that it has happened
220+
statusVerbage := stack.VerbMap[grandchild.Action][deploymentspb.ResourceDeploymentStatus_PENDING]
221+
222+
currentNode.AddNode(grandchild.Name, lipgloss.NewStyle().Foreground(statusColor).Render(statusVerbage))
221223
}
222224
}
223225

pkg/view/tui/components/listprompt/listprompt.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
package listprompt
1818

1919
import (
20-
"strings"
21-
2220
"github.com/charmbracelet/bubbles/key"
2321
tea "github.com/charmbracelet/bubbletea"
2422
"github.com/charmbracelet/lipgloss"
@@ -105,7 +103,7 @@ func (m ListPrompt) View() string {
105103
listView.Addln(m.Choice()).WithStyle(historyTextStyle)
106104
}
107105

108-
return strings.TrimSuffix(listView.Render(), "\n")
106+
return listView.Render()
109107
}
110108

111109
type ListPromptArgs struct {

0 commit comments

Comments
 (0)