-
-
Notifications
You must be signed in to change notification settings - Fork 247
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
add a check for a 'replace' directive in a 'go.mod' for Go modules #276
Comments
The implementation could be fairly straightfoward.
The JSON output corresponds to these Go types:
To check if there are any Here is an example JSON output (in this case, showing there are no
Alternatively, github.com/rogpeppe/go-internal/modfile is an importable go package that can parse a go.mod file. |
This issue is stale because it has been open 60 days with no activity. |
For us, it will be nice to have:
|
Summary
In short, while a
replace
directive in ago.mod
might be a necessary evil or might be needed for a temporary workaround, I think it is fair to say that it is always cleaner to not have areplace
, and hence very worthwhile to drop the "Go Report Card" score if there is areplace
found in a Go module.Background
Some background on
replace
is available in this FAQ from the Modules wiki.Some examples of why a project might have a
replace
when they are publishing an open source module with a "Go Report Card" badge:It might be colossal mistake where someone accidentally checked in a temporary
replace
.For example, the author of module
foo
might have accidentally checked in ago.mod
with something likereplace bar => /user/Gopher42/my/local/bar
, which tells thego
command to use a local copy of thebar
module, but would mean everyone downloading and buildingfoo
via something likego build .
would be broken (because that localbar
would not be there, unless you happen to be userGopher42
in this example).There is a general issue that two modules can't automatically find each other if you are working on more than one module at the same time. (e.g., skim cmd/go: support simultaneous edits of interdependent modules golang/go#27542 or cmd/go: allow go.mod.local to contain replace/exclude lines golang/go#26640 for 30 sec to get a sense of the issue, if interested). The development time solution is often to introduce a
replace
directive (e.g., as explained in the FAQ above), but then you need to remember to remove that development timereplace
when you are checking in or when you are publishing your module. It can be scripted (e.g., viagit
hooks), but in practice people make mistakes here.It might be a significant mistake if a library module author incorrectly thinks library consumers will respect the
replace
There is a nuance in modules that a library module can have a
replace
, but thatreplace
only applies if you are runninggo build
orgo test
from inside the library itself, and that samereplace
is ignored if you are importing that library in a separate module (say, the top-level binary). Not everyone knows this, however, so some library authors in practice include areplace
without knowing it will be ignored in the top-level binary.The "Build Control" section in the official proposal has a discussion about this, including:
It might be a deliberate choice by a library author, but a confusing one
A more sophisticated module library author might know that a
replace
is ignored in a consuming top-level module, and might in theory purposefully include areplace
in their own library (e.g., maybe to help with local testing) under the knowledge that it won't impact a consumer, but then that would be confusing for a consumer to see thatreplace
, and hence it could be reasonable to view that as not a great practice.It might be an indication that a specific version of a dependency is being pinned for a binary
It might be an indication that a fork of a dependency is in use for a binary
For 4. or 5. -- that might be "OK", but it is at least notable and not as "clean" as if there was no replace. More importantly,it helps the overall ecosystem if any temporary forks (e.g., to temporarily fix a bug) are eventually merged upstream, and similarly if any upstream bugs are fixed upstream so that the version of a dependency no longer needs to be pinned to work around that upstream bug. The go report card could help nudge people in that direction and/or remind them to nudge upstream, etc., and once the issue is resolved upstream, the
replace
can then be removed and return to a "cleaner" state of noreplace
directives.Recommendation
I think if you put all all that together, it is at a minimum a fairly notable thing that a project uses a
replace
regardless of why, and at worst it is a major mistake. Even if it is purposeful, it is is cleaner for the overall ecosystem if any temporarily necessaryreplace
is later removed.I would recommend starting very simple and not trying to differentiate between different cases above, and the logic could just be something like -- if there is any
replace
found, drop the score. Given it is at least eyebrow-raising and potentially a big mistake, I would recommend moving the score enough to always visibly drop a partial grade (e.g., move an "A+" to an "A", or a "B" to a "B-", etc.).Most of the same issues also apply to the
exclude
directive, butexclude
is not used as frequently asreplace
, so could be very reasonable to start just withreplace
, or alternatively could have the same basic scoring logic forexclude
as well.The text was updated successfully, but these errors were encountered: