Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve conflicting go module dependencies when a top-level module and one of its sub-modules are separately imported as separate versions?

I have two dependencies in my project.

go.mod:

module github.com/test-org/test-repo

go 1.12

require (
    github.com/foo/bar v1.0.0
    github.com/raz/mataz v1.0.0
)

After running go mod download, those two dependencies result in two different versions of a github.com/shared/dependency to be downloaded. The interesting thing is that the github.com/shared/dependency contains sub-modules, e.g.:

dependency
  -- go.mod
  -- api
      -- go.mod

Inspecting the downloaded modules shows two versions are downloaded to my local machine:

ls ${GOPATH}/pkg/mod/github.com/shared:

[dir] dependency    [dir] [email protected]

ls ${GOPATH}/pkg/mod/github.com/shared/dependency:

[dir] [email protected]

Looking at the contents of these directories:

${GOPATH}/pkg/mod/github.com/shared/[email protected]:

The file contents of the whole repo in v1.1.0, including the api folder with its own go.mod file.

${GOPATH}/pkg/mod/github.com/shared/dependency/[email protected]:

The file contents of the api folder of the repo in v1.2.0, including the go.mod file.


Finally, I have a .go file in my test-repo with the following setup:

package test-package

import (
    "github.com/foo/bar"
)

func MyFunc() {...bar.NewBar()...}

When I try to run a test of MyFunc (that exists elsewhere), I get an unknown import path...ambiguous import... error message. e.g.

go test github.com/test-org/test-repo/test-package -test.run=TestMyFunc -v:

unknown import path "github.com/shared/dependency/api": ambiguous import: found github.com/shared/dependency/api in multiple modules:
    github.com/shared/dependency v1.1.0 (${GOPATH}/pkg/mod/github.com/shared/[email protected]/api)
    github.com/shared/dependency v1.2.0 (${GOPATH}/pkg/mod/github.com/shared/dependency/[email protected])

The error points to the import line of the .go file importing github.com/shared/dependency/api in the github.com/foo/bar repo. It doesn't know which api to choose in my local ${GOPATH}/pkg/mod folder, given the two versions available:

  1. ${GOPATH}/pkg/mod/github.com/shared/[email protected]/api
  2. ${GOPATH}/pkg/mod/github.com/shared/dependency/[email protected]

Is there any way that I can make that go test call work (solve the dependency conflicts)? Neither of my two dependencies explicitly call out downloading the full shared/[email protected], but for some reason it gets pulled in. If that weren't there, it would seemingly fix the issue.

like image 823
N N Avatar asked Sep 16 '19 07:09

N N


People also ask

What is a dependency conflict?

Dependency conflicts occur when different Python packages have the same dependency, but depend on different and incompatible versions of that shared package. Because only a single version of a dependency is permitted in any project's environment, finding a compatible solution can be difficult.

Where are Golang dependencies stored?

As we have learned in Go installation tutorial, standard Go packages like located inside GOROOT directory (where Go is installed). Other project-level dependencies are stored inside GOPATH.

Is Gopath required with Go modules?

With Go modules, you do not need to keep your project files under GOPATH and can easily manage dependencies in your project. Read more about Go modules at go.

What is Go mod tidy?

go mod tidy ensures that the go. mod file matches the source code in the module. It adds any missing module requirements necessary to build the current module's packages and dependencies, if there are some not used dependencies go mod tidy will remove those from go.


1 Answers

The issue turned out to be that one of the dependencies was referencing a version of the github.com/shared/dependency/api that was pre-go-modules.

This caused the go tooling to have a module reference to the github.com/shared/dependency/api sub-module, but also a black box import of the entire github.com/shared/dependency repo for the pre-go-modules version. In this example, it would mean that v1.2.0 had go modules (had a go.mod file), and v1.1.0 did not.

Adding the following line to my go.mod file was able to fix the issue, and this solution worked with multiple dependencies I had with such conflicts:

replace (
    github.com/shared/dependency => github.com/shared/dependency v1.2.0
)

Note that this solution only works because we are forcing references to the shared dependency to use go-module-enabled versions (v1.2.0+).

like image 159
N N Avatar answered Sep 23 '22 11:09

N N