diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9cbf60f7..7e0a0cc4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -61,9 +61,7 @@ jobs: - name: Setup Poetry run: python -m pip install poetry - name: Setup Conan - run: | - python -m pip install conan - conan profile detect + run: python -m pip install conan - name: Setup Gradle uses: gradle/gradle-build-action@v2 with: diff --git a/commands/audit/sca/conan/conan.go b/commands/audit/sca/conan/conan.go index 51a682eb..71afe49b 100644 --- a/commands/audit/sca/conan/conan.go +++ b/commands/audit/sca/conan/conan.go @@ -6,6 +6,7 @@ import ( "fmt" "os/exec" + "github.com/jfrog/gofrog/datastructures" "github.com/jfrog/gofrog/io" "github.com/jfrog/gofrog/version" "github.com/jfrog/jfrog-client-go/utils/errorutils" @@ -95,6 +96,17 @@ type conanGraphOutput struct { } `json:"graph"` } +func calculateUniqueDependencies(nodes map[string]conanRef) []string { + uniqueDepsSet := datastructures.MakeSet[string]() + for id, dep := range nodes { + if id == "0" { // ignore the root node + continue + } + uniqueDepsSet.Add(dep.NodeName()) + } + return uniqueDepsSet.ToSlice() +} + func calculateDependencies(executablePath, workingDir string, params utils.AuditParams) (dependencyTrees []*xrayUtils.GraphNode, uniqueDeps []string, err error) { graphInfo := append([]string{"info", ".", "--format=json"}, params.Args()...) conanGraphInfoContent, err := getConanCmd(executablePath, workingDir, "graph", graphInfo...).RunWithOutput() @@ -114,12 +126,7 @@ func calculateDependencies(executablePath, workingDir string, params utils.Audit } dependencyTrees = append(dependencyTrees, rootNode) - for id, dep := range output.Graph.Nodes { - if id == "0" { - continue - } - uniqueDeps = append(uniqueDeps, dep.NodeName()) - } + uniqueDeps = calculateUniqueDependencies(output.Graph.Nodes) return } diff --git a/commands/audit/sca/conan/conan_test.go b/commands/audit/sca/conan/conan_test.go index 0ed7bfa5..d21f0a9e 100644 --- a/commands/audit/sca/conan/conan_test.go +++ b/commands/audit/sca/conan/conan_test.go @@ -22,6 +22,7 @@ var expectedResult = &xrayUtils.GraphNode{ {Id: "conan://meson:1.4.1", Nodes: []*xrayUtils.GraphNode{{Id: "conan://ninja:1.11.1"}}}, }, } +var expectedUniqueDeps = []string{"conan://openssl:3.0.9", "conan://zlib:1.3.1", "conan://meson:1.4.1", "conan://ninja:1.11.1"} func TestParseConanDependencyTree(t *testing.T) { _, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("other", "conan")) @@ -41,10 +42,10 @@ func TestParseConanDependencyTree(t *testing.T) { } func TestBuildDependencyTree(t *testing.T) { - _, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "conan")) + dir, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "conan")) defer cleanUp() - expectedUniqueDeps := []string{"conan://openssl:3.0.9", "conan://zlib:1.3.1", "conan://meson:1.4.1", "conan://ninja:1.11.1"} params := &utils.AuditBasicParams{} + params.SetConanProfile(filepath.Join(dir, "profile")) graph, uniqueDeps, err := BuildDependencyTree(params) assert.NoError(t, err) if !tests.CompareTree(expectedResult, graph[0]) { @@ -52,3 +53,17 @@ func TestBuildDependencyTree(t *testing.T) { } assert.ElementsMatch(t, uniqueDeps, expectedUniqueDeps, "First is actual, Second is Expected") } + +func TestCalculateUniqueDeps(t *testing.T) { + input := map[string]conanRef{ + "0": {Name: "root node", Version: "please ignore"}, // root node, should be removed + "1": {Name: "zlib", Version: "1.3.1"}, + "2": {Name: "openssl", Version: "3.0.9"}, + "3": {Name: "meson", Version: "1.4.1"}, + "4": {Name: "ninja", Version: "1.11.1"}, + "5": {Name: "openssl", Version: "3.0.9"}, // duplicate, should be removed + } + + uniqueDeps := calculateUniqueDependencies(input) + assert.ElementsMatch(t, uniqueDeps, expectedUniqueDeps, "First is actual, Second is Expected") +} diff --git a/tests/testdata/projects/package-managers/conan/profile b/tests/testdata/projects/package-managers/conan/profile new file mode 100644 index 00000000..86745c5f --- /dev/null +++ b/tests/testdata/projects/package-managers/conan/profile @@ -0,0 +1,8 @@ +[settings] +arch=x86_64 +build_type=Release +compiler=gcc +compiler.cppstd=gnu17 +compiler.libcxx=libstdc++11 +compiler.version=11 +os=Linux \ No newline at end of file diff --git a/utils/auditbasicparams.go b/utils/auditbasicparams.go index 80b5eb89..df3a23fd 100644 --- a/utils/auditbasicparams.go +++ b/utils/auditbasicparams.go @@ -186,6 +186,11 @@ func (abp *AuditBasicParams) SetNpmScope(depType string) *AuditBasicParams { return abp } +func (abp *AuditBasicParams) SetConanProfile(file string) *AuditBasicParams { + abp.args = append(abp.args, "--profile:build", file) + return abp +} + func (abp *AuditBasicParams) OutputFormat() format.OutputFormat { return abp.outputFormat }