diff --git a/pkg/workflow/action_pins.go b/pkg/workflow/action_pins.go index 0db3d28694..d2facbd156 100644 --- a/pkg/workflow/action_pins.go +++ b/pkg/workflow/action_pins.go @@ -156,7 +156,7 @@ func GetActionPin(actionRepo string) string { // GetActionPinWithData returns the pinned action reference for a given action@version // It tries dynamic resolution first, then falls back to hardcoded pins -// If strictMode is true and resolution fails, it returns an error +// If resolution fails, emits a warning and returns empty string (in both strict and non-strict modes) // The returned reference includes a comment with the version tag (e.g., "repo@sha # v1") func GetActionPinWithData(actionRepo, version string, data *WorkflowData) (string, error) { actionPinsLog.Printf("Resolving action pin: repo=%s, version=%s, strict_mode=%t", actionRepo, version, data.StrictMode) @@ -272,17 +272,11 @@ func GetActionPinWithData(actionRepo, version string, data *WorkflowData) (strin } } - // No pin available - if data.StrictMode { - errMsg := fmt.Sprintf("Unable to pin action %s@%s", actionRepo, version) - if data.ActionResolver != nil { - errMsg = fmt.Sprintf("Unable to pin action %s@%s: resolution failed", actionRepo, version) - } - fmt.Fprintln(os.Stderr, console.FormatErrorMessage(errMsg)) - return "", fmt.Errorf("%s", errMsg) - } + // No pin available - emit warning in both strict and non-strict modes + // Note: This used to fail in strict mode, but it's not always possible to resolve pins + // so we now emit a warning and continue compilation in both modes - // In non-strict mode, emit warning and return empty string (unless it's already a SHA) + // In both strict and non-strict mode, emit warning and return empty string (unless it's already a SHA) if isAlreadySHA { // If version is already a SHA and we couldn't find it in pins, return it as-is without warnings actionPinsLog.Printf("SHA %s not found in hardcoded pins, returning as-is", version) diff --git a/pkg/workflow/action_pins_logging_test.go b/pkg/workflow/action_pins_logging_test.go index 1475b95c7b..c55929af10 100644 --- a/pkg/workflow/action_pins_logging_test.go +++ b/pkg/workflow/action_pins_logging_test.go @@ -117,25 +117,30 @@ func TestActionPinResolutionWithMismatchedVersions(t *testing.T) { } } -// TestActionPinResolutionWithStrictMode tests that strict mode prevents version mismatches +// TestActionPinResolutionWithStrictMode tests action pin resolution in strict mode +// Note: Strict mode now emits warnings instead of errors when SHA resolution fails, +// as it's not always possible to resolve pins func TestActionPinResolutionWithStrictMode(t *testing.T) { tests := []struct { - name string - repo string - requestedVer string - expectError bool + name string + repo string + requestedVer string + expectWarning bool + expectSuccess bool }{ { - name: "ai-inference v1 fails in strict mode", - repo: "actions/ai-inference", - requestedVer: "v1", - expectError: true, + name: "ai-inference v1 emits warning in strict mode", + repo: "actions/ai-inference", + requestedVer: "v1", + expectWarning: true, + expectSuccess: false, }, { - name: "checkout v5.0.1 succeeds in strict mode", - repo: "actions/checkout", - requestedVer: "v5.0.1", - expectError: false, + name: "checkout v5.0.1 succeeds in strict mode", + repo: "actions/checkout", + requestedVer: "v5.0.1", + expectWarning: false, + expectSuccess: true, }, } @@ -143,7 +148,7 @@ func TestActionPinResolutionWithStrictMode(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Create a WorkflowData in strict mode without a resolver data := &WorkflowData{ - StrictMode: true, // Strict mode should error on version mismatch + StrictMode: true, ActionResolver: nil, } @@ -159,15 +164,25 @@ func TestActionPinResolutionWithStrictMode(t *testing.T) { var buf bytes.Buffer buf.ReadFrom(r) + stderrOutput := buf.String() - if tt.expectError { - if err == nil { - t.Errorf("Expected error in strict mode for %s@%s, got nil", tt.repo, tt.requestedVer) + // Strict mode should never return an error for resolution failures + if err != nil { + t.Errorf("Unexpected error in strict mode for %s@%s: %v", tt.repo, tt.requestedVer, err) + } + + if tt.expectWarning { + // Should emit warning and return empty result + if !strings.Contains(stderrOutput, "Unable to pin action") { + t.Errorf("Expected warning message for %s@%s, got: %s", tt.repo, tt.requestedVer, stderrOutput) } if result != "" { - t.Errorf("Expected empty result on error, got: %s", result) + t.Errorf("Expected empty result on warning, got: %s", result) } - } else { + } + + if tt.expectSuccess { + // Should not emit warning and return non-empty result if err != nil { t.Errorf("Unexpected error: %v", err) }