provide package blocked feedback in proxy mode (#154)

* provide package blocked feedback in proxy mode

* update test case & clear status on block

* refactor reporting

* clearStatus on `continueExecution`

* set spinnerChan to nil

* add sync for spinner
This commit is contained in:
Sahil Bansal
2026-02-11 09:22:18 +05:30
committed by GitHub
parent a6cb60a757
commit 7fe9fc8763
5 changed files with 47 additions and 39 deletions
-2
View File
@@ -85,8 +85,6 @@ func (f *proxyFlow) Run(ctx context.Context, args []string, parsedCmd *packagema
return nil
}
ui.SetStatus("Initializing proxy mode...")
// Setup CA certificate for MITM
caCert, caCertPath, err := f.setupCACertificate()
if err != nil {
+8 -1
View File
@@ -119,6 +119,8 @@ func (r *ReportData) WasSuccessful() bool {
func Report(data *ReportData) {
data.Finalize()
StopSpinner()
switch verbosityLevel {
case VerbosityLevelSilent:
reportSilent(data)
@@ -133,7 +135,6 @@ func Report(data *ReportData) {
// Normal successful execution produces no output
func reportSilent(data *ReportData) {
// Silent mode: no report output
// Block messages and errors are already shown via ui.Block() and ui.ErrorExit()
}
// reportNormal shows minimal, assuring output
@@ -171,6 +172,12 @@ func reportNormal(data *ReportData) {
switch data.Outcome {
case OutcomeBlocked:
fmt.Println()
fmt.Printf("%s %s\n", Colors.Red("✗"), Colors.Red("Malicious package blocked"))
printMaliciousPackagesList(data.BlockedPackages)
fmt.Println()
icon = Colors.Red("✗")
message = fmt.Sprintf("PMG: %d packages analyzed, %d blocked",
data.TotalAnalyzed, data.BlockedCount)
+22 -1
View File
@@ -2,10 +2,14 @@ package ui
import (
"fmt"
"sync"
"time"
)
var spinnerChan chan bool
var (
spinnerChan chan bool
spinnerMu sync.Mutex
)
func StartSpinner(msg string) {
StartSpinnerWithColor(msg, Colors.Normal)
@@ -20,7 +24,15 @@ func StartSpinnerWithColor(msg string, c ColorFn) {
frames := []rune(style)
length := len(frames)
spinnerMu.Lock()
// If a previous spinner exists, stop it cleanly before starting a new one
if spinnerChan != nil {
close(spinnerChan)
spinnerChan = nil
}
spinnerChan = make(chan bool)
spinnerMu.Unlock()
ticker := time.NewTicker(100 * time.Millisecond)
go func() {
@@ -40,6 +52,13 @@ func StartSpinnerWithColor(msg string, c ColorFn) {
}
func StopSpinner() {
spinnerMu.Lock()
defer spinnerMu.Unlock()
if spinnerChan == nil {
return
}
// Gracefully handle the case where the spinner is already stopped
// and the channel is closed, yet client code calls StopSpinner() again.
defer func() {
@@ -48,6 +67,8 @@ func StopSpinner() {
close(spinnerChan)
spinnerChan = nil
fmt.Printf("\r")
fmt.Println()
}