chore: update CLI to CLIO (#2001)

Signed-off-by: Keith Zantow <kzantow@gmail.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Keith Zantow
2023-08-29 15:52:26 -04:00
committed by GitHub
co-authored by Alex Goodman
parent b03e9c6868
commit 2b7a9d0be3
95 changed files with 1680 additions and 3192 deletions
+5
View File
@@ -0,0 +1,5 @@
package internal
const (
NotProvided = "[not provided]"
)
-2
View File
@@ -33,8 +33,6 @@ func (n *NoUI) Handle(e partybus.Event) error {
case event.CLIReport, event.CLINotification:
// keep these for when the UI is terminated to show to the screen (or perform other events)
n.finalizeEvents = append(n.finalizeEvents, e)
case event.CLIExit:
return n.subscription.Unsubscribe()
}
return nil
}
+7 -3
View File
@@ -10,7 +10,6 @@ import (
"github.com/wagoodman/go-partybus"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/version"
"github.com/anchore/syft/syft/event"
"github.com/anchore/syft/syft/event/parsers"
)
@@ -119,13 +118,18 @@ func writeAppUpdate(writer io.Writer, events ...partybus.Event) error {
style := lipgloss.NewStyle().Foreground(lipgloss.Color("13")).Italic(true)
for _, e := range events {
newVersion, err := parsers.ParseCLIAppUpdateAvailable(e)
updateCheck, err := parsers.ParseCLIAppUpdateAvailable(e)
if err != nil {
log.WithFields("error", err).Warn("failed to parse app update notification")
continue
}
notice := fmt.Sprintf("A newer version of syft is available for download: %s (installed version is %s)", newVersion, version.FromBuild().Version)
if updateCheck.Current == updateCheck.New {
log.Tracef("update check event with identical versions: %s", updateCheck.Current)
continue
}
notice := fmt.Sprintf("A newer version of syft is available for download: %s (installed version is %s)", updateCheck.New, updateCheck.Current)
if _, err := fmt.Fprintln(writer, style.Render(notice)); err != nil {
// don't let this be fatal
@@ -9,6 +9,7 @@ import (
"github.com/wagoodman/go-partybus"
"github.com/anchore/syft/syft/event"
"github.com/anchore/syft/syft/event/parsers"
)
func Test_postUIEventWriter_write(t *testing.T) {
@@ -34,8 +35,11 @@ func Test_postUIEventWriter_write(t *testing.T) {
Value: "<notification 2>",
},
{
Type: event.CLIAppUpdateAvailable,
Value: "v0.33.0",
Type: event.CLIAppUpdateAvailable,
Value: parsers.UpdateCheck{
New: "v0.33.0",
Current: "[not provided]",
},
},
{
Type: event.CLINotification,
@@ -61,8 +65,11 @@ func Test_postUIEventWriter_write(t *testing.T) {
Value: "<notification 1>",
},
{
Type: event.CLIAppUpdateAvailable,
Value: "<app update>",
Type: event.CLIAppUpdateAvailable,
Value: parsers.UpdateCheck{
New: "<new version>",
Current: "<current version>",
},
},
{
Type: event.CLIReport,
+9 -14
View File
@@ -49,31 +49,23 @@ func (m *UI) Setup(subscription partybus.Unsubscribable) error {
}
m.subscription = subscription
m.program = tea.NewProgram(m, tea.WithOutput(os.Stderr), tea.WithInput(os.Stdin))
m.program = tea.NewProgram(m, tea.WithOutput(os.Stderr), tea.WithInput(os.Stdin), tea.WithoutSignalHandler())
m.running.Add(1)
go func() {
defer m.running.Done()
if _, err := m.program.Run(); err != nil {
log.Errorf("unable to start UI: %+v", err)
m.exit()
bus.ExitWithInterrupt()
}
}()
return nil
}
func (m *UI) exit() {
// stop the event loop
bus.Exit()
}
func (m *UI) Handle(e partybus.Event) error {
if m.program != nil {
m.program.Send(e)
if e.Type == event.CLIExit {
return m.subscription.Unsubscribe()
}
}
return nil
}
@@ -88,7 +80,9 @@ func (m *UI) Teardown(force bool) error {
// string from the worker (outside of the UI after teardown).
m.running.Wait()
} else {
m.program.Kill()
// it may be tempting to use Kill() however it has been found that this can cause the terminal to be left in
// a bad state (where Ctrl+C and other control characters no longer works for future processes in that terminal).
m.program.Quit()
}
// TODO: allow for writing out the full log output to the screen (only a partial log is shown currently)
@@ -107,7 +101,6 @@ func (m UI) RespondsTo() []partybus.EventType {
return append([]partybus.EventType{
event.CLIReport,
event.CLINotification,
event.CLIExit,
event.CLIAppUpdateAvailable,
}, m.handler.RespondsTo()...)
}
@@ -126,8 +119,10 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
// today we treat esc and ctrl+c the same, but in the future when the syft worker has a graceful way to
// cancel in-flight work via a context, we can wire up esc to this path with bus.Exit()
case "esc", "ctrl+c":
m.exit()
bus.ExitWithInterrupt()
return m, tea.Quit
}
@@ -135,7 +130,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
log.WithFields("component", "ui").Tracef("event: %q", msg.Type)
switch msg.Type {
case event.CLIReport, event.CLINotification, event.CLIExit, event.CLIAppUpdateAvailable:
case event.CLIReport, event.CLINotification, event.CLIAppUpdateAvailable:
// keep these for when the UI is terminated to show to the screen (or perform other events)
m.finalizeEvents = append(m.finalizeEvents, msg)