From 7ebdf6c83e316ddd317635106353a0cbb90f2075 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 12 Apr 2026 09:52:14 +0300 Subject: [PATCH 1/8] Auto install Cocoapods when Podfile.lock not exist --- .../technologies/cocoapods/cocoapods.go | 26 ++++++++++++++----- .../technologies/cocoapods/podcommand.go | 14 +++++++--- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go b/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go index 12c5e6a54..b8fe660be 100644 --- a/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go +++ b/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go @@ -2,12 +2,13 @@ package cocoapods import ( "fmt" - "golang.org/x/exp/slices" "os" "path/filepath" "regexp" "strings" + "golang.org/x/exp/slices" + "github.com/jfrog/gofrog/datastructures" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli-security/sca/bom/buildinfo/technologies" @@ -22,6 +23,9 @@ import ( // dependencies. const ( VersionForMainModule = "0.0.0" + + descriptorFileName = "Podfile" + lockFileName = "Podfile.lock" ) var ( @@ -34,7 +38,7 @@ func GetTechDependencyLocation(directDependencyName, directDependencyVersion str var podPositions []*sarif.Location for _, descriptorPath := range descriptorPaths { descriptorPath = filepath.Clean(descriptorPath) - if !strings.HasSuffix(descriptorPath, "Podfile") { + if !strings.HasSuffix(descriptorPath, descriptorFileName) { log.Logger.Warn("Cannot support other files besides Podfile: %s", descriptorPath) continue } @@ -92,7 +96,7 @@ func parsePodLine(line, directDependencyName, directDependencyVersion, descripto func FixTechDependency(dependencyName, dependencyVersion, fixVersion string, descriptorPaths ...string) error { for _, descriptorPath := range descriptorPaths { descriptorPath = filepath.Clean(descriptorPath) - if !strings.HasSuffix(descriptorPath, "Podfile") { + if !strings.HasSuffix(descriptorPath, descriptorFileName) { log.Logger.Warn("Cannot support other files besides Podfile: %s", descriptorPath) continue } @@ -180,11 +184,11 @@ func extractPodsSection(filePath string) (string, error) { } func GetDependenciesData(currentDir string) (string, error) { - _, err := os.Stat(filepath.Join(currentDir, "Podfile.lock")) + _, err := os.Stat(filepath.Join(currentDir, lockFileName)) if err != nil { return "", err } - result, err := extractPodsSection(filepath.Join(currentDir, "Podfile.lock")) + result, err := extractPodsSection(filepath.Join(currentDir, lockFileName)) if err != nil { return "", err } @@ -199,11 +203,21 @@ func BuildDependencyTree(params technologies.BuildInfoBomGeneratorParams) (depen packageName := filepath.Base(currentDir) packageInfo := fmt.Sprintf("%s:%s", packageName, VersionForMainModule) - _, _, err = getPodVersionAndExecPath() + _, podExecPath, err := getPodVersionAndExecPath() if err != nil { err = fmt.Errorf("failed while retrieving pod path: %s", err.Error()) return } + // Check if lock file exists, if not run 'pod install' + lockFilePath := filepath.Join(currentDir, lockFileName) + if _, err := os.Stat(lockFilePath); os.IsNotExist(err) { + if params.SkipAutoInstall { + return nil, nil, fmt.Errorf("Podfile.lock not found and skip auto install is enabled") + } + if _, err = runPodCmd(podExecPath, currentDir, []string{"install"}); err != nil { + return nil, nil, fmt.Errorf("failed to run 'pod install': %w", err) + } + } // Calculate pod dependencies data, err := GetDependenciesData(currentDir) if err != nil { diff --git a/sca/bom/buildinfo/technologies/cocoapods/podcommand.go b/sca/bom/buildinfo/technologies/cocoapods/podcommand.go index a11ed68c8..9f0a57f45 100644 --- a/sca/bom/buildinfo/technologies/cocoapods/podcommand.go +++ b/sca/bom/buildinfo/technologies/cocoapods/podcommand.go @@ -22,15 +22,23 @@ type PodCommand struct { executablePath string } -func getPodVersionAndExecPath() (*version.Version, string, error) { +func getPodExecPath() (string, error) { podExecPath, err := exec.LookPath("pod") if err != nil { - return nil, "", fmt.Errorf("could not find the 'pod' executable in the system PATH %w", err) + return "", fmt.Errorf("could not find the 'pod' executable in the system PATH %w", err) + } + return podExecPath, nil +} + +func getPodVersionAndExecPath() (*version.Version, string, error) { + podExecPath, err := getPodExecPath() + if err != nil { + return nil, "", err } log.Debug("Using pod executable:", podExecPath) versionData, err := runPodCmd(podExecPath, "", []string{"--version"}) if err != nil { - return nil, "", err + return nil, "", fmt.Errorf("failed to get pod version: %w", err) } return version.NewVersion(strings.TrimSpace(string(versionData))), podExecPath, nil } From 282c55cfb2b9e655da194779d302e816724fd112 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 12 Apr 2026 09:59:26 +0300 Subject: [PATCH 2/8] Add tests --- audit_test.go | 12 +++++++++--- .../technologies/cocoapods/cocoapods_test.go | 10 +++++----- .../cocoapods/{ => cocoapods-no-lock-file}/Podfile | 0 .../cocoapods/cocoapods-project/Podfile | 10 ++++++++++ .../cocoapods/{ => cocoapods-project}/Podfile.lock | 0 5 files changed, 24 insertions(+), 8 deletions(-) rename tests/testdata/projects/package-managers/cocoapods/{ => cocoapods-no-lock-file}/Podfile (100%) create mode 100644 tests/testdata/projects/package-managers/cocoapods/cocoapods-project/Podfile rename tests/testdata/projects/package-managers/cocoapods/{ => cocoapods-project}/Podfile.lock (100%) diff --git a/audit_test.go b/audit_test.go index 580a196a3..c84c5cf72 100644 --- a/audit_test.go +++ b/audit_test.go @@ -573,12 +573,18 @@ func testXrayAuditPip(t *testing.T, outFormat format.OutputFormat, requirementsF func TestXrayAuditCocoapods(t *testing.T) { securityIntegrationTestUtils.InitAuditCocoapodsTest(t, scangraph.CocoapodsScanMinXrayVersion) - output := testXrayAuditCocoapods(t, format.Json) + output := testXrayAuditCocoapods(t, format.Json, "cocoapods-project") validations.VerifyJsonResults(t, output, validations.ValidationParams{Total: &validations.TotalCount{Vulnerabilities: 1}}) } -func testXrayAuditCocoapods(t *testing.T, format format.OutputFormat) string { - _, cleanUp := securityTestUtils.CreateTestProjectEnvAndChdir(t, filepath.Join(filepath.FromSlash(securityTests.GetTestResourcesPath()), "projects", "package-managers", "cocoapods")) +func TestXrayAuditCocoapodsNoLockFile(t *testing.T) { + securityIntegrationTestUtils.InitAuditCocoapodsTest(t, scangraph.CocoapodsScanMinXrayVersion) + output := testXrayAuditCocoapods(t, format.Json, "cocoapods-no-lock-file") + validations.VerifyJsonResults(t, output, validations.ValidationParams{Total: &validations.TotalCount{Vulnerabilities: 1}}) +} + +func testXrayAuditCocoapods(t *testing.T, format format.OutputFormat, projectName string) string { + _, cleanUp := securityTestUtils.CreateTestProjectEnvAndChdir(t, filepath.Join(filepath.FromSlash(securityTests.GetTestResourcesPath()), "projects", "package-managers", "cocoapods", projectName)) defer cleanUp() cleanUpHome := securityIntegrationTestUtils.UseTestHomeWithDefaultXrayConfig(t) defer cleanUpHome() diff --git a/sca/bom/buildinfo/technologies/cocoapods/cocoapods_test.go b/sca/bom/buildinfo/technologies/cocoapods/cocoapods_test.go index d495f69f4..6aefe8a3c 100644 --- a/sca/bom/buildinfo/technologies/cocoapods/cocoapods_test.go +++ b/sca/bom/buildinfo/technologies/cocoapods/cocoapods_test.go @@ -20,7 +20,7 @@ import ( func TestBuildCocoapodsDependencyList(t *testing.T) { // Create and change directory to test workspace - _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods")) + _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods", "cocoapods-project")) defer cleanUp() // Run getModulesDependencyTrees @@ -62,7 +62,7 @@ func TestBuildCocoapodsDependencyList(t *testing.T) { } func TestGetTechDependencyLocation(t *testing.T) { - _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods")) + _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods", "cocoapods-project")) defer cleanUp() currentDir, err := coreutils.GetWorkingDirectory() assert.NoError(t, err) @@ -93,7 +93,7 @@ func TestPodLineParseFoundOnlyDependencyName(t *testing.T) { } func TestFixTechDependencySingleLocation(t *testing.T) { - _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods")) + _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods", "cocoapods-project")) defer cleanUp() currentDir, err := coreutils.GetWorkingDirectory() assert.NoError(t, err) @@ -105,7 +105,7 @@ func TestFixTechDependencySingleLocation(t *testing.T) { } func TestFixTechDependencyMultipleLocations(t *testing.T) { - _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods")) + _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods", "cocoapods-project")) defer cleanUp() currentDir, err := coreutils.GetWorkingDirectory() assert.NoError(t, err) @@ -118,7 +118,7 @@ func TestFixTechDependencyMultipleLocations(t *testing.T) { } func TestFixTechDependencyNoLocations(t *testing.T) { - _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods")) + _, cleanUp := technologies.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods", "cocoapods-project")) defer cleanUp() currentDir, err := coreutils.GetWorkingDirectory() assert.NoError(t, err) diff --git a/tests/testdata/projects/package-managers/cocoapods/Podfile b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Podfile similarity index 100% rename from tests/testdata/projects/package-managers/cocoapods/Podfile rename to tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Podfile diff --git a/tests/testdata/projects/package-managers/cocoapods/cocoapods-project/Podfile b/tests/testdata/projects/package-managers/cocoapods/cocoapods-project/Podfile new file mode 100644 index 000000000..ebd2ece07 --- /dev/null +++ b/tests/testdata/projects/package-managers/cocoapods/cocoapods-project/Podfile @@ -0,0 +1,10 @@ +platform :ios, '9.0' + +target 'Test' do + use_frameworks! +pod 'GoogleSignIn', '~> 6.2.4' +pod 'AppAuth', '~> 1.7.5' +pod 'AppAuth', '~> 1.7.5' +pod 'nanopb', '~> 0.3.0' + +end \ No newline at end of file diff --git a/tests/testdata/projects/package-managers/cocoapods/Podfile.lock b/tests/testdata/projects/package-managers/cocoapods/cocoapods-project/Podfile.lock similarity index 100% rename from tests/testdata/projects/package-managers/cocoapods/Podfile.lock rename to tests/testdata/projects/package-managers/cocoapods/cocoapods-project/Podfile.lock From 48e9e600bf2f3e829e8c4d0c62f34cd28170d8e0 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 12 Apr 2026 10:01:13 +0300 Subject: [PATCH 3/8] add hidden flag desc change --- cli/docs/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/docs/flags.go b/cli/docs/flags.go index 07a4149ed..c90be0a47 100644 --- a/cli/docs/flags.go +++ b/cli/docs/flags.go @@ -306,7 +306,7 @@ var flagsMap = map[string]components.Flag{ WorkingDirs: components.NewStringFlag(WorkingDirs, "A comma-separated(,) list of relative working directories, to determine the audit targets locations. If flag isn't provided, a recursive scan is triggered from the root directory of the project."), OutputDir: components.NewStringFlag(OutputDir, "Target directory to save partial results to.", components.SetHiddenStrFlag()), UploadRepoPath: components.NewStringFlag(UploadRepoPath, "Artifactory repository name or path to upload the cyclonedx file to. If no name or path are provided, a local generic repository will be created which will automatically be indexed by Xray.", components.WithStrDefaultValue("import-cdx-scan-results")), - SkipAutoInstall: components.NewBoolFlag(SkipAutoInstall, "Set to true to skip auto-install of dependencies in un-built modules. Currently supported for Yarn and NPM only.", components.SetHiddenBoolFlag()), + SkipAutoInstall: components.NewBoolFlag(SkipAutoInstall, "Set to true to skip auto-install of dependencies in un-built modules. Currently supported only for some package managers.", components.SetHiddenBoolFlag()), AllowPartialResults: components.NewBoolFlag(AllowPartialResults, "Set to true to allow partial results and continuance of the scan in case of certain errors.", components.SetHiddenBoolFlag()), ExclusionsAudit: components.NewStringFlag( Exclusions, From 6a4ae3a57eab10021bb6a90ca6e88877e95237f6 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 12 Apr 2026 11:11:23 +0300 Subject: [PATCH 4/8] only run new tests on MAC, show hint on err --- .github/workflows/test.yml | 3 +++ audit_test.go | 1 + .../technologies/cocoapods/cocoapods.go | 18 ++++++++++++++- .../integration/test_integrationutils.go | 22 +++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 18899ab58..c01dca888 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -94,6 +94,9 @@ jobs: name: "[${{ matrix.os }}] ${{ matrix.suite.name }} Audit Command Integration Tests" needs: Pretest runs-on: ${{ matrix.os }}-latest + env: + LANG: en_US.UTF-8 + LC_ALL: en_US.UTF-8 strategy: fail-fast: false matrix: diff --git a/audit_test.go b/audit_test.go index c84c5cf72..2d4bc62a9 100644 --- a/audit_test.go +++ b/audit_test.go @@ -579,6 +579,7 @@ func TestXrayAuditCocoapods(t *testing.T) { func TestXrayAuditCocoapodsNoLockFile(t *testing.T) { securityIntegrationTestUtils.InitAuditCocoapodsTest(t, scangraph.CocoapodsScanMinXrayVersion) + securityIntegrationTestUtils.RequireCocoaPodsPodInstallEnv(t) output := testXrayAuditCocoapods(t, format.Json, "cocoapods-no-lock-file") validations.VerifyJsonResults(t, output, validations.ValidationParams{Total: &validations.TotalCount{Vulnerabilities: 1}}) } diff --git a/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go b/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go index b8fe660be..fc00fc9b2 100644 --- a/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go +++ b/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go @@ -5,6 +5,7 @@ import ( "os" "path/filepath" "regexp" + "runtime" "strings" "golang.org/x/exp/slices" @@ -195,6 +196,21 @@ func GetDependenciesData(currentDir string) (string, error) { return result, nil } +// podInstallErrWithHint appends guidance when pod failed due to missing or misconfigured Xcode (macOS). +func podInstallErrWithHint(podInstallErr error) error { + if podInstallErr == nil { + return nil + } + msg := podInstallErr.Error() + if runtime.GOOS != "darwin" { + return podInstallErr + } + if !strings.Contains(msg, "xcodebuild") && !strings.Contains(msg, "xcode-select") && !strings.Contains(msg, "CommandLineTools") { + return podInstallErr + } + return fmt.Errorf("%w\nhint: on macOS, CocoaPods often requires full Xcode (not only Command Line Tools). Install Xcode and run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer", podInstallErr) +} + func BuildDependencyTree(params technologies.BuildInfoBomGeneratorParams) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps []string, err error) { currentDir, err := coreutils.GetWorkingDirectory() if err != nil { @@ -215,7 +231,7 @@ func BuildDependencyTree(params technologies.BuildInfoBomGeneratorParams) (depen return nil, nil, fmt.Errorf("Podfile.lock not found and skip auto install is enabled") } if _, err = runPodCmd(podExecPath, currentDir, []string{"install"}); err != nil { - return nil, nil, fmt.Errorf("failed to run 'pod install': %w", err) + return nil, nil, fmt.Errorf("failed to run 'pod install': %w", podInstallErrWithHint(err)) } } // Calculate pod dependencies diff --git a/tests/utils/integration/test_integrationutils.go b/tests/utils/integration/test_integrationutils.go index 6122a92fe..449f6f817 100644 --- a/tests/utils/integration/test_integrationutils.go +++ b/tests/utils/integration/test_integrationutils.go @@ -5,7 +5,10 @@ import ( "fmt" "net/http" "os" + "os/exec" "path/filepath" + "runtime" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -160,6 +163,25 @@ func InitAuditCocoapodsTest(t *testing.T, minVersion string) { testUtils.GetAndValidateXrayVersion(t, minVersion) } +// RequireCocoaPodsPodInstallEnv skips the test unless the host can run `pod install` for typical iOS +// CocoaPods fixtures (macOS with full Xcode selected, not Command Line Tools only). +func RequireCocoaPodsPodInstallEnv(t *testing.T) { + t.Helper() + if runtime.GOOS != "darwin" { + t.Skip("Skipping: CocoaPods auto-install (pod install) for this iOS fixture requires macOS with Xcode.") + return + } + out, err := exec.Command("xcode-select", "-p").CombinedOutput() + path := strings.TrimSpace(string(out)) + if err != nil { + t.Skipf("Skipping: could not run xcode-select -p: %v (%s)", err, path) + return + } + if strings.Contains(path, "CommandLineTools") { + t.Skip("Skipping: full Xcode is required for pod install (active developer dir is Command Line Tools only). Install Xcode and run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer") + } +} + func InitAuditSwiftTest(t *testing.T, minVersion string) { if !*configTests.TestAuditSwift { t.Skip(getSkipTestMsg("Audit command Swift technologies integration", "--test.audit.Swift")) From 50230bc6f2dcd4e3d0e7896fc331e817194911e2 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 12 Apr 2026 11:14:41 +0300 Subject: [PATCH 5/8] fix static --- sca/bom/buildinfo/technologies/cocoapods/cocoapods.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go b/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go index fc00fc9b2..b2810234d 100644 --- a/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go +++ b/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go @@ -228,7 +228,7 @@ func BuildDependencyTree(params technologies.BuildInfoBomGeneratorParams) (depen lockFilePath := filepath.Join(currentDir, lockFileName) if _, err := os.Stat(lockFilePath); os.IsNotExist(err) { if params.SkipAutoInstall { - return nil, nil, fmt.Errorf("Podfile.lock not found and skip auto install is enabled") + return nil, nil, fmt.Errorf("the Podfile.lock file was not found and skip auto install is enabled") } if _, err = runPodCmd(podExecPath, currentDir, []string{"install"}); err != nil { return nil, nil, fmt.Errorf("failed to run 'pod install': %w", podInstallErrWithHint(err)) From d3ceb614d457da748a6bfda72d1100a34ceab7f5 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 12 Apr 2026 11:58:13 +0300 Subject: [PATCH 6/8] try fix tests for all os --- .github/workflows/test.yml | 3 - audit_test.go | 6 +- .../technologies/cocoapods/cocoapods.go | 18 +- .../cocoapods/cocoapods-no-lock-file/Podfile | 1 - .../Test.xcodeproj/project.pbxproj | 311 ++++++++++++++++++ .../Test.xcworkspace/contents.xcworkspacedata | 10 + .../Test/AppDelegate.swift | 16 + .../Test/Base.lproj/LaunchScreen.storyboard | 26 ++ .../cocoapods-no-lock-file/Test/Info.plist | 30 ++ 9 files changed, 399 insertions(+), 22 deletions(-) create mode 100644 tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test.xcodeproj/project.pbxproj create mode 100644 tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test.xcworkspace/contents.xcworkspacedata create mode 100644 tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/AppDelegate.swift create mode 100644 tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/Base.lproj/LaunchScreen.storyboard create mode 100644 tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/Info.plist diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c01dca888..18899ab58 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -94,9 +94,6 @@ jobs: name: "[${{ matrix.os }}] ${{ matrix.suite.name }} Audit Command Integration Tests" needs: Pretest runs-on: ${{ matrix.os }}-latest - env: - LANG: en_US.UTF-8 - LC_ALL: en_US.UTF-8 strategy: fail-fast: false matrix: diff --git a/audit_test.go b/audit_test.go index 2d4bc62a9..04c7d3c00 100644 --- a/audit_test.go +++ b/audit_test.go @@ -30,6 +30,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/common/format" "github.com/jfrog/jfrog-cli-core/v2/common/progressbar" + // "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli-security/sca/bom/buildinfo" @@ -579,7 +580,10 @@ func TestXrayAuditCocoapods(t *testing.T) { func TestXrayAuditCocoapodsNoLockFile(t *testing.T) { securityIntegrationTestUtils.InitAuditCocoapodsTest(t, scangraph.CocoapodsScanMinXrayVersion) - securityIntegrationTestUtils.RequireCocoaPodsPodInstallEnv(t) + // if !coreutils.IsMac() { + // t.Skip("Skipping: CocoaPods auto-install (pod install) for this iOS fixture requires macOS with Xcode.") + // return + // } output := testXrayAuditCocoapods(t, format.Json, "cocoapods-no-lock-file") validations.VerifyJsonResults(t, output, validations.ValidationParams{Total: &validations.TotalCount{Vulnerabilities: 1}}) } diff --git a/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go b/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go index b2810234d..a5ca1ab13 100644 --- a/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go +++ b/sca/bom/buildinfo/technologies/cocoapods/cocoapods.go @@ -5,7 +5,6 @@ import ( "os" "path/filepath" "regexp" - "runtime" "strings" "golang.org/x/exp/slices" @@ -196,21 +195,6 @@ func GetDependenciesData(currentDir string) (string, error) { return result, nil } -// podInstallErrWithHint appends guidance when pod failed due to missing or misconfigured Xcode (macOS). -func podInstallErrWithHint(podInstallErr error) error { - if podInstallErr == nil { - return nil - } - msg := podInstallErr.Error() - if runtime.GOOS != "darwin" { - return podInstallErr - } - if !strings.Contains(msg, "xcodebuild") && !strings.Contains(msg, "xcode-select") && !strings.Contains(msg, "CommandLineTools") { - return podInstallErr - } - return fmt.Errorf("%w\nhint: on macOS, CocoaPods often requires full Xcode (not only Command Line Tools). Install Xcode and run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer", podInstallErr) -} - func BuildDependencyTree(params technologies.BuildInfoBomGeneratorParams) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps []string, err error) { currentDir, err := coreutils.GetWorkingDirectory() if err != nil { @@ -231,7 +215,7 @@ func BuildDependencyTree(params technologies.BuildInfoBomGeneratorParams) (depen return nil, nil, fmt.Errorf("the Podfile.lock file was not found and skip auto install is enabled") } if _, err = runPodCmd(podExecPath, currentDir, []string{"install"}); err != nil { - return nil, nil, fmt.Errorf("failed to run 'pod install': %w", podInstallErrWithHint(err)) + return nil, nil, fmt.Errorf("failed to run 'pod install': %w", err) } } // Calculate pod dependencies diff --git a/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Podfile b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Podfile index ebd2ece07..dc6d9aca2 100644 --- a/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Podfile +++ b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Podfile @@ -4,7 +4,6 @@ target 'Test' do use_frameworks! pod 'GoogleSignIn', '~> 6.2.4' pod 'AppAuth', '~> 1.7.5' -pod 'AppAuth', '~> 1.7.5' pod 'nanopb', '~> 0.3.0' end \ No newline at end of file diff --git a/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test.xcodeproj/project.pbxproj b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test.xcodeproj/project.pbxproj new file mode 100644 index 000000000..e848a3bcc --- /dev/null +++ b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test.xcodeproj/project.pbxproj @@ -0,0 +1,311 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + A10000000000000000000002 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000001 /* AppDelegate.swift */; }; + A10000000000000000000004 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000003 /* LaunchScreen.storyboard */; }; + F51413AF8754363C12A3E256 /* Pods_Test.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CC3B301B576613215FD6C43 /* Pods_Test.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 3CC3B301B576613215FD6C43 /* Pods_Test.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Test.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 47D034BAC64B6AEE5A00F461 /* Pods-Test.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Test.debug.xcconfig"; path = "Target Support Files/Pods-Test/Pods-Test.debug.xcconfig"; sourceTree = ""; }; + A10000000000000000000001 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + A10000000000000000000003 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + A10000000000000000000005 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A10000000000000000000006 /* Test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Test.app; sourceTree = BUILT_PRODUCTS_DIR; }; + CE57013AB51B58F18AC16E73 /* Pods-Test.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Test.release.xcconfig"; path = "Target Support Files/Pods-Test/Pods-Test.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A10000000000000000000020 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F51413AF8754363C12A3E256 /* Pods_Test.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 964F89CB559E387E0CBAC86B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3CC3B301B576613215FD6C43 /* Pods_Test.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + A10000000000000000000030 = { + isa = PBXGroup; + children = ( + A10000000000000000000031 /* Test */, + A10000000000000000000032 /* Products */, + C6686A7500ABCD32985A289C /* Pods */, + 964F89CB559E387E0CBAC86B /* Frameworks */, + ); + sourceTree = ""; + }; + A10000000000000000000031 /* Test */ = { + isa = PBXGroup; + children = ( + A10000000000000000000001 /* AppDelegate.swift */, + A10000000000000000000005 /* Info.plist */, + A10000000000000000000033 /* Base.lproj */, + ); + path = Test; + sourceTree = ""; + }; + A10000000000000000000032 /* Products */ = { + isa = PBXGroup; + children = ( + A10000000000000000000006 /* Test.app */, + ); + name = Products; + sourceTree = ""; + }; + A10000000000000000000033 /* Base.lproj */ = { + isa = PBXGroup; + children = ( + A10000000000000000000003 /* LaunchScreen.storyboard */, + ); + path = Base.lproj; + sourceTree = ""; + }; + C6686A7500ABCD32985A289C /* Pods */ = { + isa = PBXGroup; + children = ( + 47D034BAC64B6AEE5A00F461 /* Pods-Test.debug.xcconfig */, + CE57013AB51B58F18AC16E73 /* Pods-Test.release.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A10000000000000000000040 /* Test */ = { + isa = PBXNativeTarget; + buildConfigurationList = A10000000000000000000050 /* Build configuration list for PBXNativeTarget "Test" */; + buildPhases = ( + B5391DB07AAEF4AD50CE4F29 /* [CP] Check Pods Manifest.lock */, + A10000000000000000000021 /* Sources */, + A10000000000000000000020 /* Frameworks */, + A10000000000000000000022 /* Resources */, + 6D104EA4B5AA9D4569E1F218 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Test; + productName = Test; + productReference = A10000000000000000000006 /* Test.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A10000000000000000000041 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + A10000000000000000000040 = { + CreatedOnToolsVersion = 15.0; + }; + }; + }; + buildConfigurationList = A10000000000000000000051 /* Build configuration list for PBXProject "Test" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A10000000000000000000030; + productRefGroup = A10000000000000000000032 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A10000000000000000000040 /* Test */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A10000000000000000000022 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A10000000000000000000004 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 6D104EA4B5AA9D4569E1F218 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Test/Pods-Test-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Test/Pods-Test-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Test/Pods-Test-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + B5391DB07AAEF4AD50CE4F29 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Test-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A10000000000000000000021 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A10000000000000000000002 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + A10000000000000000000060 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + A10000000000000000000061 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + A10000000000000000000062 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 47D034BAC64B6AEE5A00F461 /* Pods-Test.debug.xcconfig */; + buildSettings = { + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = Test/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A10000000000000000000063 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CE57013AB51B58F18AC16E73 /* Pods-Test.release.xcconfig */; + buildSettings = { + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = Test/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A10000000000000000000050 /* Build configuration list for PBXNativeTarget "Test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A10000000000000000000062 /* Debug */, + A10000000000000000000063 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A10000000000000000000051 /* Build configuration list for PBXProject "Test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A10000000000000000000060 /* Debug */, + A10000000000000000000061 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A10000000000000000000041 /* Project object */; +} diff --git a/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test.xcworkspace/contents.xcworkspacedata b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..1451589a8 --- /dev/null +++ b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/AppDelegate.swift b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/AppDelegate.swift new file mode 100644 index 000000000..c87962629 --- /dev/null +++ b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/AppDelegate.swift @@ -0,0 +1,16 @@ +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + window = UIWindow(frame: UIScreen.main.bounds) + window?.rootViewController = UIViewController() + window?.makeKeyAndVisible() + return true + } +} diff --git a/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/Base.lproj/LaunchScreen.storyboard b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..5ee718d3f --- /dev/null +++ b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/Info.plist b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/Info.plist new file mode 100644 index 000000000..44cf433e6 --- /dev/null +++ b/tests/testdata/projects/package-managers/cocoapods/cocoapods-no-lock-file/Test/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + + From 88ead382a7356d8e7edfb94ce338101a344ecab4 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 12 Apr 2026 12:16:49 +0300 Subject: [PATCH 7/8] fix tests --- audit_test.go | 12 +++++----- git_test.go | 6 ++--- .../integration/test_integrationutils.go | 22 ------------------- 3 files changed, 9 insertions(+), 31 deletions(-) diff --git a/audit_test.go b/audit_test.go index 04c7d3c00..940fa5be4 100644 --- a/audit_test.go +++ b/audit_test.go @@ -30,7 +30,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/common/format" "github.com/jfrog/jfrog-cli-core/v2/common/progressbar" - // "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli-security/sca/bom/buildinfo" @@ -580,11 +580,11 @@ func TestXrayAuditCocoapods(t *testing.T) { func TestXrayAuditCocoapodsNoLockFile(t *testing.T) { securityIntegrationTestUtils.InitAuditCocoapodsTest(t, scangraph.CocoapodsScanMinXrayVersion) - // if !coreutils.IsMac() { - // t.Skip("Skipping: CocoaPods auto-install (pod install) for this iOS fixture requires macOS with Xcode.") - // return - // } - output := testXrayAuditCocoapods(t, format.Json, "cocoapods-no-lock-file") + if coreutils.IsWindows() { + t.Skip("Skipping: CocoaPods auto-install (pod install) requires macOS/Linux with Xcode.") + return + } + output := testXrayAuditCocoapods(t, format.SimpleJson, "cocoapods-no-lock-file") validations.VerifyJsonResults(t, output, validations.ValidationParams{Total: &validations.TotalCount{Vulnerabilities: 1}}) } diff --git a/git_test.go b/git_test.go index cd03a42df..0f966eecb 100644 --- a/git_test.go +++ b/git_test.go @@ -272,7 +272,7 @@ func TestGitAuditJasSkipNotApplicableCvesViolations(t *testing.T) { validations.ValidationParams{ Violations: &validations.ViolationCount{ ValidateScan: &validations.ScanCount{Sca: 11, Sast: 2, Secrets: 2}, - ValidateApplicabilityStatus: &validations.ApplicabilityStatusCount{NotApplicable: 5, NotCovered: 6, Inactive: 2}, + ValidateApplicabilityStatus: &validations.ApplicabilityStatusCount{NotApplicable: 6, NotCovered: 5, Inactive: 2}, }, ExactResultsMatch: true, }, @@ -299,8 +299,8 @@ func TestGitAuditJasSkipNotApplicableCvesViolations(t *testing.T) { xrayVersion, xscVersion, "", validations.ValidationParams{ Violations: &validations.ViolationCount{ - ValidateScan: &validations.ScanCount{Sca: 6, Sast: 2, Secrets: 2}, - ValidateApplicabilityStatus: &validations.ApplicabilityStatusCount{NotCovered: 6, Inactive: 2}, + ValidateScan: &validations.ScanCount{Sca: 5, Sast: 2, Secrets: 2}, + ValidateApplicabilityStatus: &validations.ApplicabilityStatusCount{NotCovered: 5, Inactive: 2}, }, ExactResultsMatch: true, }, diff --git a/tests/utils/integration/test_integrationutils.go b/tests/utils/integration/test_integrationutils.go index 449f6f817..6122a92fe 100644 --- a/tests/utils/integration/test_integrationutils.go +++ b/tests/utils/integration/test_integrationutils.go @@ -5,10 +5,7 @@ import ( "fmt" "net/http" "os" - "os/exec" "path/filepath" - "runtime" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -163,25 +160,6 @@ func InitAuditCocoapodsTest(t *testing.T, minVersion string) { testUtils.GetAndValidateXrayVersion(t, minVersion) } -// RequireCocoaPodsPodInstallEnv skips the test unless the host can run `pod install` for typical iOS -// CocoaPods fixtures (macOS with full Xcode selected, not Command Line Tools only). -func RequireCocoaPodsPodInstallEnv(t *testing.T) { - t.Helper() - if runtime.GOOS != "darwin" { - t.Skip("Skipping: CocoaPods auto-install (pod install) for this iOS fixture requires macOS with Xcode.") - return - } - out, err := exec.Command("xcode-select", "-p").CombinedOutput() - path := strings.TrimSpace(string(out)) - if err != nil { - t.Skipf("Skipping: could not run xcode-select -p: %v (%s)", err, path) - return - } - if strings.Contains(path, "CommandLineTools") { - t.Skip("Skipping: full Xcode is required for pod install (active developer dir is Command Line Tools only). Install Xcode and run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer") - } -} - func InitAuditSwiftTest(t *testing.T, minVersion string) { if !*configTests.TestAuditSwift { t.Skip(getSkipTestMsg("Audit command Swift technologies integration", "--test.audit.Swift")) From 56a1f0773c712174c8860371f766de7d06cc4e30 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 12 Apr 2026 12:49:12 +0300 Subject: [PATCH 8/8] verify right format --- audit_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audit_test.go b/audit_test.go index 940fa5be4..5ed4ac687 100644 --- a/audit_test.go +++ b/audit_test.go @@ -585,7 +585,7 @@ func TestXrayAuditCocoapodsNoLockFile(t *testing.T) { return } output := testXrayAuditCocoapods(t, format.SimpleJson, "cocoapods-no-lock-file") - validations.VerifyJsonResults(t, output, validations.ValidationParams{Total: &validations.TotalCount{Vulnerabilities: 1}}) + validations.VerifySimpleJsonResults(t, output, validations.ValidationParams{Total: &validations.TotalCount{Vulnerabilities: 1}}) } func testXrayAuditCocoapods(t *testing.T, format format.OutputFormat, projectName string) string {