-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: track tool dependencies in go.mod #48429
Comments
I like this, I find it annoying to use the If this proposal moves forward, where does the dependency go in the |
Good question! I'm not so familiar with the reasoning behind the multiple blocks... something to do with lazy loading? I'd defer to those with more experience in this area |
Personally, I think #42088 is already a pretty good solution. With it, one can write
Similarly, Another big advantage is that you can pick specific versions of tools, and they won't interfere with your main |
The only downside to #42088 is that, if you repeat the same |
Or |
Oh interesting, thanks @mvdan I wasn't aware of that solution. 🤔 A few concerns immediately come to mind...
|
Also this |
In module mode, |
It certainly warrants a mention. I'm not sure we should bless it as the only best practice, though, because there can be legitimate reasons for versioning, downloading, and running tools some other way. Perhaps some of your tools aren't written in Go, such as protoc, so you use a "tool bundler" that's entirely separate to Go. Or perhaps you do need your tools to share the same MVS graph with your main module for proper compatibility, so you want them to share a |
Gotta say though...
|
So even with the |
Also worth noting: codegen tools like gqlgen and protobuf are often comprised of a generator command and a runtime, both of which typically need to be versioned in lock-step. This proposal solves that case rather neatly, allowing go.mod to manage both generator and runtime versions. |
We used to do that. Then people would have that replicated across different files and the version wouldn't always match, and we wanted to automate tool updating, so we figured that migrating to Again, |
@jayconrod has previously suggested something similar, using a new directive (perhaps Personally, I prefer the approach of adding a new directive — today we do treat requirements with A new |
@bcmills would such tool requirements be part of the same MVS module graph? |
The In particular:
|
Or |
I like this proposal. I've had something similar in my drafts folder for a while. @bcmills touched on the main difference.
I don't think |
Yeah I like the A |
Or have I got that wrong? Is sharing indirect dependencies between tools and other dependencies a desirable feature? |
Right. The go command reports errors for unknown directives in the main module's go.mod file, but it ignores unknown directives in dependencies' go.mod files. So everyone working on a module that used this would need to upgrade to a version of Go that supports it (same as most other new features), but their users would be unaffected.
My suggestion is to have If you don't want to mix tool and library dependencies in |
Yep that makes a lot of sense @jayconrod |
This proposal has been added to the active column of the proposals project |
@jayconrod Did you want to write up the |
For #48429 Change-Id: I1a7bd8ffddbc65e3b687dc1d40f3853702e1b5dc Reviewed-on: https://go-review.googlesource.com/c/go/+/521958 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Sam Thanawalla <samthanawalla@google.com> Reviewed-by: Michael Matloob <matloob@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org>
Nice to see this being worked on. |
Change https://go.dev/cl/614555 mentions this issue: |
Allowing relative paths in `go.mod` introduced an inconsistency as we do not allow relative package paths anywhere else. For #48429 Change-Id: I5ef88aec4fe35f7e94a0cf6288e94099f3ca7a0e Reviewed-on: https://go-review.googlesource.com/c/go/+/614555 Reviewed-by: Sam Thanawalla <samthanawalla@google.com> Reviewed-by: Michael Matloob <matloob@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Packages referenced by tool lines in go.mod files will now be included in the module graph for the new "tool" package pattern and the "all" package pattern. For #48429 Change-Id: I128f6a50880814bd5395674426c9a7ee2ddc19bf Reviewed-on: https://go-review.googlesource.com/c/go/+/521959 Reviewed-by: Carlos Amedee <carlos@golang.org> Reviewed-by: Michael Matloob <matloob@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Running `go get -tool example.com/m1` will add a tool line to your mod file and add any missing dependencies. Running `go get -tool example.com/m1@none` will drop the tool line from your mod file. For #48429 Change-Id: I07b4776f1f55eff588d08cb6649d94cc42a729d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/563175 Reviewed-by: Michael Matloob <matloob@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Sam Thanawalla <samthanawalla@google.com>
Reminder that buildtime dependencies installed via out of band methods are likely missing from SBOM's sent to SCA tools. govulncheck, Snyk, Dependabot, etc. look primarily in A few container SCA tools like Docker Scout, Red Hat Quay Container Security Operator, Snyk Container may happen to match CVE's for vulnerable buildtime Go dependency tools. But only for Go tools installed via OS package managers, and likely only for Go tools that are not removed from the final image using modern, multi stage images. |
Change https://go.dev/cl/613095 mentions this issue: |
Running `go tool` with no arguments will now list built in tools followed by module defined tools. Running `go tool X` where X matches either the full package path, or the last segment of the package path, of a defined tool will build the tool to a known location and immediately execute it. For #48429 Change-Id: I02249df8dad12fb74aa244002f82a81af20e732f Reviewed-on: https://go-review.googlesource.com/c/go/+/534817 Reviewed-by: Michael Matloob <matloob@golang.org> Reviewed-by: Sam Thanawalla <samthanawalla@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This change implements executable caching. It always caches the outputs of link steps used by go run. To do so we need to make a few changes: The first is that we want to cache binaries in a slightly different location than we cache other outputs. The reason for doing so is so that the name of the file could be the name of the program built. Instead of placing the files in $GOCACHE/<two digit prefix>/<hash>-d, we place them in $GOCACHE/<two digit prefix>/<hash>-d/<executable name>. This is done by adding a new function called PutExecutable that works differently from Put in two ways: first, it causes the binaries to written 0777 rather than 0666 so they can be executed. Second, PutExecutable also writes its outputs to a new location in a directory with the output id based name, with the file named based on p.Internal.ExeName or otherwise the base name of the package (plus the .exe suffix on Windows). The next changes are for writing and reading binaries from the cache. In cmd/go/internal/work.updateBuildID, which updates build ids to the content based id and then writes outputs to the cache, we first make the change to always write the content based id into a binary. This is because we won't be throwing the binaries away after running them. Then, if the action is a link action, and we enabled excutable caching for the action, we write the output to the binary cache. When reading binaries, in the useCache function, we switch to using the binary cache, and we also print the cached link outputs (which are stored using the build action's action id). Finally, we change go run to execute the built output from the cache. The support for caching tools defined in a module that are run by go tool will also use this functionality. Fixes #69290 For #48429 Change-Id: Ic5f1d3b29d8e9786fd0d564460e3a5f53e951f41 Reviewed-on: https://go-review.googlesource.com/c/go/+/613095 Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Alan Donovan <adonovan@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Change https://go.dev/cl/630695 mentions this issue: |
While the cached name of an executable is set based on the base name of the package path, the executable produced as the output of link doesn't have ExeName set on it and is just called a.out (with a .exe suffix on Windows). Set ExeName so that the first time the binary is run, from the directory link is run in, it has the right name for ps. For #48429 Change-Id: Ic049304ec6fd5b23c2f5aaaf91aa58d79fe5a7ba Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest,gotip-windows-amd64-longtest Reviewed-on: https://go-review.googlesource.com/c/go/+/630695 Reviewed-by: Conrad Irwin <conrad.irwin@gmail.com> Reviewed-by: Hongxiang Jiang <hxjiang@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Playing with tip I can do: go install tool github.com/alta/protopatch/cmd/protoc-gen-go-patch
go get -tool google.golang.org/protobuf/cmd/protoc-gen-go But these do not appear to work (tools metapackage): go install tools
go build tools Is the tools metapackage planned for Go1.24? |
@meling Apologies- the design doc is now a little out of date. We changed the naming of the metapackage to A few other major changes in the final
|
Adding a release blocker to track mentioning this new cmd/go feature in the Go 1.24 release notes. |
@matloob @samthanawalla to confirm the code has been completed and only release notes are pending for 1.24. |
@dmitshur the Modules FAQ may also need to be updated |
Change https://go.dev/cl/632555 mentions this issue: |
Change https://go.dev/cl/632595 mentions this issue: |
Change https://go.dev/cl/632556 mentions this issue: |
Change https://go.dev/cl/632596 mentions this issue: |
UPDATE: 2024-07-29: the latest proposal can be found here.
Background
The current best-practice to track tool dependencies for a module is to add a
tools.go
file to your module that includes import statements for the tools of interest. This has been extensively discussed in #25922 and is the recommended approach in the Modules FAQThis approach works, but managing the tool dependencies still feels like a missing piece in the
go mod
toolchain. For example, the instructions for getting a user set up with a new project using gqlgen (a codegen tool) looks like thisThe
printf
line above really stands out as an arbitrary command to "add a tool" and reflects a poor developer experience when managing tools. For example, an immediate problem is that theprintf
line will only work on unix systems and not windows. And what happens iftools.go
already exists?So while we have some excellent tools for managing dependencies within the
go.mod
file usinggo get
andgo mod edit
, there is no such equivalent for managing tools in thetools.go
file.Proposed Solution
The
go.mod
file uses the// indirect
comment to track some dependencies. An// indirect
comment indicates that no package from the required module is directly imported by any package in the main module (source).I propose that this same mechanism be used to add tool dependencies, using a
// tool
comment.Users could add a tool with something like
or
A
go.mod
would then look something likeAnd would allow users to subsequently run the tool with
go run github.com/99designs/gqlgen
This would mean a separate
tools.go
file would no longer be required as the tool dependency is tracked in thego.mod
file.Go modules would be "tool" aware. For example:
go mod tidy
would not remove the// tool
dependency, even though it is not referenced directly in the module// tool
dependency is imported by another module, Go modules understands that the// tool
dependency is not required as an indirect dependency. Currently when usingtools.go
, go modules does not have that context and the tool is treated like any other indirect dependencygo get -tool [packages]
would only add a dependency with amain
packageThe text was updated successfully, but these errors were encountered: