Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: cmd/go: support local directive in go.mod #51779

Open
liubog2008 opened this issue Mar 18, 2022 · 6 comments
Open

proposal: cmd/go: support local directive in go.mod #51779

liubog2008 opened this issue Mar 18, 2022 · 6 comments

Comments

@liubog2008
Copy link

Why

One go.mod is not reasonable for monorepo

For example, we have a repo with structure as below

- cmd
- pkg
  - server
  - client
  - api
- go.mod
- go.sum

If the repo consumers hope to import client and api pkg, they have to import the whole module and indirectly import dependencies of server pkg.

Only three choices for this situation.

  1. New git repo for client and api
  2. New go.mod file and new git tag for client and api, e.g client/v0.1.0
  3. New go.mod file and use replace directive

For choice 1, we have to manage more git repos and submit more PRs for a feature.
For choice 2, we have to tag api and client, then change the go.mod version and tag main module.
For choice 3, replace directive has some problems now.

replace directive for monorepo

The below lines are used in many go.mod files.

replace github.com/xxx/yyy/api => ./api
replace github.com/xxx/yyy/client => ./client

However, go install is not worked if replace directive exists(See #44840, #40276)

Another problem of replace is if client also imports api and replaces it. consumers have to use replace in go.mod again to ensure api module's version.

require (
    github.com/xxx/yyy/api v0.0.1
    github.com/xxx/yyy/client v0.0.1
)

# If omit this line, the below error will be thrown
# go: github.com/xxx/yyy/client@v0.0.1 requires
#.     github.com/xxx/yyy/api@v0.0.0-00010101000000-000000000000: invalid version: unknown revision 000000000000
replace github.com/xxx/yyy/api => github.com/xxx/yyy/api v0.0.1

Design

  1. Add local directive for all modules which are imported from same git repo.
  2. Use same version as the main module to import local modules.

In main module

module github.com/xxx/yyy

local (
    github.com/xxx/yyy/client
    github.com/xxx/yyy/api
)

in client module

module github.com/xxx/yyy/client

local (
    github.com/xxx/yyy/api
)

in consumer module

module github.com/aaa/bbb

require (
    github.com/xxx/yyy/client v0.0.1
    github.com/xxx/yyy/api v0.0.1
)

go mod graph for consumer

github.com/aaa/bbb github.com/xxx/yyy/client@v0.0.1
github.com/aaa/bbb github.com/xxx/yyy/api@v0.0.1
github.com/xxx/yyy/client@v0.0.1 github.com/xxx/yyy/api@v0.0.1

Compatibility

No compatibility problem

Alternatives

  1. Just omit version in require as the local module. (also good to me)
  2. Change the behavior of replace directive.
@gopherbot gopherbot added this to the Proposal milestone Mar 18, 2022
@ianlancetaylor ianlancetaylor added this to Incoming in Proposals (old) Mar 18, 2022
@ianlancetaylor
Copy link
Contributor

CC @bcmills

@seankhliao seankhliao changed the title proposal: x/mod: support local directive in go.mod proposal: cmd/go: support local directive in go.mod Mar 18, 2022
@beoran
Copy link

beoran commented Mar 18, 2022

Go 1.18 has workspaces. Could they be used in your use case?

@mvdan
Copy link
Member

mvdan commented Mar 18, 2022

Also note that this is otherwise a duplicate of #26640.

@liubog2008
Copy link
Author

Go 1.18 has workspaces. Could they be used in your use case?

go.work seems a local workspace and not be pushed to remote repo in best practice? If I split monorepo to three git repos, go.work can be easily used for me to modify my code.

@liubog2008
Copy link
Author

Also note that this is otherwise a duplicate of #26640.

I feel they are not duplicated.

@bandesz
Copy link

bandesz commented Aug 3, 2022

I would like to add a further issue to consider here.

We have a similar project structure, but we also use vendoring in the root project. Using the example from the description, this means the pkg/client module is copied to vendor (but with full module path of course), and whenever you make a change to pkg/client during development, you have to run go mod vendor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Incoming
Development

No branches or pull requests

7 participants