Search code examples
godependenciesdependency-managementgo-modules

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.


Solution

  • 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+).