mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
fix: Interactive pty identification for proxy mode (#174)
This commit is contained in:
@@ -39,11 +39,8 @@ func ProxyFlow(pm packagemanager.PackageManager, packageResolver packagemanager.
|
|||||||
|
|
||||||
// Run executes the proxy-based flow
|
// Run executes the proxy-based flow
|
||||||
func (f *proxyFlow) Run(ctx context.Context, args []string, parsedCmd *packagemanager.ParsedCommand) error {
|
func (f *proxyFlow) Run(ctx context.Context, args []string, parsedCmd *packagemanager.ParsedCommand) error {
|
||||||
|
// Check if we have a supported ecosystem else fail fast
|
||||||
// Get the ecosystem from the package manager
|
|
||||||
ecosystem := f.pm.Ecosystem()
|
ecosystem := f.pm.Ecosystem()
|
||||||
|
|
||||||
// Check if proxy mode is supported for this ecosystem
|
|
||||||
if !interceptors.IsSupported(ecosystem) {
|
if !interceptors.IsSupported(ecosystem) {
|
||||||
return fmt.Errorf("proxy mode is not supported for %s", ecosystem.String())
|
return fmt.Errorf("proxy mode is not supported for %s", ecosystem.String())
|
||||||
}
|
}
|
||||||
@@ -82,6 +79,7 @@ func (f *proxyFlow) Run(ctx context.Context, args []string, parsedCmd *packagema
|
|||||||
|
|
||||||
reportData.Outcome = ui.OutcomeDryRun
|
reportData.Outcome = ui.OutcomeDryRun
|
||||||
ui.Report(reportData)
|
ui.Report(reportData)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,12 +162,12 @@ func (f *proxyFlow) Run(ctx context.Context, args []string, parsedCmd *packagema
|
|||||||
proxyEnv := f.setupEnvForProxy(proxyAddr, caCertPath)
|
proxyEnv := f.setupEnvForProxy(proxyAddr, caCertPath)
|
||||||
|
|
||||||
var executionError error
|
var executionError error
|
||||||
if !pty.IsInteractiveTerminal() {
|
if pty.IsInteractiveTerminal() {
|
||||||
// Execute the package manager command with proxy environment variables for non PTY or non-interactive TTY
|
|
||||||
executionError = f.executeWithProxyForNonInteractiveTTY(ctx, parsedCmd, proxyEnv, confirmationChan, interaction)
|
|
||||||
} else {
|
|
||||||
// Execute the package manager command with proxy environment variables
|
// Execute the package manager command with proxy environment variables
|
||||||
executionError = f.executeWithProxy(ctx, parsedCmd, proxyEnv, confirmationChan, interaction)
|
executionError = f.executeWithProxy(ctx, parsedCmd, proxyEnv, confirmationChan, interaction)
|
||||||
|
} else {
|
||||||
|
// Execute the package manager command with proxy environment variables for non PTY or non-interactive TTY
|
||||||
|
executionError = f.executeWithProxyForNonInteractiveTTY(ctx, parsedCmd, proxyEnv, confirmationChan, interaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate report data from stats collector
|
// Populate report data from stats collector
|
||||||
@@ -221,7 +219,7 @@ func (f *proxyFlow) setupCACertificate() (*certmanager.Certificate, string, erro
|
|||||||
tempDir := os.TempDir()
|
tempDir := os.TempDir()
|
||||||
caCertPath := filepath.Join(tempDir, fmt.Sprintf("pmg-ca-cert-%d.pem", os.Getpid()))
|
caCertPath := filepath.Join(tempDir, fmt.Sprintf("pmg-ca-cert-%d.pem", os.Getpid()))
|
||||||
|
|
||||||
if err := os.WriteFile(caCertPath, caCert.Certificate, 0600); err != nil {
|
if err := os.WriteFile(caCertPath, caCert.Certificate, 0o600); err != nil {
|
||||||
return nil, "", fmt.Errorf("failed to write CA certificate to %s: %w", caCertPath, err)
|
return nil, "", fmt.Errorf("failed to write CA certificate to %s: %w", caCertPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-2
@@ -36,13 +36,21 @@ type InteractiveSession interface {
|
|||||||
|
|
||||||
// IsInteractiveTerminal returns true if stdin is a real terminal (TTY).
|
// IsInteractiveTerminal returns true if stdin is a real terminal (TTY).
|
||||||
// Returns false in CI environments (when the "CI" env var set to "true"),
|
// Returns false in CI environments (when the "CI" env var set to "true"),
|
||||||
// when input is piped, or in non-interactive shells.
|
// when input or output is piped, or in non-interactive shells.
|
||||||
func IsInteractiveTerminal() bool {
|
func IsInteractiveTerminal() bool {
|
||||||
if ci := os.Getenv("CI"); ci != "" && strings.ToLower(ci) == "true" {
|
if ci := os.Getenv("CI"); ci != "" && strings.ToLower(ci) == "true" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return term.IsTerminal(int(os.Stdin.Fd()))
|
if !term.IsTerminal(int(os.Stdout.Fd())) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !term.IsTerminal(int(os.Stdin.Fd())) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ InteractiveSession = &session{}
|
var _ InteractiveSession = &session{}
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package pty
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsInteractiveTerminal(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
ciEnv string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "returns false when CI env is set to true",
|
||||||
|
ciEnv: "true",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "returns false when CI env is set to TRUE (case insensitive)",
|
||||||
|
ciEnv: "TRUE",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "returns false when CI env is set to True (mixed case)",
|
||||||
|
ciEnv: "True",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "returns false in test runner (stdin/stdout are pipes)",
|
||||||
|
ciEnv: "",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if tt.ciEnv != "" {
|
||||||
|
t.Setenv("CI", tt.ciEnv)
|
||||||
|
} else {
|
||||||
|
t.Setenv("CI", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
result := IsInteractiveTerminal()
|
||||||
|
assert.Equal(t, tt.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user