Skip to content
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions pkg/workflow/argument_injection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package workflow

import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"
)
Expand Down Expand Up @@ -443,6 +445,71 @@ func TestValidatePipCommandPackageArg(t *testing.T) {
}
}

func TestValidatePythonPackagesWithPip_SkipsInvalidPackageBeforeExec(t *testing.T) {
compiler := NewCompiler()
tempDir := t.TempDir()
argsFile := filepath.Join(tempDir, "pip-args.txt")
fakePip := filepath.Join(tempDir, "pip")

script := `#!/bin/sh
printf "%s\n" "$@" >> "$GH_AW_TEST_PIP_ARGS_FILE"
`
if err := os.WriteFile(fakePip, []byte(script), 0o755); err != nil {
t.Fatalf("failed to write fake pip executable: %v", err)
}
t.Setenv("GH_AW_TEST_PIP_ARGS_FILE", argsFile)

compiler.validatePythonPackagesWithPip([]string{"--index-url"}, "pip", fakePip)

if _, err := os.Stat(argsFile); err == nil {
t.Fatalf("expected invalid package to be rejected before exec; args file %q was created", argsFile)
} else if !os.IsNotExist(err) {
t.Fatalf("failed to stat recorded pip arguments file: %v", err)
}
}

func TestValidatePythonPackagesWithPip_ExecutesValidatedPackage(t *testing.T) {
compiler := NewCompiler()
tempDir := t.TempDir()
argsFile := filepath.Join(tempDir, "pip-args.txt")
fakePip := filepath.Join(tempDir, "pip")

script := `#!/bin/sh
printf "%s\n" "$@" >> "$GH_AW_TEST_PIP_ARGS_FILE"
`
if err := os.WriteFile(fakePip, []byte(script), 0o755); err != nil {
t.Fatalf("failed to write fake pip executable: %v", err)
}
t.Setenv("GH_AW_TEST_PIP_ARGS_FILE", argsFile)

compiler.validatePythonPackagesWithPip([]string{"requests"}, "pip", fakePip)

if _, err := os.Stat(argsFile); err != nil {
if os.IsNotExist(err) {
t.Fatalf("expected pip to be invoked for valid package; args file %q was not created", argsFile)
}
t.Fatalf("failed to stat recorded pip arguments file: %v", err)
}

argsData, err := os.ReadFile(argsFile)
if err != nil {
t.Fatalf("failed to read recorded pip arguments: %v", err)
}
args := string(argsData)

// validatePythonPackagesWithPip executes: pip index versions <package> --pre
gotArgs := strings.Split(strings.TrimSpace(args), "\n")
wantArgs := []string{"index", "versions", "requests", "--pre"}
if len(gotArgs) != len(wantArgs) {
t.Fatalf("expected one pip invocation with %d args, got %d args: %q", len(wantArgs), len(gotArgs), args)
}
for i, want := range wantArgs {
if gotArgs[i] != want {
t.Fatalf("unexpected pip args at position %d: got %q, want %q (full args: %q)", i, gotArgs[i], want, args)
}
}
}

// TestValidateUvPackages_RejectsInvalidPackageName verifies that uv package names
// which do not conform to the PyPI naming rules are rejected before being passed
// as arguments to the uv CLI. This validation happens before uv/pip is resolved
Expand Down
Loading