-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
cmd/go: go.work: go build
requires versioned replace directive when replacing a used module with a local path
#54264
Comments
workspace
|
Same problem for me. Frankly I'm surprised, most of the go tooling is generally high quality, but |
In general we would expect modules that are included in a workspace to not also require a |
The reason I was looking to do this was to handle an environment where I cannot directly connect to the upstream git repo. I'm seeing go execute I can remove the |
don't know where you came up w/ that long versioning string, fyi:
to note that you shouldn't need the |
It appears to do that by running |
I am having the same problems in 1.19. Once I put in go.work everything goes haywire.
Thinking about trying the latest go to see if the behavior changes. |
As said above, since the beginning of go workspaces, and at least up to current Go 1.21.5 ; Tree structure :
CONTENT of module-A (no dependencies) :
CONTENT of mains-project (depends on moduleA) :
So, they are manually-crafted files, and the repos/gitlab doesn't event exists, go.mod.sum are missing, the v0.9.9 doesn't really exists, etc etc... but it reflects the SAME PROBLEM than really existing private git-cloned repos. Inside
So the full text above is not really interesting. The MAIN POINT is that go it trying to I would also like to specify, in aim to alleviate unneedy discussions, that for a real scenarios, my So, for the described scenario above, using only This WONT happen for even-dummy-er testbed scenarios where you would omit this from
Indeed, if you only use local-only never-git-pushed tagless/unversionned dependencies, the problem would not occur. If for some reasons (which seems valid to me), your ----8<----8<----8<----8<----8<----8<----8<----8< I severely miss a simple method to having this workflow working seamlessly :
I mean, all the above works seamlessly, except for me, the dev, which needs to constantly jungle with some go.work, use, and replace directives. This just doesn't work seamlessly, go.work ----8<----8<----8<----8<----8<----8<----8<----8< To me, it feels like the Googling around on "go.work", "git ls-remote", "use", "ignored", "without replace", etc... yields a lot of results of confused people which seems to have a bad time figuring out a workflow which would suits to them. I would just like a simple way to :
That's just hard in Go, having to constantly jungle with replaces directives. I cannot seem to have a fixed-once-figured-out-do-not-constantly-modify-replaces set of go.mod/go.work files where I would just No, Go is willing to |
I'd like to chime in too with the same issue and an additional potential bug (not sure if I should open a separate issue for that though). I felt it's most appropriate in this issue, but it's certainly also related to #50750 . FTR we're using Go 1.21. In our monorepo we gitignored
A local Go workspace enabled us to efficiently make updates to multiple modules in one change and test them without having to update versions. Push to CI/CD however, requires an update to the versions (e.g. if module To avoid this, we decided to add
Removing go.work for this change in CI fixed the issue. Repository with demo: https://github.com/mweibel/gomodreplace/tree/fail (please note, this is only a partial reproduction because we have an additional issue in our monorepo due to the fact that we are on an on-premise GitLab instance without a go module proxy in front). The issue with this approach is visible when running
Because I certainly might be doing something wrong and would love to get some help/documentation if that's the case. Thank you! |
There are a couple of solutions we could consider here:
(CC @matloob @samthanawalla) |
Truly, this behavior makes go.work useless in a mono repo, and contradicts the documentation. Spent half the day trying to use the feature as documented, and getting progressively more frustrated. Found this thread and realized I should just abandon the effort, and go back to a maze of replace directives in the individual modules. Could we at least ask for something in the documentation that clarifies what's required to make workspaces functional? That is to say, at least describe the behavior as it is to save this kind of frustration for others? |
@rselph-tibco Could you clarify what part of the documentation is inaccurate? I'd like to correct it to clarify that this isn't supported. Workspaces were not built to support modules that can't be built outside a workspace context. |
Hi @matloob, this issue isn't about modules that don't work outside of a workspace. It's about handling them reasonably in more complex situations such as a mono-repo. The workspace doc is pretty short and sweet on the subject of the replace directive:
But the behavior discussed in this issue is an exception to this. Following the documentation in this situation leads to difficult to understand errors that seem to be in direct contradiction to the doc. For instance, I have a number of modules in one repo that build using replace directives pointing to another part of the source tree. They build fine outside of a workspace. The doc promises that I could instead have a single replace directive in my go.work that would avoid many different relative replace directives in the various go.mod files. But that doesn't work due to the issues outlined here. |
@rselph-tibco Okay, I can see a documentation problem: we should more clearly document that a workspace module can not be replaced using a replace directive in a go.work file (replacing at specific versions is supported for the purposes of tweaking the dependency graph, but should almost never need to be used. blanket replaces that apply to all versions are explicitly disallowed). The reason for this is that it's not clear what the behavior should be if a workspace module (which is at the root at the module graph) is replaced with a different module. (There is an analogue to this in single module mode: There is also weird behavior in a single-module context if that module replaces itself. We don't report an error in that case but we probably should.) So I can add a line to the modules reference explicitly clarifying that workspaces can not be replaced using wildcard replaces. But I don't think that solves your core problem: "handling [modules] reasonably in more complex situations such as a mono-repo". I might still be misunderstanding this, so bear with me, but it seems to me that the main case I've seen in this bug for replacing a workspace module in a go.work file is to circumvent fetching the module when it appears as a dependency of other workspace modules. My understanding of when this would happen (please correct me if I'm wrong here) is because the module is not able to be fetched either using git or a local module proxy. If that is the case the module would not be buildable outside of a workspace context (unless it replaces all of its dependencies!). Does that sound right to you? If not, I would like to hear more about your use case. |
One use case I have—which I think is similar to the one @rselph-tibco described—is when I have a series of modules that depend on each other, and I want to test a change to a module and those that depend on it locally, before pushing everything to a central Git server. It'd be useful in that case to check out the module and a handful of packages that depend on it into a "workspace," and enforce that everything in that workspace should always use the local copy, without having to edit X individual go.mod files. Using the present system, I've missed a file when adding my replace directives, and wondered why my change seemingly had no effect. I've also frequently forgotten to remove the temporary "replace" directive before pushing up my changes. Having a mechanism (go.work replace or otherwise) that took precedence over go.mod would make this workflow much easier and less error-prone. |
@dpifke After you push your modules to a central git server, is it possible to build the modules individually outside of a workspace? That is, are the modules able to be downloaded from git or a private proxy? If so, then your use case falls squarely under the set of use cases that |
Edit: re-reading the docs, I think it's clear this scenario is supposed to work. It's been almost two years since I subscribed to this bug, and my recollection is that |
@dpifke If I understand your use case directly it should work. What doesn't work is replacing the workspace modules (the modules that are |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Given the following workspace structure:
With the following
go.work
:Build
realdeal
which depends onfubar
:What did you expect to see?
Nothing, the build should succeed
What did you see instead?
Found workaround
The only way I've found to fix this is to update the
go.work
to be as follow:This is not needed if a workspace is not used. It also seems to contradict the example from the documentation (https://go.dev/ref/mod#workspaces):
The text was updated successfully, but these errors were encountered: