| Dependencies & vendoring | Brad Fitzpatrick | 02/03/15 09:38 | Gophers, One of the most frequent questions we’ve received since Go 1 was how to deal with dependencies and their versions. We’ve never recommended any particular answer. In Google’s internal source tree, we vendor (copy) all our dependencies into our source tree and have at most one copy of any given external library. We have the equivalent of only one GOPATH and rewrite our imports to refer to our vendored copy. For example, Go code inside Google wanting to use “golang.org/x/crypto/openpgp” would instead import it as something like “google/third_party/golang.org/x/crypto/openpgp”. This has worked out very well for us and we get reproducible builds. If we ever want to update openpgp in our vendored directory, we update it, verify that all the affected code in the world still compiles and tests pass (making code changes as necessary), and then check it in. The world compiles and passes at all points in the version control system’s history, and if we bisect in time, we see which version of an external library was in use at any point. We’re starting to see others in the Go community do the same, with tools like godep and nut. We think it’s time to start addressing the dependency & vendoring issue, especially before too many conflicting tools arise and fragment best practices in the Go ecosystem, unnecessarily complicating tooling. It would be nice if the community could converge on a standard way to vendor. Our proposal is that the Go project,
The important part is that as a community, we all do this the same way, so tooling can mature and interoperate. In Go 1.5, the “internal” package mechanism introduced in Go 1.4 for the standard library will be extended to all go-gettable packages, so using the “internal” directory as the root of rewritten import paths makes sense (as opposed to “vendor” or “third_party”). Consider an existing use of vendoring in the Go source tree: $GOROOT/src/cmd/internal currently contains copies of “rsc.io/x86/x86asm” and “rsc.io/arm/armasm” as $GOROOT/src/cmd/internal/rsc.io/x86/x86asm/ and $GOROOT/src/cmd/internal/rsc.io/arm/armasm/, respectively. When we use those inside the Go tools, however, we import them “cmd/internal/rsc.io/x86/x86asm” and not “rsc.io/x86/x86asm”. (Although this example comes from the Go distribution repo, the effect is the same as a local project using $GOPATH/src/your.project/path instead of $GOROOT/src/cmd.) We currently maintain those copies by hand. Instead, we want to write a file (filename and syntax to be determined), such as: src/cmd/internal/TBDCONFIG.CFG: “rsc.io/x86/x86asm” with revision af2970a7819d “rsc.io/arm/armasm” with revision 616aea947362 And then your vendoring tool (such as “godep” or “nut”) would read TBDCONFIG.CFG and write out, src/cmd/internal/rsc.io/x86/x86asm/*.go src/cmd/internal/rsc.io/arm/armasm/*.go rewriting imports and import comments in these files for the new location. It may also optionally change your source so any occurrence of import “rsc.io/x86/x86asm” becomes import “cmd/internal/rsc.io/x86/x86asm” The vendoring tool would be responsible for generating errors on conflicts or missing dependencies. The thing that we as a community need to figure out is the recommended configuration file format. We’d prefer something that the Go standard library can already parse easily. That includes XML, JSON, and Go. Nobody likes XML, so that leaves JSON and Go. godep already uses JSON, as do Go tools themselves (e.g. “go list -json fmt”), so we’ll probably want something like godep’s JSON format: { "Deps": [ { "ImportPath": "rsc.io/arm/armasm", "Rev": "616aea947362" }, { "ImportPath": "rsc.io/x86/x86asm", "Rev": "af2970a7819d" } ] } We can start with that for discussion. Note that we have rejected non-vendoring approaches that require modifications to GOPATH or new semantics inside the go command and toolchain. We believe it is important that the solution not require additional effort on the part of all the tools that already understand how to build, analyze, or modify code in the standard GOPATH hierarchy. |
| Re: [golang-dev] Dependencies & vendoring | Aram Hăvărneanu | 02/03/15 09:47 | One of the nicest things about Go is that all the information required
to build Go programs is in the source code, a.i. in .go files, and not in any other files (Makefiles, .cfg files, etc). With this proposal, this would change. We'd have information in non-Go files (TBDCONFIG.CFG). -- Aram Hăvărneanu |
| Re: [golang-dev] Dependencies & vendoring | Brendan Tracey | 02/03/15 09:49 | Who is the we in “Our proposal is that”?
|
| Re: [golang-dev] Dependencies & vendoring | cm...@golang.org | 02/03/15 09:51 | As noted in the OP, TBDCONFIG.CFG could be TBDCONFIG.go (or TBDCONFIG.json). I'm not sure if that alleviates the problem of having "other files" but the other files can be other Go files. -- |
| Re: [golang-dev] Dependencies & vendoring | Brad Fitzpatrick | 02/03/15 09:56 | On Mon, Mar 2, 2015 at 9:49 AM, Brendan Tracey <tracey....@gmail.com> wrote: me, Rob, Russ, Andrew, Ian, David Crawshaw, David Symonds, Sameer, Alan Donovan, et al. |
| Re: [golang-dev] Dependencies & vendoring | rsc | 02/03/15 09:56 | On Mon, Mar 2, 2015 at 12:46 PM, Aram Hăvărneanu <ara...@mgk.ro> wrote:One of the nicest things about Go is that all the information required Not really true. cmd/internal/gc has information in a .y file. go generate arranges to write out the files needed to conform to the usual setup, without teaching the usual setup about yacc. The same thing is going on here. The tool (godep, nut, whatever) would use the config file to write the files needed to conform to the usual setup. This config file would only be read by that tool, not by the go command. Russ |
| Re: [golang-dev] Dependencies & vendoring | Nathan Youngman | 02/03/15 10:37 | It's good to see this discussion happening. Agreeing on a common file format and file layout below /internal/ would be a huge step forward. There are some philosophical differences between nut and godep. Is the file generated from current imports or created manually? Does it only contain SHA commits or can it include branches or tags? I think it's great to have multiple independent implementations (at first), to see what works better in the wild. |
| Re: [golang-dev] Dependencies & vendoring | Rodrigo Kochenburger | 02/03/15 11:10 | I really like the fact we are discussing this as the community has a lot to benefit from a standard approach. One thing I love about Go is how the workflow flows. It's smooth. How do you guys envision the workflow for: a) adding a new dependency; b) updating a dependency? Does the developer have to manually update the dependency file (similar to nut) or is the dependency file generated from the code (similar to godep)? In which step would the import path rewrite happen? Also, will library packages also have dependencies specified like that or only application/main packages? What happens to the dependencies of dependencies? For example, my application (github.com/divoxx/app) imports "github.com/foo/foo which in turn imports "github.com/bar/bar", after the rewrite they are both gonna be "github.com/divoxx/app/internal/github.com/foo/foo" and "github.com/divoxx/app/internal/github.com/bar/bar" respectively? --You received this message because you are subscribed to the Google Groups "golang-dev" group. |
| Re: [golang-dev] Dependencies & vendoring | Brad Fitzpatrick | 02/03/15 11:20 | On Mon, Mar 2, 2015 at 11:10 AM, Rodrigo Kochenburger <div...@gmail.com> wrote: We're not looking to specify either of those right now. We only care about standardizing the configuration file format at this time. (we might say "for Go 1.5" on accident, but this has nothing to do with Go 1.5's release cycle timing... this could happen tomorrow or in 5 months)
The mechanism should work for libraries too, but I think we'll discourage overuse of it for libraries. We imagine it'll be mostly used for package main.
That's up to the tool. There might also be a mechanism to declare packages which are safe for duplication (no internal state in package-level vars) vs those which are not. Then the vendoring tool can error if it finds a problem. |
| Re: [golang-dev] Dependencies & vendoring | Rodrigo Kochenburger | 02/03/15 11:28 | Okay, gotcha. I also think Godeps seems to be the easiest and more comprehensive format out there. I like the fact that it also has the go version specified in it, which AFAIK is not enforced in any way but potentially could. |
| Re: [golang-dev] Dependencies & vendoring | Brad Fitzpatrick | 02/03/15 11:29 | On Mon, Mar 2, 2015 at 11:28 AM, Rodrigo Kochenburger <div...@gmail.com> wrote: I removed it from the example because it wasn't clear what it even meant. |
| Re: Dependencies & vendoring | Ben Darnell | 02/03/15 11:38 | On Monday, March 2, 2015 at 12:38:02 PM UTC-5, Brad Fitzpatrick wrote: There is a crucial difference between Google's use of import rewriting and how this would be used in the outside world: the third_party directory (which I assume would be renamed to "internal" under this proposal) exists in a scope that spans many projects, so google/gmail, google/plus, and google/selfdrivingcar can all share the same set of vendored packages. Outside of Google, there is no accessible common ancestor directory, so when two packages share a common dependency they must each import their own version of it into their own vendor directory. For a concrete example, cockroachdb currently depends on etcd, and they both depend on golang.org/x/net/context. Etcd vendors their dependencies and so cockroach uses the unsightly import path "github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context". If "Godeps/_workspace" were moved under "internal", we couldn't do that and we'd end up with two copies of the library (for net/context I think that would still work since the main thing used from that package is an interface, but it wouldn't work with e.g. glog). Granted, this situation is a bit unusual since etcd is primarily intended to be an end-user executable rather than a reusable go library, and we intend to break out the parts that are used by cockroachdb (the 'raft' subpackage) into a separate package/repo, but that just moves the problem around. The new raft package would either have to vendor its dependencies and rewrite its imports, or use canonical import paths for everything with no way to control dependency versions even for its own tests. Personally, while I see the value of import-rewriting for corporate environments where you have one large meta-project, I think the better solution for the open-source world is to avoid rewriting imports and instead improve tooling support for a per-project GOPATH (I now let the emacs package go-projectile manage my GOPATH, which works very well for my workflow) and to use something like gpm or goop to pin dependency versions. -Ben |
| Re: [golang-dev] Dependencies & vendoring | Axel Wagner | 02/03/15 12:44 | Hi,
the gist: I strongly dislike vendoring because 1 You end up with more than one copy of the same code in your binary (unless there is some magic I am not aware of possible) 2 It discourages contribution to upstream (because it is quicker to fix it in the vendored copy, right?) 3 As a consequence it creates diverging versions of the same library 4 And possibly licensing issues (as observed with ruby) 5 It puts a lot of burden unto package maintainers, as distributions normally disallow vendoring (for security- and maintability concerns) At the very least I would want to discourage vendoring for the creators of libraries. The rant (I will probably not say a lot more about this, but I at least wanted to put my concerns out there): I am a big non-fan of vendoring. My main question with this proposal is: What happens, when two different packages vendor the same dependency? Will we end up with two copies of the dependency? Will that be a problem? I could see problems both in codesize and with stuff like sql/driver, where you would effectively end up with two disjunct sources for drivers, if the package gets duplicated. I dislike the comparison with Google's mechanism. A big difference is, that nobody imports googles internal packages, so the above problem (or any below) doesn't arrive. Google's approach works, because it is basically the same as the approach in a distribution: third_party/foo/bar corresponds to a package in a distribution with distribution-specific patches. As you have one codebase with one controlling authority, you can do global updates and more or less atomic changes over all of the codebase. This stops working with an open-source ecosystem, where you have in part little to no control over upstreams. Instead of updating a library on my system and maybe fixing up dependencies, if there are build-failures, I now have to wait for all upstreams to update their vendored versions (or in turn have to vendor *them* and take over some maintainership responsibilities). Vendoring is the solution the ruby-community has chosen, apparently, and at least as far as I can tell, that is the main reason, why jekyll in debian has been broken for year(s?). At least I gave up trying to package it after having to figure out bugs in all the transitive vendored dependencies and having to deal with the licensing jungle (because once stuff gets vendored anyway, you can just add random files right? Without regard for what is licensed how. Or even annotating what files are from where). I think vendoring is the wrong solution for reproducible builds. Reproducible build only requires all the version information of all transitive dependencies used to build a binary plus the version of the go toolchain and stdlib used (btw: Does godep or nut address that? Just out of curiosity). Therefore I feel that reproducible builds are a red herring, when advocating for vendoring. I think the main reason, why vendoring became popular is, that it makes it easier to deal with API-incompatibilities of upstream and to make software go-gettable. But I think this is a bad optimization goal. Again, gem/pip/npm are things chosen by other languages and I at least will try everything I can *not* to install something that depends on any of those. I prefer clean releases and *one* Package manager. Not everyone wants to install a go toolchain, just to install one tool, just as I don't want to install a node.js toolchain just to use the keybase.io CLI :) I fear, that with library, we are ultimately giving up on any API-stability, because we don't even have to deal with an upstream that changes their API all the time, we can just vendor and ship with a frozen-in-time version… |
| Re: [golang-dev] Dependencies & vendoring | minux | 02/03/15 12:51 | Then this view suggests indirectly that the go tool will never gain the ability to use such file to import new revisions? |
| Re: [golang-dev] Dependencies & vendoring | Keith Rarick | 02/03/15 12:52 | This proposal sounds good to me.
Especially using "internal"; it makes sense. I'll make any changes necessary in godep to work with the format and file paths we agree on. I don't care about the details of the config file format. I just want it to be possible to generate it automatically from scratch from an existing set of go source code and dependency code, if the user so desires. |
| Re: [golang-dev] Dependencies & vendoring | Keith Rarick | 02/03/15 12:56 | >> Also, will library packages also have dependencies specified like that orI support discouraging this for libraries. If a library P does this with its dependency D, then someone who wants to use both P and D is required to also use a vendoring tool (unless it happens to be ok to link in two copies of D). That is annoying, especially for a person or project that's just getting started. It's much nicer to be able to 'go get P D' and import P and D and get to work. |
| Re: [golang-dev] Dependencies & vendoring | Keith Rarick | 02/03/15 13:04 | On Mon, Mar 2, 2015 at 12:10 PM, Axel WagnerUnfortunately, experience shows this is not true. A reproducible build requires the source code needed to make the build. With vendoring, you have the source code. Without it, you need not only the version information but also a *means* to acquire the source code—a network that is functional and fast enough. You might be surprised how often that requirement is not met. Godep records the output of "go version" when it generates the file Godeps.json. |
| Re: [golang-dev] Dependencies & vendoring | Nathan Youngman | 02/03/15 13:23 | Libraries that depend on libraries other than the standard library do complicate things. I've had good success with shallow dependencies: main (Godep) -> library (gopkg.in or go get) -> standard library So while the directory structure and revisions file may support vendoring within libraries, I would also discourage it. Nathan. -- |
| Re: [golang-dev] Dependencies & vendoring | Sébastien Douche | 02/03/15 13:41 | On Mon, 2 Mar 2015, at 18:46, Aram Hăvărneanu wrote:Hmm, I would say "the nicest thing about Go is you don't need external tool to build Go programs". -- Sébastien Douche <s...@nmeos.net> Twitter: @sdouche http://douche.name |
| Re: Dependencies & vendoring | Owen Ou | 02/03/15 13:46 | It's good to see such discussion going on. I'm the author of nut so my comments might be bias :) It sounds like there're two things nut does differently from Brad's suggestions:
For 1), I'm open to suggestions as long as the format is clear and concise. Currently nut adopts Tomlas the config format. An example of declaring depnednecies: [dependencies] "rsc.io/arm/armasm" = "616aea947362" "rsc.io/x86/x86asm" = "af2970a7819d" I personally think this is very clear and less noisy than JSON. But I understand the preference of using something Go standard library can parse. It wouldn't be hard for nut to support JSON as the config file. But I think the proposed JSON schema is a bit verbose: the keys of "ImportPath" and "Rev" seem unecessary. How about removing the keys? {
"Deps": {
"rsc.io/arm/armasm": "616aea947362",
"rsc.io/x86/x86asm": "af2970a7819d"
}
}For 2), I don't have a problem of renaming "vendor" as in nut to "internal": making vendored dependencies only accessible to current package makes sense. |
| Re: [golang-dev] Dependencies & vendoring | Brendan Tracey | 02/03/15 13:52 |
What is the suggested behavior for libraries? I must be missing something, because this mentality does not seem in the spirit of Go. Go is excellent at supporting programming in the large. As programs get richer and as the ecosystem grows, there will inevitably be a hierarchy of libraries. The standard library will only implement so many ideas. I don’t intend to be critical, I just don’t see the intended vision. |
| Re: [golang-dev] Re: Dependencies & vendoring | Andrew Gerrand | 02/03/15 13:54 | On 3 March 2015 at 06:34, <ben.d...@gmail.com> wrote: Vendoring should be used only for the dependencies of binaries, not for the dependencies of packages. This particular problem could be solved by: a) a policy of API stability adhered to by the raft subpackage and its dependent packages, b) testing infrastructure that is version-aware.
Right now I'm working on an API stability policy similar to the Go 1 compatibility promise for the gokit project and its dependencies. If that goes well, maybe the greater Go community can adopt the policy for their projects. Andrew |
| Re: [golang-dev] Dependencies & vendoring | Andrew Gerrand | 02/03/15 13:56 | This property doesn't change; you won't need non-Go files to *build* Go programs. You'll just need the metadata to update a program's dependencies, and that necessary metadata is not currently encoded in Go source code anywhere. |
| Re: [golang-dev] Re: Dependencies & vendoring | Andrew Gerrand | 02/03/15 13:58 | One advantage to Brad's proposed syntax is that we can add extra fields (if need be) while maintaining backward compatibility with older tools. |
| Re: [golang-dev] Re: Dependencies & vendoring | Jaana Burcu Dogan | 02/03/15 14:16 | > Vendoring should be used only for the dependencies of binaries, not for the dependencies of packages.Could you clarify what this exactly means? How am I supposed to vendor a revision of package x, if that revision doesn't know which revision of package y to depend on? In any case, a revision has to know about the revision it is depending on. And if the packages need to vendor, there is a critical problem with this proposal. How am I supposed to export a symbol from a vendored package? package a type Doer interface package b func X(doer a.Doer) a's import path will be visible to package b only. |
| Re: [golang-dev] Re: Dependencies & vendoring | Jaana Burcu Dogan | 02/03/15 14:18 | Ah, Gmail quoted and wrapped the bottom half of my email. Resending that part.
And if the packages need to vendor, there is a critical problem with this proposal. How am I supposed to export a symbol from a vendored package? package a type Doer interface package b func X(doer a.Doer) a's import path will be visible to package b only. On Mon, Mar 2, 2015 at 2:16 PM, Burcu Dogan <j...@google.com> wrote: >> Vendoring should be used only for the dependencies of binaries, not for the dependencies of packages. > > Could you clarify what this exactly means? How am I supposed to vendor > a revision of package x, if that revision doesn't know which revision > of package y to depend on? In any case, a revision has to know about > the revision it is depending on. > > And if the packages need to vendor, there is a critical problem with > this proposal. > >> officially recommends vendoring into an “internal” directory with import rewriting (not GOPATH modifications) as the canonical way to pin dependencies. > > How am I supposed to export a symbol from a vendored package? > > package a > > type Doer interface > > > package b > > func X(doer a.Doer) > > > a's import path will be visible to package b only. > > > On Mon, Mar 2, 2015 at 1:53 PM, Andrew Gerrand <a...@golang.org> wrote: >> >> On 3 March 2015 at 06:34, <ben.d...@gmail.com> wrote: >>> >>> Granted, this situation is a bit unusual since etcd is primarily intended >>> to be an end-user executable rather than a reusable go library, and we >>> intend to break out the parts that are used by cockroachdb (the 'raft' >>> subpackage) into a separate package/repo, but that just moves the problem >>> around. The new raft package would either have to vendor its dependencies >>> and rewrite its imports, or use canonical import paths for everything with >>> no way to control dependency versions even for its own tests. >> >> >> Vendoring should be used only for the dependencies of binaries, not for the >> dependencies of packages. This particular problem could be solved by: >> a) a policy of API stability adhered to by the raft subpackage and its >> dependent packages, >> b) testing infrastructure that is version-aware. >> >>> Personally, while I see the value of import-rewriting for corporate >>> environments where you have one large meta-project, I think the better >>> solution for the open-source world is to avoid rewriting imports and instead >>> improve tooling support for a per-project GOPATH (I now let the emacs >>> package go-projectile manage my GOPATH, which works very well for my >>> workflow) and to use something like gpm or goop to pin dependency versions. >> >> >> I think we can develop the tools to make it easier to test packages with >> different versions of their dependencies, and to make it easier for the >> ultimate consumer (a program binary) to vendor the correct dependencies (or >> provide diagnostics in the rare case of incompatible dependenct versions). >> Those tools may be [based on] projects like gpm or goop. >> >> Right now I'm working on an API stability policy similar to the Go 1 >> compatibility promise for the gokit project and its dependencies. If that >> goes well, maybe the greater Go community can adopt the policy for their >> projects. >> >> Andrew >> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-dev" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-dev+...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. |
| Re: [golang-dev] Re: Dependencies & vendoring | Owen Ou | 02/03/15 14:23 | On Monday, March 2, 2015 at 1:58:02 PM UTC-8, Andrew Gerrand wrote:
Cool, I've created https://github.com/jingweno/nut/issues/10 & https://github.com/jingweno/nut/issues/11 to track. |
| Re: [golang-dev] Re: Dependencies & vendoring | Ben Darnell | 02/03/15 14:24 | On Mon, Mar 2, 2015 at 4:53 PM, Andrew Gerrand <a...@golang.org> wrote: The raft package was developed in tandem with the rest of etcd; it is only now reaching a point of API stability (after validating its interfaces with usage in two applications). In a world of rewritten imports (where at least some dependencies are like glog and must not be duplicated), reusing a piece of an application is a significant burden. Before we could even begin to use raft in cockroachdb, we would have had to move the master copy of the raft code out of etcd (into a new repo which would be developed under "package rules" instead of "binary rules") and vendor it back in to etcd. (we are in fact undertaking this work now, but only after the experiment has proven successful) I don't like the strict division of packages into "those which are so closely tied to a particular binary that they use its rewritten imports" and "those which use 'go get' for their own dependencies but should be vendored into any application that uses them"
But if we had this version-aware infrastructure (which I admit is a harder problem), would we still want to rewrite imports? I claim that for purposes of reproducible builds it's better to place the entire GOPATH under version control (as long as you can have per-project GOPATHs) than to use an internal/vendor directory to ensure that all your dependencies share a common prefix deep in the source tree.
Yes. I agree that the needs of library developers are different from the needs of application developers. Libraries must be as broad as possible in their dependencies to minimize conflicts (hopefully just a minimum version; occasionally a maximum or range) while applications want to pin things down exactly. I'd just like for this difference to be as localized as possible (e.g. "use == instead of >= in your dependencies.json file") instead of completely changing the workflow. -Ben
|
| Re: [golang-dev] Re: Dependencies & vendoring | Zellyn | 02/03/15 14:49 | On Monday, March 2, 2015 at 1:58:02 PM UTC-8, Andrew Gerrand wrote:
Agreed. As an example, I could see particular tools adopting conventions for noting which (semver.org -style) version of dependencies you were aiming for, and trying to merge shared dependencies. Like Brad's "safe for duplication declaration" mentioned above, this would require some kind of metadata convention too, so I'm glad we're not trying here to decide what color to paint that bikeshed. Zellyn |
| Re: [golang-dev] Re: Dependencies & vendoring | Andrew Gerrand | 02/03/15 15:36 | On 3 March 2015 at 09:24, Ben Darnell <ben.d...@gmail.com> wrote: I think it's reasonable to expect some difficulty when re-using the internal packages of larger projects. Until those packages are officially supported by their authors, you're kind of in "here be dragons" territory. I don't think this proposal makes such issues better or worse.
There's an argument for keeping all the various mechanical pieces small and simple. It's definitely possible to imagine some larger infrastructure that manages everything for us, from end to end, but that's not the direction we have taken so far.
What I'm talking about is codifying our existing workflows and formal documentation of the stability of packages, not changing workflows entirely.
|
| Re: [golang-dev] Re: Dependencies & vendoring | Andrew Gerrand | 02/03/15 15:38 | On 3 March 2015 at 09:16, Burcu Dogan <j...@google.com> wrote: > Vendoring should be used only for the dependencies of binaries, not for the dependencies of packages. I'm saying the maintainers of the binary should vendor all of its transitive dependencies, if they vendor at all. The package maintainers should not vendor anything.
I don't understand the question. As maintainer of the code en masse you have visibility into all import paths. Maybe my answer to your first question helps?
|
| Re: [golang-dev] Re: Dependencies & vendoring | Keith Rarick | 02/03/15 15:46 | On Mon, Mar 2, 2015 at 1:57 PM, Andrew Gerrand <a...@golang.org> wrote:>> But I think >> the proposed JSON schema is a bit verbose: the keys of "ImportPath" andFor example: if the program has vendored a patch to one of its dependencies and the patch is not yet merged upstream, the author might want their tool to include an alternative URL where the patch has been published. Or: godep currently includes the output of "git describe --tags" (or a similarly descriptive command for hg and bzr) for each dependency, for the benefit of any human who is reading the file. |
| Re: [golang-dev] Re: Dependencies & vendoring | rsc | 02/03/15 15:47 | People seem to agree that libraries should not vendor other libraries without a good reason. That's actually beyond the scope here. There is some question about what happens if libraries *do* vendor other libraries, and that gets to the heart of the proposal. If there is an agreed-upon vendoring approach (import path rewriting) and data format that describes what vendoring did happen, then no matter what vendoring helper did it, another tool (or perhaps the same one) can come along and analyze the situation and either just fix it or help the programmer fix it with minimal interactions. On the other hand, if the vendoring tools use different semantics or even just different config files, this kind of metatool becomes much more difficult. The goal here is to (1) agree on import path rewriting (as opposed to dynamic GOPATH tweaking or other complications), and (2) agree on a config file format that records the rewriting that happened, so that different projects can use different tools and still interoperate, both for just building things and for using meta tools that provide things like deduplication and diamond crushing. Russ |
| Re: [golang-dev] Re: Dependencies & vendoring | Ben Darnell | 02/03/15 15:59 | On Mon, Mar 2, 2015 at 6:35 PM, Andrew Gerrand <a...@golang.org> wrote: This proposal does make some such issues a bit worse by requiring (or at least encouraging) the use of an "internal" namespace for vendored packages. Currently we can experiment in "here be dragons" territory by importing another application's vendored packages; that becomes more difficult (at least in some cases) if such packages become internal. But your point is taken; in the absence of a specific counter-proposal it is probably better to move forward with increased standardization in this area since vendoring with rewritten imports does solve at least some of the versioning problem. -Ben
|
| Re: [golang-dev] Re: Dependencies & vendoring | Jaana Burcu Dogan | 02/03/15 16:59 | > Maybe my answer to your first question helps?Yes, the first answer clarifies both. The second question arises only if the packages have to vendor their own dependencies. (IMHO, vendoring libraries should be considered in the scope of this proposal not to break whatever standardization may come out of this proposal. What's your argument against the libs vendoring or blessing the revisions of their dependencies? We need to develop some ideas/conventions around the API compatibility and versioning before tackling a configuration schema problem -- especially in a world where a revision hash hardly ever can represent an API version.) |
| Re: [golang-dev] Dependencies & vendoring | Kamil Kisiel | 02/03/15 17:26 | I like the idea of having it be a .go file. It could be required to have a specific name, and would import a package which has an exported struct type used to describe a dependency. Over time when the requirements evolve, more fields could be added to the struct type. The syntax is familiar and we get strict checking for free via the compiler. eg: import "deps" var Dependencies = []deps.D{ {Path: "rsc.io/arm/armasm", Rev: "616aea947362"}, } The dependency tool could either compile it or read the information using the ast package. On Monday, March 2, 2015 at 9:51:30 AM UTC-8, cm...@golang.org wrote:
|
| Re: Dependencies & vendoring | Emil Davtyan | 02/03/15 20:14 | I would like to suggest an "alias" parameter as well, inside the configuration format. This would allow us to specify the folder that we would like the given dependency to be written out to, therefore also allowing us to simultaneously vendor multiple versions of one package. For example : These would be written out to : |
| Re: [golang-dev] Re: Dependencies & vendoring | jul...@soundcloud.com | 02/03/15 20:14 | On Monday, March 2, 2015 at 10:54:11 PM UTC+1, Andrew Gerrand wrote: So if I have a repo that has both libraries and binaries, should it be split up? Or should any binaries in it vendor the library parts of the same repo? Actually we recently had the problem where binary B used library L (different repos), and L had a method which accepted protobufs defined in a third repo P. Since L vendored P (now P'), it was impossible for B to pass in protobuf types from P to L. So we had to un-vendor everything in L, which is all good according to your suggestion to not vendor dependencies for libraries. But the library repo also contains some sample binaries. Should these live somewhere else or simply not use vendoring? Julius |
| Re: [golang-dev] Dependencies & vendoring | Michael Schuett | 02/03/15 20:14 | I am not sure what you are aiming for when saving the output requiring dependencies to the Dependencies variable. In the original post versioned dependencies have their own path in the vendored folder so implementing an entire new stdlib seems like overkill. This also allows for some odd things like being able to manage deps in any go file which could get very confusing and I see it being abused. Looking at the following JSON object I think this would be a much cleaner way. I can immediately tell by looking at this that if i want to import armasm into the project i am working on i would use vendor/folder/rsc.io/arm/armasm. { "destination": "vendor/folder/", "deps": [ { "ImportPath": "rsc.io/arm/armasm", "Rev": "616aea947362" }, {
] } |
| Re: [golang-dev] Dependencies & vendoring | Jacek Masiulaniec | 02/03/15 21:01 | It will be daunting having to read long lines such as: This can be ameliorated by running a vanity domain, for example: In fact, this is the exact approach taken by my recent project (http://opentsp.org/). I am overall quite happy with this approach. It has made me toy with an idea for a dependency upgrade tool that walks internal/ to obtain the dependency list (i.e. without resorting to a config file), and then syncs each to the latest version that doesn't introduce a build or test failure in any importing package. This idea is half-baked; having an explicit hash or tag is probably the way to go. Jacek On 2 March 2015 at 09:37, Brad Fitzpatrick <brad...@golang.org> wrote:
|
| Re: Dependencies & vendoring | Joshua Marsh | 02/03/15 21:29 | On Monday, March 2, 2015 at 10:38:02 AM UTC-7, Brad Fitzpatrick wrote: I would personally prefer using something within the source code and more familiar to what I'm used to in Go. I like the idea of using something like a build constraint/generate comment or a struct field tag. Some possible formats might be: import ( ) This appeals to me because:
|
| Re: [golang-dev] Dependencies & vendoring | Kamil Kisiel | 02/03/15 21:36 | I think you misunderstood, I wasn't suggesting that you'd be able to have dependencies in any .go file, just the one specially named for configuration. Your dependencies would still ultimately go in to their own vendored path. I'm only discussing the format of the version definitions, using standard go code as an alternative to JSON syntax. I don't think the JSON is any cleaner, it's probably about on par with Go's syntax as far as verbosity goes. The advantage of using Go syntax is that it's a bit easier to validate via the languages type system. Maybe that's not compelling enough and/or parsing would be too complicated compared to JSON, that's why I'm asking what people think. I'm not sure what you mean by "implementing an entire new stdlib". |
| Re: [golang-dev] Dependencies & vendoring | Dmitri Shuralyov | 02/03/15 22:59 | I have one observation I'd like to share, it's one of many aspects that should be considered. The examples in discussion above seem to be all using import paths as keys. Perhaps it's better to allow import path patterns (as defined at https://golang.org/cmd/go/#hdr-Description_of_package_lists), since they can represent a VCS repository in one line. It's less likely you'd use different revisions for packages within one VCS repo. So, instead of... "rsc.io/arm/armasm": "616aea947362" "rsc.io/x86/x86asm": "af2970a7819d" It could be: "rsc.io/arm/armasm/...": "616aea947362" All I ask is you consider this point (that a single repository may contain more than one Go package) and see what works better. (Also note that normal import paths are valid import path patterns too, so it's backwards compatible.) |
| Ce message a été masqué, car il a été signalé comme étant abusif. | |||
| Re: Dependencies & vendoring | Sean Bowman | 03/03/15 05:38 | Vendoring is going to be a complete mess to maintain in the long run, and way too complicated a solution. I think if you're Google you can make it work. But if you're a startup in a basement, you're going to have to switch to a language with proper dependency management. You just won't have the manpower to maintain the source and updates for 30 other libraries along with your app.
Why not instead just add support to Go for an optional tag or commit ID to the import string, along the lines of what Joshua Marsh is suggesting: import "github.com/johndoe/mylib 1.0" import "bitbucket.org/janedoe/another fe3b56a01ccde" If it's not there, use the "master" branch. import "github.com/old/mylib" // uses master branch |
| Re: Dependencies & vendoring | Eric Anderton | 03/03/15 05:38 | FWIW, I have something in my in-progress Grapnel tool (https://github.com/eanderton/grapnel) that does this Alias capability. Instead of 'Alias', it optionally de-couples the import path from the URL that is used to obtain it. I've found this approach to be both flexible and self-documenting: # TOML format [[dependencies] # denotes a single dependency in the 'dependencies' struct array What's nice about this is that if you have a fork of a commonly used library, you can easily aim Grapnel at that repo instead. Aside: Grapnel is very under-documented at the moment, but it already does some other interesting things like sifting through tags for semantic versioning support, dynamically re-writing gopkg.in imports to direct github.com interactions, and recursive dependency solving. Because of this thread, JSON config support and import re-writing are going to have to take priority next. |
| Re: Dependencies & vendoring | Mihai B | 03/03/15 06:14 | package ax import "golang.org/x/crypto/openpgp" // internal af2970a7819d - would keep the source of openpgp package with revision af2970a7819d in the internal directory of the package ax. I would definitely vote to maintain the versioning information in the source code (i.e. special comments as in the proposal above). That way what you see is what you get. You don't need to look in a config file to find if the imported package actually has a different version than what you see on godoc. It just pops up when you read the import paths which you need to do anyway. I've always liked that Go doesn't use config files like npm or rust to manage the dependencies/import packages. That may not be the case for some packages with unusual requirements (as cmd/internal/gc was mentioned) but such packages are "exceptions". |
| Re: [golang-dev] Dependencies & vendoring | Lars Seipel | 03/03/15 06:32 | On Tue, Mar 03, 2015 at 10:56:55AM +0000, Matthew Sackman wrote:Because library packages are supposed to be combined with other Go code. If a package vendors its dependencies, the user of that package also has to use the vendored copies or deal with the consequences of having multiple copies of a package inside a single binary. What if two packages both include a copy of a third one, but using different versions? It would put the burden of reconciling the mess on the package user and, in my opinion, massively hurt the Go package ecosystem if gaining widespread use. A package should be as widely useful as reasonably possible—don't decrease its usefulness by restricting the environment it might be used in. Being able to specify a commit hash is no substitute for choosing your dependencies wisely. |
| Ce message a été masqué, car il a été signalé comme étant abusif. | |||
| Re: Dependencies & vendoring | pote | 03/03/15 07:24 | > officially recommends vendoring into an “internal” directory with import rewriting (not GOPATH modifications) as the canonical way to pin dependencies. Is there any reason to being so adamant about not changing the GOPATH? What benefits does import rewriting bring to the table over it? In my experience changing the GOPATH solves a pretty big part of the vendoring/dependency problem and it does so without having to change a single line of Go code, this is something that has been out there for a while and we can leverage immediately, why go for a more complex solution? Why hardcode something like "internal" or "vendor" when setting a per-project GOPATH can give us a flexible solution for free?
I am obviously biased from working on gpm, but I think it's dependency file format is a good starting point: https://github.com/pote/gpm#the-godeps-file, it is almost verbatim what is described as what we need in the initial proposal. Having package versions in .go files as part of imports doesn't communicate how Go dependencies work: it would imply that you can import different versions of the same package in different files, a package can only have one active version per application importing it so having it be a per-application metadata file seems like a more correct approach. I also don't think we should jump directly into JSON/Yaml without there being an actual need for them, particularly at such an early point in the discussion: complexity is easy to add and hard to get rid of. |
| Re: [golang-dev] Dependencies & vendoring | Brian Picciano | 03/03/15 07:24 | I like the idea of using a .go file as opposed to a .json file for this. Another nice property of a .go file which wasn't mentioned is that it can be commented, something which could definitely be useful if you want to inform future generations why you're using a particular commit or branch.
One negative which we ought to address though: it's possible (though not terribly likely) that someone's project already exports a variable or type of the same name that we choose here, which would mean this would require changes to their existing package |
| Re: [golang-dev] Dependencies & vendoring | Brad Fitzpatrick | 03/03/15 07:26 | On Tue, Mar 3, 2015 at 6:09 AM, <mediocr...@gmail.com> wrote:I like the idea of using a .go file as opposed to a .json file for this. Another nice property of a .go file which wasn't mentioned is that it can be commented, something which could definitely be useful if you want to inform future generations why you're using a particular commit or branch. Good point. That's probably the strongest argument in favor of Go instead of JSON. I'm always annoyed by the lack of comments in JSON. |
| Re: [golang-dev] Dependencies & vendoring | rsc | 03/03/15 07:31 | I like the idea of using a Go file, but note that it cannot be one that actually builds, because it needs to record the original import paths, not the vendored ones. I would expect that a Go config file would have a standard .go suffix (so that gofmt etc apply) but a build tag keeping it from building, a standard name (say, vendor.go), and a required package name (say, vendor): --- // +build ignore package vendor import ( // These are for the disassemblers. "rsc.io/arm/armasm" // 616aea947362 "rsc.io/x86/x86asm" // af2970a7819d ) --- Russ |
| Re: [golang-dev] Re: Dependencies & vendoring | Robert W. Johnstone | 03/03/15 07:56 | On Monday, 2 March 2015 17:24:41 UTC-5, Ben Darnell wrote: Is there a use-case for vendoring some dependencies, but pulling others from your GOPATH? Otherwise, I don't see the advantage of import rewriting over pointing GOPATH at your vendored libraries. |
| Re: [golang-dev] Dependencies & vendoring | ehedgehog | 03/03/15 07:56 | On 3 March 2015 at 15:26, Brad Fitzpatrick <brad...@golang.org> wrote:{"comment": "this is a comment", "otherField": 1066, ...} {"comment": ["lacking multiline strings", "use an array"]} Would that not suffice despite its clunkiness? Chris -- Chris "or is it 'clunkyness'?" Dollin |
| Re: [golang-dev] Re: Dependencies & vendoring | Pablo Astigarraga | 03/03/15 07:59 | Is there a use-case for vendoring some dependencies, but pulling others from your GOPATH? Otherwise, I don't see the advantage of import rewriting over pointing GOPATH at your vendored libraries. Even if there was you can easily accomplish that with a GOPATH like "locally/vendored/dependencies:/global/go/dependencies", I am also struggling to understand the benefits of import rewriting.
|
| Re: [golang-dev] Dependencies & vendoring | Ian Davis | 03/03/15 08:03 | Could use the main package if we wanted to restrict vendoring only to applications rather than packages.
Ian
|
| Re: [golang-dev] Dependencies & vendoring | Lars Seipel | 03/03/15 08:07 | On Tue, Mar 03, 2015 at 02:48:27PM +0000, Matthew Sackman wrote:If the author of the package you depend on introduces a bug which breaks your package it should be fixed. Just pinning down some old version might let that bug go unnoticed for a long time and some way down the road maybe someone else starts to depend on that buggy behaviour. Now it's no longer possible to combine your package and that other one. Not good for the ecosystem. If you don't trust package authors to not go nuts and break the API left and right, you shouldn't use their packages at all. If they break it inadvertently, it's simply a bug and should be fixed. It's certainly not the most convenient way (and might be unpractical at times) but it should pay off in the long run. |
| Re: [golang-dev] Dependencies & vendoring | Ian Davis | 03/03/15 08:15 |
I suspect go generate could be used for vendoring.
//go:generate vendor rsc.io/arm/armasm 616aea947362
//go:generate vendor rsc.io/x86/x86asm af2970a7819d
Running go generate would check out those package versions, copy the source below an internal package and rewrite imports.
Ian
|
| Ce message a été masqué, car il a été signalé comme étant abusif. | |||
| Re: [golang-dev] Dependencies & vendoring | Tartari Giacomo | 03/03/15 08:44 | Has this bee proposed and ruled out already? package main import ( //go:vendor 616aea947362 //go:vendor af2970a7819d ) The imports reordering tools need to keep track of the "vendoring comment". Giacomo |
| Re: [golang-dev] Dependencies & vendoring | Michael Schuett | 03/03/15 08:49 | I feel like allowing every import to specify a version ends up with people in "version hell". You would also have to specify the version everytime you wanted to use that package. If you changed one would an error be thrown until you changed it in the various other places that you are specifying the old version?
|
| Re: [golang-dev] Dependencies & vendoring | Tartari Giacomo | 03/03/15 08:59 | I would assume so, but that is another easily automated task. Could even be made interactive: $go vendor $go vendor found mismatching version for package X: v1, v2, v3. do you wish to unify the versions or something? y,n version [1], [2], [3]? And it would be cool it tags are supported //go:vendor rev:616aea947362 //go:vendor tag:616aea947362 Tags are easier to read. Giacomo |
| Re: [golang-dev] Dependencies & vendoring | Tartari Giacomo | 03/03/15 09:01 |
this was supposed to be //go:vendor tag:v1.0 I need more coffe/sleep, sorry. |
| Re: [golang-dev] Dependencies & vendoring | Michael Schuett | 03/03/15 09:15 | Tags would be cool but I don't really know how many packages support them I am guessing a very small amount since go get works off master. Some of the larger projects do which may be reason of enough for tag support but commit tag support is really all I would be looking for and would simplify things. But I may bias I like the simplicity of one json or go file in the root of the projects that manages all the dependencies I think it would also be familiar with people coming from pretty much any other language not that we need to cater to them. I am leaning towards a .json file because the vendoring file should not be considered to be part of your go project it's just installing something that you will be using in your project. just my 2c. |
| Re: [golang-dev] Dependencies & vendoring | Joshua Marsh | 03/03/15 09:23 | On Tue, Mar 3, 2015 at 9:49 AM, Michael Schuett <michae...@gmail.com> wrote: I think this might actually be no different than how a config might produce a "version hell". If one developer was working on one revision and another developer a different revision, once the two sources were brought together there would be a build failure that could be resolved. Using a config won't fix this. You could possibly catch it early if you looked at the config during the merge, but otherwise, you'd probably still find it during the testing after the merge. If the a revision was already in place local testing would catch it just as fast as the command that parses the config. This way seems more inline with the go ecosystem as opposed to some external configuration file in my mind. Using a configuration feels like building an additional room to your house with some plywood and duct tape. Using something like a build constraint or struct tag like I suggested earlier feels like you called a contractor and got it done right. |
| Re: [golang-dev] Dependencies & vendoring | Tartari Giacomo | 03/03/15 09:29 | I don’t see tags as more complicated, to the contrary they would make it easier to distinguish form major versions(and backward incompatibilities): //go:vendor rev:af2970a7819d vs //go:vendor tag:v2.1 As for the json file, I prefer to keep it to go. Eventually a json file will be filled up with other configurations for other incompatible third party tools and stuff will break. Keeping it in control of the go team is a more stable choice imho. Giacomo |
| Re: [golang-dev] Dependencies & vendoring | Govert Versluis | 03/03/15 09:29 | If one uses tags or commit hashes in the .go source file, how are conflicting versions stored in the gopath?
e.g. package A depends on package C tag 123, package B depends on package C tag 456. They both have a magic comment in the source file to indicate the right tag to use. However, since the path in the go source file is the same ("C"), the go build tool (and indeed other tools) will all look in $GOPATH/src/C. I'm against storing this data in .go files, especially if it's in some form of magic comment. The need for structure in directives such as these stands completely opposed to comments (which can be anything). The primary approach to vendoring at the moment seems to be to place the vendored packages in a internal/, third_party/ or vendor/ sub-directory, thus import paths need to be rewritten. As such it seems to make more sense to store the original package path and the revision to use in a manner separate from the actual source files, in structured format. allowing all imports (in multiple files) to be rewritten as needed by the appropriate tool. I don't see an elegant way to do this in .go files. |
| Re: [golang-dev] Dependencies & vendoring | Pieter Droogendijk | 03/03/15 09:43 | On Tuesday, March 3, 2015 at 6:29:36 PM UTC+1, Govert Versluis wrote: I agree with this, putting it in a comment may be the wrong move. But aren't import paths just strings? Don't they allow somewhat more freedom? Didn't we do that for a reason? import `rsc.io/x86/x86asm, vendor, rev:"af2970a7819d"` Or perhaps a tag string, like struct fields. Nicely backwards-compatible, and it nets us something like this: import ( "os" x86asm_v2 "rsx.io/x86/x86asm" `vendor, tag:"v2"` ) |
| Re: [golang-dev] Dependencies & vendoring | Tartari Giacomo | 03/03/15 09:44 | Sorry for the noise did not reply to all.
> On 3Mar, 2015, at 18:29 , Govert Versluis <gov...@ver.slu.is> wrote:They are not, the comment is for a vendoring tool that will checkout the right version in the internal dir. I would also add a go version comment to get completely reproducible builds, //go:version 1.5. |
| Dependencies & vendoring | Martin Leiser | 03/03/15 09:46 | I like the idea of vendoring.
Doing it only on the main package level is fine. But what I dislike is leaving the external library authors out of the game. If a library has no non standard lib as dependency we do not have a problem. But if library A depends on B, the maintainer should have a mechanism to tell his users which version(s) of B are fine, and which are not. He knows that from its own test, and it would be an immense waste of effort if we do not share this knowledge and even worse we do not have a way of sharing it. If we now think of a third package C depending on B as well, we may use the imformation provided by the the maintainers of A and C to make our vendoring decision. But how to supply this kind of information must be a second proposal, separate from the first. Martin |
| Re: [golang-dev] Dependencies & vendoring | Eric Myhre | 03/03/15 10:23 | Whatever comes of this discussion: Distancing any proposed model from how Google works internally is going to be difficult, but necessary.
The open source community as a whole has been burned before by the behaviors that emerge from a company culture that attempts open source but maintains things only in their personal vendorized ecosystem: remember the release of thrift.... followed by the release of thrift? This is -- and there's no shame in this, but I remember a number of central gophers admitting their workplace basically means they never use 'go get' -- a large part of the reason 'go get' is in such a dilapidated state compared to the rest of the otherwise charming and excellent go tool. I don't want to see go getting hung up on root misunderstandings of how a needs of a global collaboration culture may differ from those of a single company with a single dictatorial source tree with a single snapshot view available for a single point in time. The latter is easier, to be sure. Let's focus on moving beyond that. Planet Earth does not have a single shared source tree. Solutions need to account for usage *without prior coordination* between package authors. ... And that's where a whole bunch of the proposed stuff fails. Badly. This whole discussion started with vendoring presumed. (Why is it even in the thread title?) Import rewriting is then proposed as a workaround. There's still huge trouble with this when extended to more than *literally one* project, so it's proposed (with *colossal* handwaving) that libraries and programs should be different. These are both ridiculous duct tape workarounds. No: import rewriting is a ridiculous ducktape workaround, and claiming that libraries and programs are clearly distinct is just lying back and thinking of England. I propose we take a moment and clearly define the goalposts again: everyone's concerns are oriented around isolation, repeatability, and composability. Are there better ways we can serve these goals, especially with scaling across many repositories and many uncoordinated authors? ### isolation Notice how I didn't say "import rewriting". What everyone wants is isolation. We should discuss how to implement that concept. "import rewriting" is one possible way to implement isolation; let's phrase the conversation around the concept first. I second every single person (there have been many) who suggest either using per-project GOPATH settings, or -- if this hasn't been suggested outloud yet, I'd like to make the proposal -- creating a new system with similar semantics. Having wholey separate directory trees for each project is, in fact, absolutely the semantic that I want. Global variables are bad; global library heaps are equally bad, particularly when shared between many different programs of wildly unrelated authorship. (Anyone from the maven world -- remember how it feels to `rm -rf ~/.m2`? Tension just flows out of the body. Tension that never should have existed.) Much like we gophers value our statically linked single file binaries for their ease of shipping, so too do I value a project folder that is clearly that project, only that project, and all of that project. This is what happens when I set `GOPATH=$project/.gopath/`. Much like the whole truth and nothing but the truth, it's great! This means I can sync severable parts of my work to various computers easily, etc, and is super empowering. I regret to say I cannot buy suggestions that this would be an overwhelmingly disruptive chance to the go ecosystem. Currently doing so with every single go library and program I've ever touched in fact seems like rather concrete proof that this is doable, since it is in fact, done. Import rewriting makes sense in the situation that I have a diamond dependency (A -> B -> D.v1 & A -> C -> D.v2) and I'm willing to duplicate the two different versions of that transitively required library in order to isolate them while retaining both. This is by far the exception case, not the norm. Imagine if every package that used something as common as "fmt" from the standard library re-wrote and re-vendored it! Note that I have little care for the size of my working tree in an active development environment -- duplicated libraries on disk there per project is fine; disk is cheap. Duplication that ends up in version control is where concern lies, because this duplication has troublesome impacts over deep time, and the trouble can be pushed to other people who are then powerless to address it. ### repeatability Notice how I didn't say "vendoring". What everyone wants is repeatability. "vendoring" is one possible way to implement repeatability; let's phrase the conversation around the concept first. As pointed out earlier in the threat, repeatability is also maintained by systems such as Nix: hashes do wonders. Similarly, I've been using git submodules to get perfectly reproducible builds. Bower can pin dependencies by hashes. There's a huge list of concrete examples of repeatability without vendoring. Hash-based resource references solve repeatability. Vendoring may score points in the immediate offline mode. And I'm deeply pleased with importance placed on offline operation -- I share this priority the extent that I label my business cards "sneakernet advocate" -- but offline operation is orthogonal to vendoring and also available through other choices. It's good to have a command after which the build is guaranted not to need network; that command need not be `git clone`, and could just as easily be some other subcommand of the go tool. I think folk coming from other languages would be perfectly unsurprised by such a feature in the go tool, and we could have very satisfying outcomes from a command that does all resource acquisition and then stops. Vendoring has gained traction largely because it works without additional tooling, and that makes it the most contributor-friendly thing in the current landscape where the go tool has no chosen stance and thus the community as a whole is uncommitted. In discussing additions to the go tool, this impetus is made irrelevant. Vendoring has a variety of serious drawbacks. It gets repeatability right and *everything else* wrong. It's not transparent to libraries; it results in globally multiple histories for files; and it results in permanent bloat to a project source repo. (This was discussed before at length in a particular golang project forum and this table of comparisons was made back in 2013, which remains fully accurate today: https://gist.github.com/heavenlyhash/6343783 ) The most major threat to repeatability when using hash-based resource references is network available in the deep time sense: what happens when the organization behind mycompany.net goes out of business and drops their domain, or library bananapancakes is renamed to something more user-centric, etc. In tracking recent changes, this is not frequently an issue, but doing a bisect across a well-aged repo can become troublesome. Fortunately, this is solvable: The system must have a way to replace old network addresses with updated aliases. We can do this. ### composability I'm not sure this is in the discussion as such yet, but it's been mentioned in passing, and so I figured I might as well give it a name and a heading. As a user of go, when examining a new library for potential use, I regularly want to see if it builds. Thereafter, I want to see if its tests pass. This requires that the library specify it's dependencies; specifically, it means the library must have repeatability just like a "real" "program". Bundler and rubygems actually got this fairly right: specifying a semver dependency range in one file, and specifying the "locked", pre-resolved versions of everything depended on (including transitively) is a great example of unifying both composability and repeatability goals. Bundler fell short in that it still only resolves down to a precise semver string, where it should really resolve to a hash. In the javascript world, Bower did similar things, and also carried the resolve results all the way to a hash: this truly satisfies repeatability. We should take a page from these books. While it is possible to ship executables at the end of the day without tackling this (and that is the most important thing), as Matthew Sackman has pointed out, it's a severe cramp to developer usability if we ignore this. On the plus side, this is also possible to do later, since isolation and repeatability are solvable without a solution to composability -- but it may be worth thinking about it now, when discussing data formats. ### aside: this "libraries and programs are different" thing *doesn't work* in the field Treating libraries and programs differently has a hidden presumption: that I have any control over other authors. Regrettably, I lack total control over all programmers. (Imagine! We could forgo this entire discussion! World conquest by friday! Etc.) And even if everyone in the world reoriented their views to ask all present and future users whether a package should be a library or not, there's no guarantee we'd agree. And a time dimension is indeed a part of that discussion, unless we break free of VCS repository layouts entirely, which has not yet come to pass. As one example, Docker has some code that I'd like to use as a library. But they don't consider themselves a library, and as a result, they've already vendored about 5 megs of other sources (and if including history, a much larger amount even after compression). This situation is understandable -- they consider themselves a "program", and rightly so -- but nonetheless, it's become very difficult for me to reuse their code without forking (and I mean manually, by copy-paste, a highly undesirable outcome). And then AFTER copy-paste forking the sections of code I want, I have to rewrite all their imports again to fit in my project, since I'm already using several of the same libraries at the same versions. This entire process would be nonsensical made-work that actively distracts from real development, and with all due respect to all the authors in this scenario who are all understandably acting in their best interests, I want no part of this to be in my future for other golang proje cts. |
| Re: [golang-dev] Dependencies & vendoring | Chris Hines | 03/03/15 10:48 | It could be valuable to have the vendoring metadata available at runtime. I am thinking of asking a binary to dump out its version and the versions of its build dependencies. This would be trivial if the metadata was compiled into the binary in an accessible Go data structure. I don't think this is a slam dunk argument, but something to consider. Chris |
| Re: [golang-dev] Dependencies & vendoring | Sean Bowman | 03/03/15 11:06 | Aren't we already at the gates of version hell? I feel like the only reason the import system has worked so far is because we don't have a lot of "v2" libraries out there yet. The ecosystem is too young. I'm already used to repeating myself with Go. It's not the DRYist language in the world. And yes, I'd expect the compiler to generate an error if I use conflicting versions in my code. |
| Re: Dependencies & vendoring | Christine Dodrill | 03/03/15 11:42 | I think a better solution is this: import "import/path/that/has/some/slashes#commit-like" This has the advantage of also being reproducable in the filesystem: $GOPATH/src/import/path/that/has/some/slashes#commit-like" Thoughts? This is much better than introducing the same versioning hell that Gem and NPM suffer from (not to mention Haskell's Cabal). |
| Re: Dependencies & vendoring | Antoine Grondin | 03/03/15 11:42 | A problem with this approach is that if my project imports package A, and package A imports package B, by rewriting imports, I will modify the source of package A from importing `package.com/b` to become the vendored `internal/third_party/package.com/b`. Consider a bug is found in package A. Since we modified the imports, we can't just `cd` into the repo, create a change commit and send contributions back upstream. It's possible to do it by restoring the original source file, but not as easy as if package A was vendored verbatim. When we investigated how we wanted to deal with our third party dependencies, being able to contribute changes to our vendored code back to upstream was deemed important. We found that a good way to distinguish between our project code and third party code was to create 2 gopaths, appended together in the GOPATH variable. export GOPATH:third_party/:owncode/ Since `go get` fetches package into the first path it finds in GOPATH, this means we can use `go get` on third party deps and the repos are inserted under the right path. We also get to vendor all of our code in one repository, achieving the 1 GOPATH that is mentioned above. We wrote a blog post about how we deal with dependencies: https://www.digitalocean.com/company/blog/taming-your-go-dependencies/#whats-a-mono-repo We find that this is a clean and simple way to maintain and vendor all of our code. Import paths are not changed yet we get reproducible builds at any commit. We can modify parts of a project and immediately know all the thing we broke and fix them, since we can `go build ./...` to compile all of our code. The one downside is that Git will try to make submodules from third party repos, but the same would likely be true if we used the technique described here with import rewriting. On Monday, March 2, 2015 at 12:38:02 PM UTC-5, Brad Fitzpatrick wrote:
|
| Re: [golang-dev] Dependencies & vendoring | s...@box.com | 03/03/15 11:42 | A JSON file is something that nearly anyone can read and modify trivially. Trying to understand and make changes to a .go file like this is far more challenging and would reduce the audience of people who could build tools to automatically maintain dependencies and resolve issues. I don't believe the lack of comments is enough to jettison such a machine- and human-friendly format.
|
| Re: [golang-dev] Re: Dependencies & vendoring | Ian Davis | 03/03/15 12:15 |
This cant work in general. Does the commit hash have to be on every import in every file that uses the package? What happens if two files in the same project specify different commits?
|
| Re: [golang-dev] Dependencies & vendoring | Evan Shaw | 03/03/15 12:21 | I like the spirit of the proposal, but I don't like using "internal"
as the vendored code directory. I'd like to be able to separate my own internal packages from vendored packages, and creating a "vendor" subdirectory under "internal" makes an already long import path even longer. I understand and agree that we want to disallow importing vendored dependencies from other projects, but it seems like "internal" is being used because it already exists; not because it's the best name. |
| Re: [golang-dev] Dependencies & vendoring | Peter Collingbourne | 03/03/15 12:44 | Maybe something like import ( ) would work? On Tue, Mar 3, 2015 at 7:31 AM, Russ Cox <r...@golang.org> wrote:
|
| Re: [golang-dev] Re: Dependencies & vendoring | Christine Dodrill | 03/03/15 12:48 | On Tue, Mar 03, 2015 at 08:15:25PM +0000, Ian Davis wrote:It's a commit-like so you get the advantage of specifying git tags, git commits, svn commits, bzr commits/tags etc. -- Sam Dodrill shado...@gmail.com / xe...@yolo-swag.com +1 425 221 7761 |
| Re: [golang-dev] Dependencies & vendoring | Dmitri Savintsev | 03/03/15 12:59 | It looks rather clunky and ugly. My vote would be to use Go or INI (http://en.wikipedia.org/wiki/INI_file format is well-known and should be easy to parse) and to avoid JSON (mainly due to the lack of comments but also because of the syntax generally not very friendly to a human reader or writer). On Tuesday, March 3, 2015 at 4:56:51 PM UTC+1, ehedgehog wrote: On 3 March 2015 at 15:26, Brad Fitzpatrick <brad...@golang.org> wrote: |
| Re: [golang-dev] Dependencies & vendoring | Michael Schuett | 03/03/15 13:14 | It seems like INI is coming up a lot as well as Go. I think I and a few others are pushing JSON but seem to be in the minority. I am curious to see what comes of this poll though if anyone is interested in participating as it's hard to get a great idea since some people in favor of a specific file type post a lot more than others. https://docs.google.com/forms/d/1y9jmJBHk2-mml1vwTvVVTYkSM-YgxkzmLU9A1zuL26w/viewform?usp=send_form thanks.
|
| Re: [golang-dev] Re: Dependencies & vendoring | Ian Davis | 03/03/15 13:18 | On Tue, Mar 3, 2015, at 08:48 PM, Sam Dodrill wrote:I don't think I made my point clear. Surely the commit-like would have to be specified every time the package is imported which could be spread across dozens of source files. What happens when they get out of sync, or are missed? Ian |
| Re: [golang-dev] Re: Dependencies & vendoring | Ian Davis | 03/03/15 13:53 | On Tue, Mar 3, 2015, at 09:46 PM, Justin Scheiber wrote:
Yep I saw that, see my reply suggesting using go:generate to achieve the same effect.
Ian
|
| Re: [golang-dev] Dependencies & vendoring | Gustavo Niemeyer | 03/03/15 14:55 | It's great to see the approaches being successfully put to good use by the community in the last few years being commended as first-class solutions. Having a standard file format for that will be a very welcome improvement to these conventions. At the same time, it's sad to see this being approached as an answer to questions about dependency management, when it doesn't solve any of the weak points of existing solutions. In fact, it's remarkably odd that "approaches that require [...] new semantics inside the go command and toolchain" were rejected on the path of answering questions about "how to deal with dependencies and their versions", when the former is the implementation of the latter. The subject of this thread should likely have been "standardizing on a vendoring configuration file" instead. --You received this message because you are subscribed to the Google Groups "golang-dev" group.To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com. gustavo @ http://niemeyer.net |
| Re: Dependencies & vendoring | Karan Misra | 03/03/15 16:05 | Brad, I had asked a very similar question to Dave and Francesc during the Q&A session at GopherConIndia 2015. So you can imagine my happiness on seeing this discussion thread. Thanks for bringing this up. First of all, I have to say, that vendoring is truly the most pragmatic solution for reproducible builds in Go. Our compiler is super fast and we can afford to check in the source code of whatever open source libraries we want to incorporate into our product. However, to truly come up with a solution which can be accepted by everyone, we must address the problem of versioning and vendoring separately, both for programs (the ones who should be VENDORING their dependencies' code) and libraries (who also are equal citizens in the Go world and are allowed to develop against a particular API of other open source libraries.) Also, the solution to both these problems should ideally be handled by the proposed "go deps" tool so that the community can just move on from this long hotly debated argument and focus on generics instead (I kid! I kid!) I am trying to draw inspiration from how other eco systems have approached this problem. I have worked extensively with both the Ruby/node.js ecosystems so have a feel for what works, and what doesn't. I might get lynched for saying this, but I liked the "package.json" concept followed in node.js. And my proposal is based around that idea. Common Ground
Libraries
* creating tags to reflect own version should work Programs
The "go deps" command would be responsible for a few things:
The conflict resolution would take care of stopping situations like so:
Its natural for something like this to arise and the proper way to get this fixed would be to then send a PR upstream to pq to get its dependency updated to logrus v2. This also highlights the need to have proper versions (instead of just tags or hashes.) With versions, a situation like this could still work (with the Go compiler giving the final go ahead if everything compiles):
Semantic versioning dictates that (ideally) all v2.x.y versions of logrus should have a stable public API. So, "go deps" could resolve this by vendoring the actual specific version specified by the program (i.e 2.1.4) and counting on the deps.go file in both pq/go-dockerclient correctly specifying that they are okay with logrus v2.x.y. A "go build" would deliver the final verdict, but that is something which the dev would be doing anyway (as part of ensuring that all tests are still running green.) As someone said earlier, Go is reaching that point where a rush of v2 libraries is imminent and to prevent chaos, it is important to have a solution which gives the ability of "versioning" dependencies to libraries as well. I know I have glossed over a lot of details (how do you specify sliding dependencies, what format of deps.go, etc.) but I wanted to get the idea across beyond a REM sleep cycle wiped it clean from my head! And irrespective of what eventual solution emerges from this, I am really glad that this discussion is happening now. On Rewriting? Could the go toolchain not automatically augment the GOPATH to include the current root deps.go "vendor" folder? With all the rewriting, the novelty of bringing in a new version of a dependency and seeing "what has he changed" sort of gets diminished. Its not the end of the world, but something to consider. Regards, Karan Misra |
| Re: Dependencies & vendoring | Aaron Lefkowitz | 03/03/15 16:19 | I like a few things about this proposal: 1. That we're settling on something for the community. 2. That it uses the internal mechanism. 1. The idea of using an external JSON file for configuration. JSON was never meant for configs and it continues to be a poor choice. The reasons should be obvious. For an example irritating trailing commas that unlike Go struct literals are not uniform in their placement but one always has to be left off the last entry, and surrounding keys in quotations to be conformant. Please consider TOML or the best choice: Use the Go source files. Everything in Go so far uses magic comments to achieve it's goals (build tags, documentation) and I'm think it's best to not change this. As several have pointed out simply having the commit hash/tag/branch at the end of the import path seems reasonable. It would require a backwards incompatible change to how imports are defined but it very much fits the theme of struct tags etc. 2. That it leaves libraries on it's own, if we're going to half solve the problem and fragment how we write code today, I think it's simply not a very good solution. "Are you writing package main? Do this! Are you writing anything else? Good luck!" I guess I don't see the problem with retracting this proposal completely until something that satisfies all areas of Go development is on the table while tools like godep and nut continue to hold the fort in a non-official way. 3. The overly long import paths. They're already an eyesore without adding another 4 directories of depth to them. Some proposals here liken to shortening them. I think that if they have a version number attached to them ie: "github.com/BurntSushi/toml" "2387afef8828" Then they are automatically referred to from the vendored root of "currentpackage/internal". It is sort of magic which I agree is bad in Go but the entire Go tool is convention over configuration so far, so a little more couldn't hurt. |
| Re: Dependencies & vendoring | pre...@gmail.com | 03/03/15 16:19 | On Tuesday, March 3, 2015 at 5:38:38 AM UTC-8, pic...@gmail.com wrote: Why not instead just add support to Go for an optional tag or commit ID to the import string, along the lines of what Joshua Marsh is suggesting: Suppose those imports are in package A. Now package B imports "github.com/johndoe/mylib 0.9". And Package C depends on A and B. Which version of "github.com/johndoe/mylib" should be chosen when building package C? Or let's say, B imports version 1.0.1. So, in theory, the dependency management tool should automatically pick v1.0.1 of mylib. But why? Can it be proven that 1.0.1 version of mylib is less buggy, and compatible with 1.0 clients? It can't be. Versions are fickle. That's pretty much why not. |
| Re: [golang-dev] Re: Dependencies & vendoring | Justin Scheiber | 03/03/15 16:20 | I believe that's where tooling comes in. Also, see Russ's comment earlier in the thread. From what I guess, vendoring would look like this: A central file defining the dependencies:
Then use these packages like normal in your source: import ( ) The tooling would be responsible for ensuring consistency, that the correct version is checked out, etc.. |
| Re: [golang-dev] Re: Dependencies & vendoring | Mihai B | 03/03/15 16:46 | I don't think there is a common ground yet. Has the special directive (i.e. like go:generate or the vanity import) proposal already been ruled out in favour of a config file? IMHO the config file adds friction compared with the comments/directives just like go:generate commands or the vanity import would do if they were placed in a build/config file. We already have the vanity import which enforces a custom import path so why don't we specify a specific version (be it commit hash or tag) the same way? It totally makes sense to me. Either way it would be great if someone with authority would make it clear if this thread is only about a potential config file and its specifications or if go:generate like directives are considered as well.
|
| Re: [golang-dev] Re: Dependencies & vendoring | Peter Vessenes | 03/03/15 17:10 | Of all the proposals, the #commit-like append makes the most sense to me, so I'll try and answer your question: It's easy enough to pick a behavior: Allow them and import the two commits into separate directories on go get if they're not there. Alternately, deprecate this as a possibility, and require all be at the same commit level without a build directive. Alternately, only allow one commit-like across the package without renaming the import, the others just use the standard URL to refer In the second and third case, go vet and goimports could help do the work of keeping things in sync. As a middlingly experienced Go Dev, I really hate the idea of adding cognitive load to the build process. If a build doesn't work for some reason, the idea that I now need to know where a special file is, how to check a special file, etc.. Seems evil to me. Go's cognitive load for compile/build/import is very, very low right now. I think it's a feature of the language. Adding a file like this seems like it will be a constant temptation to abuse into adding another layer to the process. Consider when adding the proposed file that every go debugging session and tutorial will need to mention that the wrong commit may be specified in a totally different place than your main code. Annoyances like that add up, in my opinion. They are easiest on the very smartest developers and hardest on the beginners and less smart. |
| Re: [golang-dev] Re: Dependencies & vendoring | Andrew Gerrand | 03/03/15 17:40 | I don't think anything about the build process changes. The go tool needn't know the file exists. This is just formalising something that people are already doing. With a standard file format we actually reduce complexity in the ecosystem. |
| Re: Dependencies & vendoring | jeane paul Soliva | 03/03/15 21:25 | Greetings, one thing I did like in Go apart from others like Ruby or JS is, I don't need to write package.json or Gemfile. I like go get ./... and everything just work naturally |
| Re: [golang-dev] Dependencies & vendoring | Jonathan Roes | 03/03/15 21:25 | If we're going to call the file vendor.go, the package vendor, and we're going to be using "vendored" as a verb so often, I can't help but think that we might as well be consistent and use "vendor" in the path instead of "internal."
|
| Re: Dependencies & vendoring | Matt Cudmore | 03/03/15 21:25 | We have had go get and in-source build flags since the beginning, and we have already seen the addition of go:generate meta commands in comments. I don't see why go get is not to be enhanced, and why a new config file will be added to the mix since in-source comments are already significant. |
| Re: Dependencies & vendoring | aos...@gmail.com | 03/03/15 21:35 | I'm late to this party but I've been doing this my own way for quite some time: This means you need a local src and pkg directory but at least everything is self contained. |
| Re: [golang-dev] Dependencies & vendoring | Nathan Youngman | 03/03/15 22:32 | I'm not sold on using a Go file to store SHA commit hashes. Perhaps this is just the way I use godep currently. When working on an app, I use godep to save the state of the world inside my main source tree. I'm not manually editing the config file, just like I never would manually edit a Gemfile.lock in Ruby-land (excepting merge conflicts :-( ). When patching dependencies, I leave my hermetically sealed bubble and work on a feature branch of that library. This allows me to push my changes upstream for hopeful inclusion (yay, collaboration, win!). I treat the Godeps subdirectory (now internal/github.com/*) as "DO NOT EDIT", simply a snapshot of work I did out in the world. This particular workflow makes "godep restore" quite necessary (implying bidirectional rewriting of import paths). But the point is, I'm not mucking about with SHA commit hashes, that's what we have tools for. I'm also not providing tags or branches in some config file. If I want to vendor a particular branch, I use commands like "cd" and "git checkout" and then take a snapshot. For me, this is the simplest thing that could possibly work, but no simpler. Mind you, I'm relatively new to this whole concept of copying third-party libraries into an internal/ folder. I'm sure I have much yet to learn, especially when applied in large teams. Nathan.
|
| Re: [golang-dev] Dependencies & vendoring | Brian Picciano | 03/03/15 22:40 |
My understanding is that we're primarily discussing the format of the file the vendor information is stored in and the basic details of how vendoring will work. It's likely that tools will sprout up around this that will allow for what you describe, regardless of what format is chosen. |
| Re: [golang-dev] Re: Dependencies & vendoring | Martin Bruse | 03/03/15 22:43 | I also really like using the string in the import declaration to define version, but why add non path compatible characters?
Why not use import ( "github.com/a/b/ver-1." ) Then you could use 'go get', or a completely new tool that: - Downloads the latest version of 'github.com/a/b' to with a tag that begins with 'ver-1.' to '$GOPATH/src/github.com/a/b/ver-1.'. - Rewrites all internal imports inside it to use the imported path. - Uses itself to download all of the missing deps of the new package (thus downloading all missing deps, with correct version, of the new package). - Is fully compatible with regular import paths to support packages depending on regular 'go get'able paths. This would solve the problem of A depending on B depending on ver 2 of C, and A depending on D depending on version 1 of C, because they would, for the go toolchain, be two separate packages. It would also allow package maintainers to fix non API breaking bugs in new minor versions, while introducing API breakage in new major versions. It would not, of course, remove the problem of this package being included twice on drive and in the binary, but no other suggestion solves that either. |
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 03/03/15 22:46 | why not go the full measure and have more options like other languages: import ( "github.com/a/b", "~>1.0"
|
| Re: [golang-dev] Re: Dependencies & vendoring | Martin Bruse | 03/03/15 22:54 | Because it would not be backwards compatible, and it would not in as
simple a manner define that the different versions live in different directories on disk (and WHICH directories). |
| Re: [golang-dev] Dependencies & vendoring | Michael Schuett | 03/03/15 22:57 | So it seems like we are a little all over the place with ideas right now but I would like to get one thing ironed out if we can and I think it will greatly help move the conversation forward. https://docs.google.com/forms/d/1y9jmJBHk2-mml1vwTvVVTYkSM-YgxkzmLU9A1zuL26w/viewanalytics?usp=already_responded shows that just over half of the people actively contributing to this thread would like to stick with keeping this in a go file. From reading above people proposing .ini did not seem opposed to using go as well but just preferred using the .ini format. I prefer .json just because all my vendor toolings in the past have used it but it's just preference and I do see the strength of using a go file for this. Does anyone feel strongly enough to argue why we should not be using a .go file for vendor config? On Wed, Mar 4, 2015 at 1:40 AM, Brian Picciano <mediocr...@gmail.com> wrote:
|
| Re: [golang-dev] Dependencies & vendoring | Nathan Youngman | 03/03/15 22:58 | If this is file is maintained by tools, *.go doesn't seem like the most natural format. In this thread I've seen considerations like comments and commas as issues with JSON and the ability to limit to package main as a potential benefit of *.go. None of this is enough to win me over. A *.go file feels like it should be capable of doing more, like there is some reason we decided to use .go as a data file, but it seems unlikely that this would be the case because of +build ignore. A *.go file also seems like it should be able to go anywhere, but in practice it would probably need to be internal/vendor.go as this special case just to store the SHAs of transient dependencies as comments? Hm. Appending comments to import lines in a centralized file is hardly extensible. What if we want to track more than just the SHA commit in the future? Having a standard set of keys in a simple JSON file with some means for tool-specific extensions would provide this. The JSON deserialization libraries are already happy to ignore keys that a particular tool doesn't use. Nathan.
|
| unk...@googlegroups.com | 03/03/15 23:08 | <Ce message a été supprimé.> | |
| Re: [golang-dev] Dependencies & vendoring | Michael Schuett | 03/03/15 23:13 | I do agree with you Nathan. I was actually just trying to workout what exactly a *.go implementation would look like and everything seems like it would be easy to abuse and syntax wise is just a pain. I think the following json allows for a simple and extensible way of managing dependencies without having to litter your imports with comments which I think will make our otherwise clean *.go files start to look a little more nasty. This also has the advantage of looking in one file and seeing what the package is all pulling in. How often do you really need to add a comment for a dependency? I know I have never run into this issue. { "require": [ { }, { }, { } ] }
|
| Re: [golang-dev] Dependencies & vendoring | Nathan Youngman | 03/03/15 23:18 | It is a good point that the SHA commit hashes being stored are not of the packages being imported, but of the repositories containing them. If this file is generated by a command like "godep save", it may not matter much, because all the commit hashes will be the same for a package in a given repository. Rather than using path patterns, a tool could just always do store the repository paths rather than full import paths. A savings of 4 characters! :-) Nathan. On 2 March 2015 at 23:59, Dmitri Shuralyov <shur...@gmail.com> wrote:
|
| Re: [golang-dev] Dependencies & vendoring | Alex Smith | 03/03/15 23:18 | I agree. I just see that this as being a tumbling block for new users, this can always be fixed or cleaned up later on. Alex |
| Re: [golang-dev] Dependencies & vendoring | Nathan Youngman | 03/03/15 23:31 | I would lean towards the more verbose key/value pairs like {"repo":rsc.io/arm/armasm", "commit": "616aea947362"}. It's ugly and seems wasteful, but it provides more flexibilty down the road. Since we already have all the code in our repo, I assume the reason why we want this metadata at all is to restore the world outside our hermetic bubble to match up? Say I submit a patch but it hasn't been merged upstream yet. Maybe a tool would like to store the fact that I had these other "remotes": ["github.com/libgo/arm"] when I took my snapshot. Then if said tool can't find "616aea947362" on a colleagues computer, it can add the remotes and see if that helps. That's just an example. The point is simplicity and extensibility. Nathan. P.S. I have add comments for dependencies before. Usually that I can't use some new thing until such and such. It's fine to put those comments in the code alongside the import statement though. No need to stuff comments in the JSON. -- |
| Re: [golang-dev] Dependencies & vendoring | Alex Smith | 03/03/15 23:40 | While I like this idea (it is useful, especially for alpha/beta) how would backwards comparability work? Is it a tag, branch, etc. with standardized naming? This is *exactly* why I started using that weird go alias, it allowed me to "go get" a given library at a given time. |
| Ce message a été masqué, car il a été signalé comme étant abusif. | |||
| Ce message a été masqué, car il a été signalé comme étant abusif. | |||
| Re: Dependencies & vendoring | Pierre Durand | 04/03/15 01:25 | I think we just need godep + versions constraint.
|
| Re: Dependencies & vendoring | Ulrich Schreiner | 04/03/15 02:51 | hi,
it would be great to only specify the file format. i don't like tools like nut or godep, i prever https://github.com/robfig/glock, because it works great with the existing go toolset and does not change import-names, does not remove canonical import comments, etc. so as long as only the format of the dependency file is specified, everyone can use the tool and approach best suited for his needs. </usc> |
| Re: [golang-dev] Re: Dependencies & vendoring | Luna Duclos | 04/03/15 04:38 | I personally also have an aversion to maintaining several apps with each their own vendored dependencies, it makes contributing to any of them a pain and I don't feel it provides much value if you trust your repo maintainers at all.
|
| Re: [golang-dev] Dependencies & vendoring | Darko Luketic | 04/03/15 06:39 | go dep get github.com/my/package#123456
or go dep get github.com/my/package and go dep up github.com/my/package#234567 or go dep up //update all go dep init internal // = internal package root save path ^not required, because this would be called initially if no _internal.json or _vendor.json was present with the "internal" default value Create a _internal.json or _vendor.json json easier to deal with, because of std support |
| Re: Dependencies & vendoring | Richard Fliam | 04/03/15 06:39 | One of the things that strikes me about this solution is this looks a lot like git submodules, mercurial subrepositories, svn externals, and the Bazaar externals plugin. As the suggested implementation almost precisely matches git submodules (indeed I though your first rough TBD config was a gitmodule file), we should at least be taking some of the lessons learned from those projects. A quick search on the subject gives us gems like "Only later do all the pitfalls and traps come and bite everyone, every day" (medium.com). Some of the negatives are discussed here as well. |
| Re: [golang-dev] Re: Dependencies & vendoring | Evgeniy OZ | 04/03/15 06:39 | Vendoring should be used only for the dependencies of binaries, not for the dependencies of packages Well.. it's strange. Binaries in windows, linux or os x version? How IDE can give code completion if all APIs will be hidden inside binaries?.. Or I'm missing something. JSON doesn't support comments, and for configs it's important. So I vote for Go config format :) On Tuesday, 3 March 2015 00:54:11 UTC+3, Andrew Gerrand wrote:
|
| Re: [golang-dev] Dependencies & vendoring | Richard Fliam | 04/03/15 06:39 | Clojure's canonical build tool Leiningen uses a configuration file and build file in of course Clojure (project.clj). This has been proven to be one of the most useful decisions the Leningen guys ever made. You can write, and register plugins for Lenigen very easily as result. I think that is the most compelling argument for using .go files over JSON. We are essentially laying the foundations for a true build tool here. Make it as flexible and useful as possible. Every build "system" in history that failed to use a more complete language is honestly terrible. Have you ever had the displeasure of using ANT? It is god awful. Let's not make that same mistake. |
| Re: [golang-dev] Dependencies & vendoring | Peter Waldschmidt | 04/03/15 06:59 | Store configuration in a .go file that must be always named deps.go ---------------------------deps.go-------------------------------------- package mypackage // use a build tag to prevent compilation if wanted at parse-time only. import ( "deps" ) var mydeps []PackageDependency = []PackageDependency{ {Pkg: "rsc.io/arm/armasm", Tag: "616aea947362"}, {Pkg: "rsc.io/x86/x86asm", Tag: "v1.4.2", Path: "internal" }, } ---------------------------deps.go-------------------------------------- In deps package: ---------------------------deps runtime package-------------------------------------- type PackageDependency struct { Pkg string Tag string // commit ref referencing a tag or hash Path string // Optional path to "vendored" copy relative to the root of this package } ---------------------------deps.go runtime package-------------------------------------- 1. This can be parsed by the go toolchain, or a third party deps toolchain. 2. It also (optionally) compiles into the package and can be used by the program to report its dependencies at runtime. 3. People that want to vendor code would use a tool like godep to read this file and populate their vendor folders. Or alternately, godep could generate this file from existing dependencies. 4. go get could use this format to fetch the proper tagged versions of dependent packages rather than the master branch of each dependent package. 5. If a "library" includes this file, This seems like a good blend of a lot of the ideas I've seen. And it's totally optional and backwards compatible and extendable for the future. |
| Re: [golang-dev] Dependencies & vendoring | Nathan Youngman | 04/03/15 08:23 | The benefit of using a real language for Leiningen, Bundler and presumably Gradle is that you can do more things. So far the proposals have been using go as a data file that is parsed and ignored by the build toolchain. This doesn't provide those benefits. Now, if the deps.go file was executed by the dependency tool, then it could get interesting. Conditional dependencies, perhaps? Personally, I'm still not sold on deps.go vs. a straight-forward deps.json. But hopefully someone can suggest how this is beneficial outside of preferring Go syntax to JSON (that's a given). Nathan. |
| Re: [golang-dev] Dependencies & vendoring | Nathan Youngman | 04/03/15 08:32 | On Tuesday, 3 March 2015 15:55:57 UTC-7, Gustavo Niemeyer wrote:
I agree, and perhaps we can all reframe the discussion around that. Firstly, what is the purpose of storing "Rev": "616aea947362" at all? We have all the code. I have my own ideas as to why this is useful: to restore the world outside the hermetic bubble of vendored code, making it easier to collaborate with upstream sources. But I don't think the OP made it clear what the purpose of this configuration is. Nathan. |
| Re: Dependencies & vendoring | Tartari Giacomo | 04/03/15 08:33 | Very nice tool thanks for sharing. And If it could read the revision from comments in the source file a config file would not be needed. Giacomo |
| Re: [golang-dev] Dependencies & vendoring | Nathan Youngman | 04/03/15 08:42 | Hi Alex, I'm not totally sure if I understand your question. In my mind, this configuration is a generated file just like godep. It is based on the state of the world when using "save" to vendor all the code. If you want to use a particular tag or branch of a third-party repo, you just check it out. Then godep save saves the commit hash (Rev) that is currently checked out along with all the code currently checked out. On a another computer, someone can already build and use the app because it contains all the code. But if they want to collaborate upstream, they can run a single command that puts external repositories into a state matching what has been vendored (assuming none of those repositories is dirty). Then they can make changes, send pull requests, and snapshot those changes back into the main repo. This is how godep works, or at least, how I work with godep presently. All this gets back to what the purpose of this file is in the first place. :-) Other people have a different idea as to what this is for, and I'd really like to hear the Go Team's take on why they feel the need to store commit hash (Rev) at all. What would it enable in their workflow that necessitates having this extra file and the potential merge conflicts to go along with it? Nathan.
|
| Re: [golang-dev] Dependencies & vendoring | Humberto Anjos | 04/03/15 09:02 | IMHO, and echoing some other comments here, the main benefit of using Go as a file format is being able to use code instead of configuration. So I see a deps.go as code to be ran, not configuration to be read, with all the flexibility and possibilities involved (some that come to mind: conditional dependencies, revision locking, vendoring, code generation...) I like the main gist of Karan Misra's proposal, but I still haven't envisioned how his deps.go would work. I lean towards a go test-like solution, myself, but I need to organize my thoughts on the matter first :)
|
| Re: [golang-dev] Dependencies & vendoring | Brian Picciano | 04/03/15 09:31 | I like this, but I would propose to make it more "go test"-like. Instead of a slice of dependencies being exposed, a single variable-per-dependency with a particular naming scheme could instead be exposed. Something like this: ``` package whatever // build tag to prevent compilation, or not, go test doesn't use one import ( . "deps" ) var DepYaml = Dep{ Pkg: "github.com/go-yaml/yaml", Tag: "49c95bdc", } var DepMySQL = Dep{ Pkg: 'github.com/go-sql-driver/mysql", Tag: "a197e5d405", } ``` This has the following benefits: * Easy to read, even easier than the json equivalent, while still being extensible. * Familiar to anyone who has used go test/benchmark. The implementation would be similar as well, I imagine. * Allows for dynamic dependency declaration, since you could do something like `var DepFoo = func() Dep { // code here }()`. To be fair, Peter's original suggestion also allows for this. |
| Re: [golang-dev] Dependencies & vendoring | Michael Schuett | 04/03/15 09:32 | No attacking anyone as I know tone can be lost over email. Under what case would we want conditional dependencies I just see it as becoming a huge mess. Go already handles making sure test imports aren't included in your production binary and that is the only conditional dependency I can think of. It is needless complication in my opinion. In what way does a *.go offer better revision locking or vendoring that you would not get out of a simple config? Maybe if you are using tags? however this would have to be solved with writing another file in any case that would keep track of the hash of the installed version. I think that is a little out of scope of OP's proposal though. On Wed, Mar 4, 2015 at 12:07 PM, Peter Waldschmidt <pet...@gnoso.com> wrote:
|
| Re: [golang-dev] Dependencies & vendoring | Michael Schuett | 04/03/15 09:33 | Guys I am really not understanding the usefulness of assigning dependencies to a variable. One it seems like this would make implementing the tooling a royal pain.. I don't even know how this would be handled personally. Could someone please enlighten me to the advantage of this? |
| Ce message a été masqué, car il a été signalé comme étant abusif. | |||
| Re: [golang-dev] Dependencies & vendoring | Richard Fliam | 04/03/15 10:14 | Here are a few examples of why being able to execute gocode would be useful:
This list is endless, as are the use cases for it. When pulling a dependency custom configuration will often be required. This can (and often is) be handled by custom scripts. Many of these tasks require parsing gocode to do, which as I mentioned above is optimally done in go. |
| Re: [golang-dev] Dependencies & vendoring | Pablo Astigarraga | 04/03/15 10:27 | Let's see if we can come to an agreement on the objective of having version metadata (either on a separate file or as part of the imports, which I dislike but remains a possibility): in my mind the purpose of having versioning information on dependencies is to be able to fetch all of them and set it to a specific version that is known to work on new environments, vendoring makes this problem irrelevant as applications are already shipped with all their dependencies included and set to a known working version, but vendoring is also cumbersome to maintain and makes changing dependency versions painful so we're trying to find a way of avoiding it. Our objective is to be able to reproduce the environment needed to build a project without having to commit the dependency tree, this is something that go get *almost* provides: it determines the dependencies and fetches them to a place we can determine using GOPATH, the fact that all dependencies are versioned repositories is great as it ensures we get versioning capabilities for free, all we really need is to use the relevant VCS to checkout the desired versions locally, so anything any VCS can understand as a descriptor of a version is fair game: commit SHAs or tags both fit the description and both commit history and tags are fetched by go get alongside the code. Do we agree with that being the problem this thread aims to tackle? It's also important to note how little is actually missing to solve it given how go get works today, isolation can already be achieved by something as simple as modifying the GOPATH, version setting by taking advantage of the versioning data in the dependencies. My main issue with other approaches like having a privileged code file dedicated to this problem is that it seems like an awful lot of overhead for solving such a small gap between what we have today and what we want, whatever Go adopts is something we'll be stuck with for the foreseeable future so I would encourage all of us to look for small, incremental improvements over what we have today instead of finding a "be all, end all" type of solution for dependency management in general, as somebody pointed out earlier: this problem is one that the community has been working on already and there are plenty of solutions out there, we have the privilege of being able to look at them, compare them and learn from how they attack the problem before we attempt to come up with a whole new approach.
|
| Re: [golang-dev] Dependencies & vendoring | Richard Fliam | 04/03/15 11:06 | > Vendoring is also cumbersome to maintain and makes changing dependency versions painful so we're trying to find a way of avoiding it. This is actually exactly why you would want executable code. As I mentioned in my earlier post git's go at vendoring is painful if you are at all tightly coupled. With executable code you can alleviate much of this pain. If you wish for development purposes to simply point at the head of a remote branch, you can do this with executable code but not with a simple json config file. Obviously this would be inadvisable in most situations, but for many it would be perfect. |
| Re: [golang-dev] Dependencies & vendoring | Nate Finch | 04/03/15 11:50 | In general, I like that Go has no configuration files, however, I think this deps.cfg file or whatever, is ok, because it's not used for building, and it doesn't exist in your main code. The layout of your application's code will look something like this: go build and go install and go get don't need to know anything about deps.cfg. They don't read it at all. You can still go get this code, and it'll Just Work™. The only tool that needs to understand it and work with it is go deps (or whatever it'll be called), and then you only need to use that command when you're vendoring dependencies for the first time, or updating to a newer version of a dependency. In general, updating should be rare (if it's not, you may want to consider why the external code you're depending is churning so much... it's probably an indication that you shouldn't depend on it). As for the format, I have to agree with those that say that JSON makes for a terrible config language. In theory, this will always be machine-written and -read, so it doesn't really matter.... but having something human readable and writable can make a big difference in real life. However, I also agree that the configuration file should be in a format that can be read using the std lib. I don't think that making it a runnable .go file is a good idea. For one, runnable code during project configuration is how Ruby has gotten into trouble so many times with gems doing nasty things. For another, the go tool would have to know to *not* build that code when doing `go build ./...` from the root directory. So... unless we're willing to put a different configuration language in the std lib (like TOML, which I love), then I think JSON is the least bad choice. But really, let's put TOML in the stdlib. That would be amazing. |
| Re: [golang-dev] Dependencies & vendoring | Tim Henderson | 04/03/15 12:58 | + 1 million to Eric's post. Vendoring is a bad solution to dependency management and import rewriting makes it worse. It is true that we often must do these things in the Go community, but that is only because we do not have better tools. If you, the go authors, don't immediately want to solve the dependency management and version management problem then you should instead tackle packaging and allow binaries to depend on packages (during build). I vote no on this proposal. Vendoring is a stop gap and should not be formalized. -Tim On Tuesday, March 3, 2015 at 1:23:47 PM UTC-5, Eric Myhre wrote: Whatever comes of this discussion: Distancing any proposed model from how Google works internally is going to be difficult, but necessary. |
| Re: [golang-dev] Dependencies & vendoring | Peter Waldschmidt | 04/03/15 12:58 |
-- |
| Dependencies & vendoring | Benjamin Measures | 04/03/15 13:35 | > But if library A depends on B,
the maintainer should have a mechanism to tell his users which version(s) of B are fine, and which are not. The maintainer cannot know this, since there are versions of B not yet written. It is precisely this false foundation that causes dependency trees to rot. |
| Re: Dependencies & vendoring | yiyus | 04/03/15 15:14 | I would like to point out that the configuration file can be very useful on its own, even when not vendoring external dependencies. This is the use case I have in mind: It would be possible to create a deps.cfg file (or vendor.go or whatever) when you successfully build your package or, even better, when a build passes all the tests. At some point, you could decide to vendor some or all the external dependencies in an internal directory but, even if you don't, the information on that file is very valuable. For example, I would not vendor golang.org/x/ packages in my personal projects (I trust golang.org more than me), but I would commit the deps.cfg file to know which was the last version of the dependencies that worked, so I (or the user) can always reproduce a successful build. -- - yiyus || JGL. |
| Re: [golang-dev] Re: Dependencies & vendoring | Daniel Skinner | 04/03/15 20:56 | As Andrew points out, this proposal would be formalizing what's already occurring in the wild, which is an optimistic view point. As a community, I agree this would be a good idea. But looking towards the future (Go 2), I'd be cautious of adopting anything official like `go dep` along this path. Cautious like generics-cautious. I'd recommend getting back to the basics, looking at GOPATH (https://golang.org/doc/code.html#GOPATH) and the intentions there at the time those design decisions were made. Vendoring feels at odds with what GOPATH represents and has enabled. One of them should probably just disappear. On Mon, Mar 2, 2015 at 5:47 PM, Russ Cox <r...@golang.org> wrote:
|
| Re: [golang-dev] Dependencies & vendoring | Keith Rarick | 04/03/15 22:52 | On Tue, Mar 3, 2015 at 10:32 PM, Nathan Youngman <he...@nathany.com> wrote:
> I'm not sold on using a Go file to store SHA commit hashes. Perhaps this is > just the way I use godep currently. Your existing godep workflow would probably not have to change. Storing this info in a .go file instead of a .json file makes little difference to godep—it is just another syntax for the tool read and write. |
| Re: [golang-dev] Re: Dependencies & vendoring | Ulrich Schreiner | 04/03/15 23:45 | hi, i hope this thread is not to agree on import path rewriting. this always collides with canonical import path checking. it only works if the toolset (nut or godep) removes the import comment from the libraries which foils the whole thing, imho. vendoring works if you have a separate central repository with all vendored libraries. you can do that inside of google or you can create a github organisatio where you copy (fork) all your libraries which you want to use. but i don't see any advantage if you have multiple repositories and every repo has it's own copy of libraries. as i wrote earlier i think another good solution is to trust your library developers and pin your cloned libraries to a specific version. this can be done with robfig's "glock" and it seamlessly integrates with the whole "go ..." toolset. you have to have different GOPATH's for every project, yes. but with vendoring-by-copy-and-rewrite you can work with one GOPATH but you will also have multiple versions of your libraries in different locations. so my request is to only commit on a config file format. tools like "godep", "nut" or "glock" can use this version information and do different things. some people think it is great to copy sublibraries and rewrite the source with godep/nut ... ok. other ones (like me) use different GOPATH's and pin the version of the libaries with tools like glock. i trust my library developers and use their canonical import path as they declared. if there is a common dependency format everyone can use the tool best suited. just my 2 cents ... </usc>
|
| Re: Dependencies & vendoring | Rob Figueiredo | 05/03/15 07:00 | It's pretty clear that everyone is on board the vendoring train, but I wanted to share the dissenting viewpoint for some variety. The analogous non-vendoring approach is where you have: - The same file of third party repos and revisions - A tool that can save the current state of your GOPATH dependencies - A tool that can sync your GOPATH with the revisions listed in the file - One version of any single package is used globally. The developer finds that a particular snapshot of GOPATH revisions works for their project, and they snapshot that. Libraries do not get their individual version of dependencies. - Avoids repo bloat / commit noise / gigantic diffs. To update a library, only a single line of text changes. The tool can run in the continuous build to ensure that all dependencies are recorded, and it can run as the first step in deploys to ensure that they are all up to date. The downside of course is that a dependency can go offline. In that case, the continuous build would notice, a developer can upload their copy as a fork and rewrite imports. It has not happened to us yet, although I can imagine if you have 1k+ dependencies that may change. However, even that process could be automated by the continuous build. We use this strategy at work via glock[1] to manage ~100 dependent packages for ~20 developers for the past year, and it works really well. |
| Re: [golang-dev] Re: Dependencies & vendoring | Craig Weber | 05/03/15 07:05 | +1 --You received this message because you are subscribed to the Google Groups "golang-dev" group. |
| Re: [golang-dev] Re: Dependencies & vendoring | Ben Darnell | 05/03/15 07:29 | On Thu, Mar 5, 2015 at 10:00 AM, Rob Figueiredo <rob...@gmail.com> wrote: +1
Dependencies going offline is (or was) a common problem in the Python world, and as a result it is common (and well-supported by the standard tools) for companies to maintain a cache/mirror of packages they depend on. Github, Google Code, and Bitbucket are more reliable than what came before, but I think the problem of unavailable dependencies deserves more support than "notice when things break and rewrite imports at that time" (in particular, most outages are transient - you need to be able to pull from a mirror without making it inconvenient to go back to the mainline). This could be accomplished with support for aliases in the GOPATH-syncing tool: map import paths to one or more alternate repositories that can be used to search for the required revision.
Glock looks great; I'm going to try switching to it. -Ben
|
| Re: Dependencies & vendoring | Ralph Corderoy | 05/03/15 07:42 | Hi Brad, I agree with others on the threads that the syntax is noisy. The problem with JSON, INI, etc., is they don't sit well with the Unix command line. Given the current need seems to be for a two-field record, can't we go with the time-honoured record per line, white-space separated fields, `#' as the first non-whitespace is a comment, format? It's low on noise, easy to parse, not too flexible so ad-hoc command line parsers have to jump through hoops, isn't XML, and, given there's no Javascript in sight, isn't JSON. If the simple format can't cope with future needs, we'll better know then what's needed. Cheers, Ralph. |
| unk...@googlegroups.com | 05/03/15 07:43 | <Ce message a été supprimé.> | |
| Re: Dependencies & vendoring | Adrien Delorme | 05/03/15 07:43 | I like the idea of having the revision in the import path ` import ( "package1#revision" // caches revision in some internal path in $GOPATH/src/package1-revisions/.revision/ or not "package2" // usual gopath ) ` It's practically the same of having another file, but when I open my go file I see what version it is using. Then if you are scared that the repo owner screws/deletes/somethinwrong its repo, just add a `go vendor save` command that will cache deps into your package. So when someone does `go install` it stores things automagically. |
| Re: Dependencies & vendoring | mat....@coull.com | 05/03/15 07:43 | My 2 cents.. We currently use a single vendor folder for managing package dependancies across a few production apps, and frankly have had no issues with it. It's a simple way of managing a production build state, that's all. I can see how a complex app with ever changing external packages could get annoying, and in that sense a config file is a pretty simple solution - i mean who can't read nicely printed json. I find I mostly work out of my GOPATH and only update vendor folders when I'm completely happy with a current package version - they are in effect a barrier to unknown change, you have to physically do something to it to make it different - a good step to reproducible builds. They're not meant to give you multiple GOPATH folders that you have to switch to everytime you move to tweak something in a new app. That's how I see it, and seem to work anyway. Package management in Go has never really bothered me - I like being able to go and see exactly what i'm importing. Sharing a state between multiple developers doesn't really get much easier than a vendor folder as well as the fact that you can ALWAYS build from an app repo. No packaging hell :)
|
| Re: Dependencies & vendoring | sa...@intellisense.io | 05/03/15 07:43 | Can we seriously not just expect the Go tool to read a JSON file with git version / tags / SHA hashes and to checkout the correct versions of each of the deps, then run it's build? This could be done without any vendoring and still have the same behaviour. If there are any changes in the local copy of any of the repos, the go tool could instead retrieve a version in a temp folder, run the build, then remove the temp folder. That would save duplication, and allow you to have different apps tagged at different versions, but only one copy of each repo? |
| Re: [golang-dev] Dependencies & vendoring | David Reiss | 05/03/15 07:44 | I'd also like to add a vote to the "vendoring is a bad idea" camp. Reproducible builds and composability are critical, but vendoring isn't the only way to achieve that, it's just the only one that fills the peculiar shape created by what "go get" does and doesn't do. The go tool does both too much and too little to solve these problems: too little because it provides no mechanism for reproducible builds, and too much because its conventions, like using a repo path (but no version!) as an import identifier, make it impossible to properly solve them and maintain full compatibility without breaking the conventions. Rather than rehashing all the problems with vendoring (well-summarized in Eric's post), I'll just jump straight to the direction I'd rather see things go: The solution I've created for go builds at my workplace is a tool called begot[1]. You record your dependencies in a yaml file that points to git repos, optionally pinning to a branch or tag or commit (sorta like a Gemfile). It fetches them for you into a private cache, which you're not supposed to look at. Commit ids are recorded in another file (sorta like a Gemfile.lock). When building, it ensures that all the cached repos are at the right version, rewrites imports as necessary (but the rewrites are only local and never pushed anywhere!), constructs a temporary workspace with symlinks pointing to the right places (sorta like Blaze), then sets GOPATH and calls the go command to do the build. When you declare a dependency on another repo that uses begot, it checks that all the versions match. This decouples import paths used in code from the origin of the code, so you can feel free to use short and convenient names for your imports, with the actual origin recorded in the dependency file. It also means it's easy to switch a whole dependency to a private fork (e.g. while you're waiting for a patch to get merged upstream) with a just one-line change to the dependency file. (You can even do this for indirect dependencies without forking all the intermediate repos.) It also allows for extra metadata to be included with dependencies, such as which git transport to use, so private repos with ssh just work. Here's what I think this approach does right: - Fully deterministic and reproducible builds. - Continues the go tradition of using scm tools as a "package system" without binary packages (even more than the vendoring approach). - Decouples import paths from code origin. - Allows more metadata than can fit in an import path (versions, aliases, transports, etc.). - Always collapses multiple copies of a library. - Doesn't bloat repos with full copies of their dependencies. Here's where it needs some more work: - It requires that all versions of a repo referenced in a project's dependency tree be locked to the same commit id. This is probably too strict for fast-moving projects. The approach could be extended to be more flexible, e.g. with semantic versions in git tags. - In order to depend on a library that uses begot, you have to use begot too. Obviously, if an approach like this becomes the standard and is built into the go tool, this isn't a concern anymore. - It doesn't provide quite as strong of a reproducibility guarantee as vendoring: if you refer to a third-party's repo on say, GitHub, and they delete it or rewrite their history such that a commit id no longer exists, you might not be able to reconstruct it. My plan for solving this is a separate tool (not yet written) that makes it easy to mirror git/other scm repos so that you have a copy under your organization's control. This could integrate with the build tool so that using a mirror in place of the origin is completely transparent. --- The go tool and vendoring conventions have created a sort of local maximum that we can't break out of without sacrificing something, but is far from the ideal. I suggest we think about how to sacrifice some compatibility with the present world so we can get to a better one in the future. |
| unk...@googlegroups.com | 05/03/15 09:33 | <Ce message a été supprimé.> | |
| Re: Dependencies & vendoring | mar...@google.com | 05/03/15 10:02 | One possible way to resolve this would be to have the "internal" directory be part of the GOPATH workspace, in addition to src, bin, etc. That gives you the "common root" that Google has, in a consistent fashion, compatible with go tooling. Vendored dependencies go there, using the same basic structure as the src directly, but appending a tag value to the end of the project directory name. If two packages were using the same dependency, there would only be a single copy of the code. If there are multiple versions, then there will be multiple copies, as required. The import rewriting tools would have to be a little smarter, but all the information needed should be available in the config. For example: $GOROOT/internal/github.com/rsc.io/x86/x86asm-af2970a7819d (or alternatively have the tag be a subdirectory under the project) This has the advantage of encouraging a single GOPATH workspace for all projects for efficiency. Multiple GOPATHs could still be used, but with additional cost (disk space). You could use a special tag such as 'latest' to always get the tip version. This gives you reliable local builds in the case of network failure, or project deletion, or non-redirected location moves, while allowing you to track the project tip.
|
| Re: [golang-dev] Re: Dependencies & vendoring | Humberto Anjos | 05/03/15 10:20 | What are the advantages of a single $GOPATH workspace over say, a $GOPATH per project?
|
| Re: [golang-dev] Re: Dependencies & vendoring | Salman Aljammaz | 05/03/15 12:58 |
go get would just work. |
| Re: [golang-dev] Dependencies & vendoring | Alexandre Bourget | 05/03/15 13:05 | I dislike calling other tools instead of `go build`. It's not as discoverable. I'd prefer having hooks à-la `go generate` that would calls the right tools, from instructions in the source code, when running `go build`. At least `go build` could display error messages saying you need to install this or that dependency management tool. maybe just allowing notation of imports like `import "github.com/bob/project v1.0"` or something, those pluggable dependency management tools could extract the info they need, and act upon. It would stay simple for beginners, you'd have hooks for more advanced use cases, and flexibility of tooling for different projects Alexandre |
| Re: Dependencies & vendoring | Jeremías Longo | 05/03/15 13:05 | I like how Dart manage packages with Pub tool developed by Google Team. We can follow the same concepts in Go. |
| Re: Dependencies & vendoring | Matthijs Mullender | 05/03/15 13:05 | It might be good to look at how other systems have solved this problem. For example gradle (used by Android) has pretty good support for transitive dependencies and dependency conflict resolution. It opts to store the dependencies in a cache directory. http://gradle.org/docs/current/userguide/dependency_management.html
|
| Re: [golang-dev] Re: Dependencies & vendoring | Michael Schuett | 05/03/15 13:12 | npm (js), composer (php), and bundler (ruby) all solve the problem we are talking about in this thread. The issues seems to be 50% of people thing that vendoring in this way a bad solution although it's been working fine for the last 3 - 4 years while I have used it.
|
| Re: [golang-dev] Re: Dependencies & vendoring | Axel Wagner | 05/03/15 16:06 | Hi,
Apparently one can't say this enough: go get is not a deployment strategy :) There are in fact people out there who are not go-developer and would still like to use your software. And they probably don't want to (and shouldn't need to) install a go development environment to do that. gem, pip and npm are popular, but they start to become very problematic, once you try to use them for deployment of your stuff. People (at least on the unices), already have one package manager and they already have to run that regularly to get updates. Having to remember one additionally package manager for every handfull of tools they install, is not a good thing (especially as most of them are particularly bad at the "uninstalling"-part of package management). go get is an amazing tool to get libraries to get up and going quickly. It is okay to use it to make your library available to other developers. For binaries (and I thought most people have agreed so far, that using vendoring for libraries would be a bad idea in and of itself) it is just not a good idea. And I mean, honestly, a tool to wrap the go-tool for a GOPATH per project is like three lines of shell (probably a bit more to make robust, but you get my point): #!/bin/sh mkdir -p .gopath GOPATH=$(pwd)/.gopath go $@ and getting something like that adopted isn't a lot harder than getting your favourite variety of vendoring tool adopted. Best, Axel |
| Re: [golang-dev] Re: Dependencies & vendoring | Axel Wagner | 05/03/15 16:14 | Hi,
vendoring doesn't create issues for the people who use it :) The claimed problems with vendorings are for the users of a project, not the developers. One of my main grudges with vendoring is, that it passes the buck downstream, to package maintainers and users (who want to re-use your stuff and can't because you vendor a different/custom/too old/too new version of the library and they first have to go through version hell). So yes, I acknowledge that it probably makes the life easier for the author of a package, but that's not the issue :) All this applies almost 100% to a GOPATH per project with a config-file and custom fetch-tool. And as mentioned in other places, a tool that detects the presence of a custom GOPATH and wraps the go-tool transparently is only a handfull of lines of shell-code. :) Best, Axel |
| Re: [golang-dev] Re: Dependencies & vendoring | Andrew Gerrand | 05/03/15 16:17 | You shouldn't be vendoring the depdencies of libraries, but rather the dependencies of binaries. Thats' what Mat is saying; they use vendoring for managing their apps' dependencies. There's nobody downstream from there. |
| Re: [golang-dev] Re: Dependencies & vendoring | Andrew Gerrand | 05/03/15 16:26 | On 6 March 2015 at 11:23, Tianon Gravi <admw...@gmail.com> wrote: On 5 March 2015 at 17:17, Andrew Gerrand <a...@golang.org> wrote:Except distribution packagers, who are constrained to packaging each Fortunately all the dependency information will be neatly catalogued in a standard machine-readable format, so they can write a simple tool to extract any vendored dependencies and rewrite the import paths. Programming FTW! |
| Re: [golang-dev] Re: Dependencies & vendoring | Axel Wagner | 05/03/15 16:28 | Hi,
Not if their app isn't open-source, no. Otherwise, there are distributions and their package maintainers. :) That's why I keep emphasizing, that vendoring works well for companies, because they really have no downstream. For most open source software, there is always something downstream and that's where the problems of vendoring show. |
| Re: [golang-dev] Re: Dependencies & vendoring | Tianon Gravi | 05/03/15 16:33 | On 5 March 2015 at 17:17, Andrew Gerrand <a...@golang.org> wrote: > Thats' what Mat is saying; they use vendoring for managing their apps' Except distribution packagers, who are constrained to packaging each♥, - Tianon 4096R / B42F 6819 007F 00F8 8E36 4FD4 036A 9C25 BF35 7DD4 |
| Re: [golang-dev] Re: Dependencies & vendoring | Humberto Anjos | 05/03/15 16:46 | On Thu, Mar 5, 2015 at 9:14 PM, Axel Wagner <axel.wa...@googlemail.com> wrote:And as mentioned in other places, a tool that |
| Re: [golang-dev] Re: Dependencies & vendoring | Humberto Anjos | 05/03/15 16:50 | On Thu, Mar 5, 2015 at 9:17 PM, Andrew Gerrand <a...@golang.org> wrote: Will libraries be able to use this dependency information as well? |
| Re: [golang-dev] Re: Dependencies & vendoring | Andrew Gerrand | 05/03/15 17:02 | Sure, I think it might be useful for libraries to provide the information to make vendoring easier for the eventual end-user. |
| Re: [golang-dev] Re: Dependencies & vendoring | Humberto Anjos | 05/03/15 17:09 | Wouldn't go get consume that information as well? |
| Re: [golang-dev] Re: Dependencies & vendoring | Eric Myhre | 05/03/15 17:20 | Speaking of! Hey Tianon, would you be so kind as to rewrite docker//pkg/system's utimes syscall stuff out into a separate library, just for me?
You see, docker rightly considers itself a program, and so vendored things, but I really want to use that package as a library ;) ---
> You shouldn't be vendoring the depdencies of libraries, but rather the > Thats' what Mat is saying; they use vendoring for managing their apps'And so I would reiterate: this "libraries" vs "programs" thing is a false dichotomy, and it *doesn't work* in at least two directions: - I want to reuse some code from a project that vendored already. Because I'm not Commandante In Chief Over All Open Source (count your lucky stars), I'm powerless to do anything about this except copy-paste parts of their library, which *sucks*. - I want to run the test suite on some project that's a library and thus has been advised *not* to vendor. I can't, because lol-tracking-third-party-master-breaks-for-no-reason. I hit one or both of these every single day I work with -- or even causally peruse -- some other go developer's project for potential use or reuse. "libraries" vs "programs" is a false dichotomy, and even if it was a valid universal split, as described so far it doesn't solve problems and just leaves libraries completely out in the unbuildable, untestable cold. And that, in practice, has had some pretty unsurprising results on the community at large: it means everyone builds "programs", because building "libraries" when you can't test them repeatably is murderously painful. And that's why we're hearing the "but what if I need to unvendor?" issue brought up by lots of people: that's the corner this approach has already backed us all into. And no, I'm not thrilled with the idea of writing so "a simple tool" to extract any vendored dependencies and rewrite the import paths. I've already done a ducttape version of this; it's called "carnaval" because everything in it is a shitshow, and I'll never push it publicly because it's just the worst code in the history of the universe. And it sucks: not because the code sucks, but because the core concept sucks. Here's why it still sucks: I end up with a new repo for every repo I have to un-vendor. And now what happens when someone else in a company next door has the same issue with the same library and needs to retro-unvendor? They don't want to rely on this random dude's psuedo-fork-rewrite repo to stay around (because why would they? I wouldn't either), so they do it *again*. Rinse and repeat for every person or organization who ever uses a library that dared to make their code certain to compile next thursday. Every one of them gets a new repo with new commit hashes and not a single one of them can pool or share resources. It's a tragedy in the full light of the commons. Best case scenario in this worldview is if every organization maintains two repos for everything: a code "library" right up to the main method, and then another repo with the main method and everything vendored. Two problems with that: A) let's admit it: nobody's going to do that, as evidenced by how nobody has been willing to do that; and B) *it **still** doesn't solve the problem of consistent builds for the tests in libraries*. We can't possibly make vendoring worse by making a standard convention for it, but it's also quite certain that a standard convention for vendoring is not going to make anything better for a wide range of the problems the community is currently challenged with. P.S. Tianon: kidding. I already bit the bullet and copy-paste forked it :/ In the current ecosystem, it doesn't actually make any sense at all for docker to take on the burden of splitting libraries out like that. |
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 05/03/15 17:32 | I've been doing this as well. It works very well and it's very simple. You can get the same function out of an alias without mkdir... go='GOPATH=`pwd`:$GOPATH go' Hope that helps. Alex
|
| Re: [golang-dev] Re: Dependencies & vendoring | Nathan Youngman | 05/03/15 17:48 | On 5 March 2015 at 00:45, Ulrich Schreiner <ulrich.s...@gmail.com> wrote:
It's true that there isn't anything about the proposed config file that would limit it to a particular way of being used. It may be a reasonable first step to just standardize on a config, though various auxiliary tools (deduping and diamond crushing as mentioned) would only work within their toolset (vendored + rewrite). The necessary data to restore the world includes: * the repositories with SHA commit hashes (repo, rev) * possibly the names and urls to other git remotes, or equivalent for hg, bzr: ("fork": "github.com/libgo/pdf") (your commit is in another castle) * perhaps the name of the tool that created the config * perhaps a mechanism for tools to store additional custom information (though they could always use an additional file) For these requirements, I would still recommend JSON or a simple text format (TOML or a subset?). A build tool like Slurp <https://github.com/omeid/slurp> seems out of scope. I would avoid naming the file packages.json because mixed-language projects may already have one. So perhaps deps.json or deps.{ext}. As for location, I like the idea of placing the file in the main package. That may be be the repository root, or one or more cmd/something/ folders. But perhaps just a single file in the repository root would be simpler and better. Nathan. |
| Re: [golang-dev] Re: Dependencies & vendoring | Tianon Gravi | 05/03/15 18:57 | On 5 March 2015 at 18:20, Eric Myhre <ha...@exultant.us> wrote:This is actually one of the reasons we vendor, but don't rewrite import paths. |
| Re: [golang-dev] Re: Dependencies & vendoring | Tianon Gravi | 05/03/15 18:58 | On 5 March 2015 at 19:57, Tianon Gravi <admw...@gmail.com> wrote:(so that there's a canonical "this version is the one we consider 'working' with our source" and so that it's easy for devs and users to test/build against non-vendored versions) |
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 05/03/15 19:06 | I assume go get from a git repository grabs the master branch, unstable code should not be committed on master. Just my $0.02
|
| Re: [golang-dev] Re: Dependencies & vendoring | Tianon Gravi | 05/03/15 19:15 | If only it were just about unstable; API incompatible is also a factor. ♥, |
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 05/03/15 19:17 | That's entirely true. Go has been young enough to mostly avoid this problem but there's a storm brewing. |
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 05/03/15 19:19 | On this note what if git repos had some sort of tag based system eg:
go get example.org/repo-tag or go get example.org/repo-1.0 |
| Re: [golang-dev] Re: Dependencies & vendoring | Eric Myhre | 05/03/15 19:20 | This is better than rewriting, I agree.
`go get` (or anything else that interacts at the vcs repo level, for that matter) still yanks all the other vendored data, though, which is a bummer when it turns out to be 200x bigger than my teeny little project repo. And to be clear, I'm not mad at docker in particular here; indeed, the opposite; they're an example because they have some handy code :) I just want to express that as a whole community together, we could come up with better than this. |
| Re: [golang-dev] Re: Dependencies & vendoring | lucio | 05/03/15 20:57 | What one needs is "governance", with all the negative consequences.
Or maybe some form of "voluntary vassalage" to one or more central registries or whatever it takes to record versions in use. Not for the faint-hearted. And not without some compensation. Lucio. > -- > You received this message because you are subscribed to the Google Groups > "golang-dev" group. > To unsubscribe from this group and stop receiving emails from it, send an |
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 05/03/15 21:08 | This is the rubygems approach. It seems to be highly objected to. Bootstrapping off of an existing system like git is much more attractive IMHO.
|
| Re: [golang-dev] Re: Dependencies & vendoring | Ulrich Schreiner | 05/03/15 23:51 | I'd vote for a json file with a "noisy" syntax so that a human can read it (which is hard with compact json). please do not use a go file. dependencies are declarative, they are not code. if the dependencies are so complex that you want them to be spelled with "go code" you are doing something wrong. and i'd also vote for a file format independent of a specific language. i can imagine small tools (aka skripts) which would like to parse the dependencies and are not written in go. i also think that sometimes i (as a human) want to see what a particular piece of code depends on. and i do not want to inspect some fancy developed go code; i'm conservative here, name your deps and not a program which should be run to see the deps. you're right: a specific tool will use the dependency file and then you're some sort of "locked in". but this is not a real problem if you are developing a "main package"; it is your decision and it is ok because you're developing the final product. but the whole discussion thread makes me nervous. i'm not sure if it is a good idea to propose a solution with the note that it is only for "main packages". you can take for sure that many libraries will vendor in their dependencies! ok, perhaps it is a qualitiy feature of a library if it doesn't. but i don't think it is good style to try to standardize something and only go a half step. and if not so experienced developers take the full step you stay behind and say "you should not have done this"? and please keep in mind that many many go projects are some sort of hybrid: they contain library packages and main packages. docker is one of the prominent ones but there are many of them. dear go team: if you think about including such a tool in 1.6+ please do not consider a copy-sourecode-tool. this works inside of google, ok. but as brad fitzpatrick's posting said you (googler's) have "at moste one copy of a given external library". but if every developer in the wild does this, you will have "at LEAST one copy of a given external library". and then you have to re-vendor the vendored sublibraries of your vendored libraries. the whole opensource community already has a global repository with exactly one version of a library: it is named "github" or "bitbucket" and a specific version is "commit hash". so if you want to include some functionality in 1.6+ consider supporting "go get'ing" specific hashes. then you can use this new dependency file and "go get" the libaries in the needed version. this would seamlessly integrate in the current go toolset. or simply do nothing, the current situation is great with all the existing tools. why change it? a standardization for "main packages" only ... well what are you standarizing? the developers of the main-packages can use what they want (copy, copy-with-import-rewrite, nothing, ...) because i (as a developer and consumer of libraries) should no use packages with vendored dependencies as a library. so why should i care if they vendor or not? and on the other side: if a develop a main package i have to use some additional steps when adding a dependency. it might be a "godep" or a "glock" command. who cares if this command is included in the default go toolset? ... |
| Re: Dependencies & vendoring | Egon Elbre | 06/03/15 00:01 | I've been skimming the discussion and could somebody, who has followed the discussion fully and has an unbiased view, condense these major points from both sides to a google doc? One important thing to remind is that we should take long perspective view - not short term. What would you expect to still work after 100years? After github.com has shut down due to energy crisis? After git, mercurial, bazaar has died? After we have interplanetary connection? |
| Re: [golang-dev] Dependencies & vendoring | rog | 06/03/15 01:28 | > officially recommends vendoring into an “internal” directoryI'm pretty sure that import path rewriting is a mistake. It conflates dependency requirement with API requirement. I also believe that putting dependency-pinning information in the import paths is a bad idea for the same reason. As I see it, an import path in a Go program represents a single package that implements some required API. When a Go program is compiled, we choose some particular implementation for that API, usually by finding it from $GOPATH. But GOPATH itself has been assembled previously by fetching packages from an arbitrary selection of sources chosen by the user. As an aside, this is why API backward compatibility is so important. When APIs are backwardly compatible, it means that even when disparate projects import the same package, we can always agree on at least one specific compatible implementation to use - the *latest available version*. If we rewrite an import path to refer to a vendored package, we add no more information - the source code now states that it will use a locally pinned implementation of the API, but we still require the same API and there are still many possible implementations. All we have done is ensure that the code is now incompatible with any other code that wants to use the same API, not a good thing! Vendoring has two main motivations: 1) we want repeatable builds and tests 2) we do not want to rely on an available network. Both of these motivations are orthogonal to one another. We can obtain repeatable builds and tests by recording dependency information and assembling it on demand. We can avoid reliance on an available network by vendoring or by having local caches (GOPATH being one example of this). I suggest that 2) is out of scope for this discussion - we already have several possibilities for avoiding network use, including vendoring and updating directories in $GOPATH. Let's just focus on the configuration file necessary for 1). Dmitry Shuralyof makes a good point that the VCS dependency information actually applies to a subtree of packages rather than an individual package. To that, I'd add the observation that it is very useful to have information that indicates how old a dependency is (a revno or a commit date), as otherwise there is no way to know whether a given change to the dependency file is moving forwards or backwards in time. If we want to pin dependencies in the absence of a network, and without the actual repositories that the dependencies are taken from, I think we should pin the actual source code itself, otherwise there is no way to verify before building that any vendored depdendencies *actually* conform to the declared dependencies. Manually editing vendored dependencies must always be a temptation and is surely always a mistake. For configuration file format, I think JSON is fine. This is a file that we want to be generated and updated automatically, and potentially merged with other similar configuration files. This is not a place for comments. My suggestion for a format would be this, formatted as JSON: // Dependencies holds information on all dependencies of some set of // packages. type Dependencies struct { // Repos holds information on all the VCS repositories used by // all dependencies, keyed by import path pattern. The key must // be of the form path/..., indicating that the repository holds // all the packages inside path/... . Repos map[string]Repo // Pkgs holds information on the source code by used by all // dependencies, keyed by package path. It will hold only // packages which are actually used as dependencies, so will not // include every package found in the above repositories. Pkgs map[string]Pkg } // Repo holds information on a repository. type Repo struct { // VCS holds the type of VCS that the repository uses, such as "git", "hg", "bzr". VCS string // Rev holds the VCS-specific revision of the dependency. Rev string // Revno holds the revision number of the revision. It will be // empty for VCSs that do not support revision numbers. Revno *int `json:",omitempty"` // Date holds the commit time of the revision. Date time.Time } // Pkg holds information on a package dependency. type Pkg struct { // SHA256 holds the SHA256 sum of all the non-test .go files in // the package's directory ordered lexically by lower-cased file // name. If a package contains two names that differ only in // case, it will be an error. SHA256 string } Thoughts? |
| Re: [golang-dev] Re: Dependencies & vendoring | Tartari Giacomo | 06/03/15 03:27 |
Or on the same line of go get -fix -u example.org, where we get the last revision and gofix looks into the source to check for old fashioned code, a tool could look into the code for revisions/tags of the imports and check them out. go get -u -sync //updates the repo and checks out the revision specified in the source go dep checkout //checks out the dependency revision specified in the source go dep save //write in the source the current revision for each dependency basically glok but without a config file. Giacomo ... |
| Re: [golang-dev] Re: Dependencies & vendoring | Pablo Astigarraga | 06/03/15 05:29 | I think this problem is fixed with a thin wrapper around `go get`, it could be an addition to the go get command or a new command alltogether, but *all* it needs to do is set packages in GOPATH to a version using the relevant VCS. it's *literally* one extra command. I would heavily advise everyone to check out gpm, glide and goop, they all solve the problem we're talking about with different shades of the same approach. Preferably read their source code as well: seeing how little work is required to solve this problem should give some perspective into why doing more involved and complex solutions is unnecessary and counter-productive. The bottom line is that expecting package APIs to never change and broken code to never be committed to master is naive and unrealistic: fetching master for all your dependencies is just not good enough, vendoring all your dependencies in your repository is cumbersome and painful, import rewriting is just about the hackiest solution out there and having a centralised system to keep track of all packages makes us lose the much-preferred decentralised nature of the current ecosystem in exchange for something we can easily obtained via other means. I've been maintaining gpm for almost two years now, during that time I've seen a lot of different approaches so I could learn other ways to tackle this problem and improve on what gpm provides, I've had a number of discussion on issues and pull requests and I'm fairly convinced that this is the best approach to the problem, I would encourage all of us to do as much research as we can before weighing in or proposing a brand-new solution - we are risking a pretty serious case of design by committee otherwise. |
| Re: [golang-dev] Re: Dependencies & vendoring | Ian Davis | 06/03/15 06:07 |
The problem with this is that it doesn't guarantee reproducible builds since repository histories can be rewritten. It also doesn't help with build reliability. At work we vendor dependencies and our build server simply checks out a fresh copy of our repository and builds. It avoids problems with temporary unavailability of remotes plus lets us build as often as we like without worrying about hammering the remote repo (some people still self-host their code, not everyone is on github).
Vendoring also helps with bug tracking via tools like git bisect. Every point in history in our repo is completely buildable even if the remote repositories have moved location or even vcs type.
Ian
|
| Re: [golang-dev] Re: Dependencies & vendoring | Craig Weber | 06/03/15 06:14 | If you're concerned about the remote changing, you could still maintain your own fork so you control the changes. This seems like a reasonable compromise. -- |
| Re: [golang-dev] Re: Dependencies & vendoring | rog | 06/03/15 06:23 | We have also been using a similar system (launchpad.net/godeps) for about
two years and I agree that this approach can work well. As I tried to say in my earlier email, I think the decision whether to to vendor dependencies is largely orthogonal to how to specify what those dependencies are. There are upsides and downsides to vendoring. That's why I agree with Russ Cox that this conversation should be about agreeing on a configuration file format, not standardising on a single tool that interprets that format. That's also part of why I am opposed to import path rewriting, because import path rewriting constrains the available options. In my view a vendored location is just *one* place from which the dependency path can be satisfied. It's the job of a tool to combine the Go source code with a set of dependencies to produce a final binary. We don't need to decide on that tool right now. cheers, rog. |
| Re: [golang-dev] Dependencies & vendoring | mat....@coull.com | 06/03/15 06:56 | On Thursday, March 5, 2015 at 3:44:32 PM UTC, dav...@gmail.com wrote:
I have a problem with that sort of setup - how do you guarantee a good build on a new server node that has no previous knowledge of the app you're about the build? You can't guarantee that the 'cached repos' are all going to be available or even that if they are the right versions will be available at that time. The point of a vendor folder for us at least, is that we control a copy of all the code that we will ever need to build an app anywhere. Unless i'm missing the point?
not sure about that - see above.. ^
I don't think in general any of us need to worry about having duplicate packages hanging around - how do you upgrade an old app safely if you update a package for all apps at once?
More tools - where as the vendoring solution is one that doens't need a tool as such, just the ability to read a config file. You can use anything. Shell/Go/manually get them all - once you have them you have them = a app that can be built anywhere and everywhere.
Again, just some of my thoughts - but from my point of view, the simpler the better. Always. |
| Re: [golang-dev] Re: Dependencies & vendoring | mat....@coull.com | 06/03/15 07:28 |
+1 sati... |
| Re: [golang-dev] Re: Dependencies & vendoring | Humberto Anjos | 06/03/15 08:31 | The OP stated (among other things): Our proposal is that the Go project, Although 2) is the main point of this thread, the big noise here is about 1), since it's the premise which will guide whatever comes out of 2) and both the tooling and community behavior to follow. A good answer for 2) will come out once a reasonably agreed-upon set of recommended dependency management workflows (for libraries too; they seem almost a second-class citizen) emerges. I believe this thread and others show that 1) isn't quite that set.
|
| Re: [golang-dev] Dependencies & vendoring | David Reiss | 06/03/15 16:25 | On Fri, Mar 6, 2015 at 6:56 AM, <mat....@coull.com> wrote:
Sorry, I left out a few details in an attempt to be concise: The commit ids (hashes) of all dependencies are recorded in a file and that file is checked into version control. After fetching a project repo on a new machine, one command will fetch all the dependent repos and reset them to the recorded commit ids. Semantically, you can imagine it fetching and resetting all dependencies for every build. The cache is just an optimization to avoid fetching over and over again. As for dependencies being unavailable, I suggested solving that with a tool to mirror repos. It's an important concern, but an orthogonal concern to getting the right versions of things, so it makes sense to solve it with a different (but integrated) tool.
I meant that it collapses multiple copies of a library within one binary. All projects have independent dependency metadata and can be upgraded independently (you can also upgrade specific packages for a project without upgrading everything). Again, any potential cross-project sharing through a cache is an optimization and doesn't affect the semantics.
The popularity of vendoring tools seems to suggest that people certainly prefer a tool to help manage the complexity of vendoring, even if it's not strictly necessary. I am a huge fan of simplicity as well, perhaps to a fault. All these design decisions involve tradeoffs, and will make one thing simpler while quietly pushing complexity into another. It took me several months of trying and thinking about various approaches, seeing what worked well and what didn't, and conversations with colleagues, to convince myself that what I described has the least overall complexity (of solutions that solve the problems I set out to solve), even if in a few aspects, it is more complex than the status quo. I'll also note that my tool, begot, has fewer (non-test) lines of code than godep, nut, or glide. This may be a cheap shot, as it's less mature and will surely grow a little over time, and LOC is a crude measure, but I want to make the point that it's not inherently more complicated than those. And of course all of these depend on the go command, which is much larger than any of them. |
| Re: [golang-dev] Dependencies & vendoring | David Reiss | 06/03/15 17:04 | On Fri, Mar 6, 2015 at 4:24 PM, David Reiss <dav...@gmail.com> wrote: I'd like to expand on a point that I don't think has been made explicit so far in this thread: What we actually want is two dependency metadata files, not one. The first file (the "request file") is where a human writes a request for a package, which obviously includes a repository identifier and may also include some sort of version specifier. Often this will just be "master"/"go1", sometimes another branch, and rarely a specific commit id. Or maybe some sort of semantic version specifier. The second file (the "lock file") is where a tool will record the actual commit ids that it got when resolving the version specifiers at a specific time. The request file is meant to be human editable and the lock file is not. The lock file contains all the metadata needed to reproduce a build (not the data, which could either be embedded in the project repo or not, depending on your vendoring preference). In the status quo, the request file isn't actually a separate file but is spread across the imports of all .go files, and it doesn't support version specifiers. Thinking about two files rather than one might help clarify some of the disagreements in this thread: - Commit ids are necessary to reproduce builds exactly, but they're not user-friendly and shouldn't go in the request file (most of the time). - Branch names shouldn't end up in the lock file, because they may resolve to different things at different times. - The lock file doesn't have to be human-editable (except for very rare situations), so it can be something like JSON. - The request file contains human intentions, which often benefit from accompanying explanations, so it should be in a format that allows comments (i.e. not JSON). - The request file doesn't have to be a separate file (although I believe it's more powerful and flexible if it is). - The lock file should be checked into version control to allow reproducible builds, even for libraries (although consumers of those libraries could choose to override it with versions recorded in their own lock file). - This is all orthogonal to vendoring vs. not vendoring (as long as you don't rewrite import paths). |
| Re: [golang-dev] Dependencies & vendoring | Eric Myhre | 06/03/15 17:17 | On 03/06/2015 08:23 AM, roger peppe wrote:>[...] >> That's why I agree with Russ Cox that this conversation should be about > That's also part of why I am opposed to import path rewriting, because > satisfied. It's the job of a tool to combine the Go source code with aHere here. I think there's at least some consensus that vendoring, though it may work today and solve some immediate problems, is probably not the permanent end-all solution. With that in mind, can we say that the goalposts in the conversation should firmly include getting a versioned dependency spec that is *fully detachable* from the details of vendoring? I think we're saying almost the same thing Russ said earlier -- "The point of the discussion is to agree on a standard format that explains what has been vendored" -- except with the additional clarification and suggestion that explaining what has been vendored is just one state of affairs we should be planning to describe. Can we have the same config reasonably describe both vendoring and a future non-vendored picture without requiring a reboot for the latter? We might not be able to anticipate everything, but we should at least try, and we should *definitely* plan for expansion (i.e., anything that involves parsing a colon-delimited string here might not be the most future-proof idea). And since we're talking about tracking upstream hashes in our records anyway, we're actually a large part of the way there already. So, that said, to do some review... Here is a shortlist of complications currently raised regarding configuration: - actual serial format (JSON, go, etc) - VCS dependency information actually applies to a subtree of packages rather than an individual package... so tracking hashes per package may be an impedance mismatch - Should version records contain branch names or hashes? Here is a shortlist of complications currently raised regarding import rewriting: - The current generation of direct package<->url relationships gets bumpy when forking a library (even on the short timescales for making a tiny PR). - Import rewriting results in "All we have done is ensure that the code is now incompatible with any other code that wants to use the same API" I think that's the big ones, and hope I haven't missed any in review. I won't repeat the shortlist of complications regarding vendoring, other than to mention that it isn't included in the above two shortlists :) --- Here's my 2c on each of those: - actual serial format: I'm on team JSON fwiw -- It's not inconceivable that non-gophers will want to parse this. Wearing a sysad/ci-maestro hat for a polyglot team for a moment, I'll say I've always been frustrated when encountering a config file that requires me to *learn someone's language*. And I think in accounting for the repo/package non-parity, we've already hit escape velocity for what makes sense as structural comments on import lines. - tracking hashes per package is definitely an impedance mismatch with how we do source. Something like Roger Peppe's suggested structs seems like a feasible direction to pursue. - Should version records contain branch names or hashes? both; follow the gemfile+gemfile.lock pattern, because it combines semantic and precision. easy to update, deterministic at every other juncture. We can focus on implementing only the "lock" half of that now, but we should probably keep the door open to evolve config for the branch/semver/whatever input to a resolver. - package<->url relationships need a layer of optional separation, because the network location of data changes (and PR's should require sed, etc). Again, something like Roger Peppe's suggested structs seems like a feasible direction to pursue. - Import rewriting should be extremely optional. Thus, it can be done when necessary. IMO should be done when necessary to isolate a transitive dependency (which is a relatively rare event and should only occur when diamond crushing is unworkable), and as a default maneuver, it makes no sense whatsoever: it addresses an inter-project isolation problem that can be better addressed by other means, doesn't help with forking or understanding when the network location of data changes, and it's otherwise a bunch of makework for sed. But if we make it clear that this is optional or we hide this behind a layer of indirection for on-disk layout just as we should be prepared to make for on-network layout, maybe we can all get along. --- On the topic of what's-after-vendoring.. > since repository histories can be rewritten. [...] > > [...] Every point in history in our repo is completely buildable even if the remote > repositories have moved location or even vcs type.I agree that these are the two biggest challenges in a system that maintains external references. When it comes to that (and yes, that may not be today, but while we're on the subject) I suggest the following: - We already, as pretty much a whole society, have come together on treating commit hashes on master to be reasonably sacrosanct. There's no other way to live reasonably. And mostly, that's working out okay. When it breaks down, we can mirror; but that's happily a vanishingly rare event, and also extremely simple to do even retroactively for all sane (D)VCSes. - A hypothetical tool for this should work by hashes as identity, purely. URLs can be provided for where to fetch from -- *multiple* URLs. The URLs are committed, but must also be overridable (e.g. `OVERIDE='s#bithub.com/lib/thingy#gotbucket.net/lib/thingy#' git bisect [...]`), and this makes it possible to have both precise data identity, and understand when data is mobile. As long as we focus on hashes as identity and network locations as fluid, we can make this arbitrarily stable/redundant/mirrorable. - Ideally, since what we're really after is a set of source files (not that plus their history), we might want something that uses the file tree hash instead of say the git commit hash. That'd require a little care for how to reconcile with existing VCS fetch commands, but is doable. |
| Re: [golang-dev] Dependencies & vendoring | Eric Myhre | 06/03/15 17:19 | On 03/06/2015 07:03 PM, David Reiss wrote:+1 to this entire post; Well said David, that's far more precisely stated about the distinction between "request file" and "lock file" than my gesticulations. |
| Re: Dependencies & vendoring | Anlhord Smithson | 07/03/15 18:24 | I think whole github should be added to go standard library |
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 07/03/15 18:38 | I like this idea but it seems entirely preferential. Why not bitbucket etc? You can always use the https versions from GitHub.
-- |
| Re: [golang-dev] Re: Dependencies & vendoring | Anlhord Smithson | 07/03/15 19:39 | well that too. perhaps everybody should release everything in public domain. that would solve the licensing problems. next we can solve the vendoring problems by vendoring everything into one huge repo. there would be subfolders google/ facebook/ github/ bitbucket/ we will give commit acces to everyone! reliable builds will be enforced each time someone breaks build we will revert. no api problems. each time someone breaks api we will revert. trust me i'm expert on this. the best thing: it will be a best practice approved by the go community so everyone will accept it ... |
| Re: [golang-dev] Re: Dependencies & vendoring | Jaana Burcu Dogan | 07/03/15 21:11 | > next we can solve the vendoring problems by vendoring everything into one huge repo.Not a scalable approach. If I have to break a package that has thousands of dependents, how can I find time to fix them all before submitting my change? >> golang-dev+...@googlegroups.com. >> For more options, visit> -- > You received this message because you are subscribed to the Google Groups > "golang-dev" group. > To unsubscribe from this group and stop receiving emails from it, send an |
| Re: [golang-dev] Re: Dependencies & vendoring | Michael Schuett | 08/03/15 11:44 | Clearly this conversation is getting derailed with ridiculous propositions right now. I think the best thing that has come about from this conversation have been the discussion of splitting up the versioning file into a 2 one that is a lock file containing the exact commit hash of what was run on a previous install. I wanted to bring this up earlier but phps composer package manager does just this and might be worth looking into what setbacks people have run into with this approach and if they outweigh the benefits. I have used composer and I must say the only issues we run into is based on team communication and the other is that php must generate an autoload file with is kept in a special vendoring file. This becomes an issue because if you pull code from master after someone has been added you get a nasty error. However this would not be an issue with Go.
Thoughts? |
| Re: [golang-dev] Dependencies & vendoring | rog | 08/03/15 16:38 | On 7 March 2015 at 01:03, David Reiss <dav...@gmail.com> wrote:This seems about right to me. The network location implied by the import paths may be sufficient in most cases but not all, and it's quite reasonable for some other tool to be responsible for fetching repositories instead of the Go tool. Any such tool would likely have a configuration file, but the details of the tool and its configuration are beyond the scope of the current discussion, I think. That said, I would see the role of such a tool as providing of access to the required repositories or source code and this allowing the "lock file" constraints to be satisfied, but not of specifying versions, otherwise ISTM that the two files would be at cross-purposes. - Import paths specify the required API (potentially including a major version number); - The "lock file" specifies exact dependency versions, chosen by a repository owner; - The "request file" could specify a network location where repositories containing the chosen versions can be find. Vendoring is an alternative (and possibly preferable) approach here. I find myself thinking that although a "request file" may be a necessary evil in some circumstances (for instance if there's much-used buggy repository that won't accept bugfixes), it's probably almost always better to just explicitly fork the repository and let the import paths mean what they say. cheers, rog. |
| Re: [golang-dev] Dependencies & vendoring | murillo...@gmail.com | 09/03/15 15:45 | If all you need to a reproducible build is the source code, then storing commit's identifiers is pointless, just save the code in the vendored folder. The go way of vendoring looks like this for me: go vendor bitbucket.com/lunargoddess/superimportantproject (it is a super important project, so I need vendoring...) no need for config files, nor stuff like that. Just like you do go get, you should do go vendor. then the go-vendor command scans superimportantproject imports list, copies the sources to $GOPATH/src/bitbucket.com/lunargoddess/superimportantproject/vendored/ and rewrites the imports list from "github.com/someone/something" to "bitbucket.com/lunargoddess/superimportantproject/vendored/github.com/someone/something" Easy doing, I love the go way. SO, now that I have vendored some stuff I happen to find that I want to update the something dependency, what should I do? What would a gopher do? A lunargoddess gopher would just import "github.com/someone/something" in her superimportantproject and go vendor bitbucket.com/lunargoddess/superimportantproject and BAM! it updates only the "github.com/someone/something" dependency in the vendored folder. OMG! I love golang, the best thing is that everything you need is in the official toolchain, no need for godeps, npm, gems, pips,... just simple stuff El lunes, 2 de marzo de 2015, 22:04:52 (UTC+1), Keith Rarick escribió: On Mon, Mar 2, 2015 at 12:10 PM, Axel Wagner El lunes, 2 de marzo de 2015, 22:04:52 (UTC+1), Keith Rarick escribió: On Mon, Mar 2, 2015 at 12:10 PM, Axel Wagner |
| Re: [golang-dev] Dependencies & vendoring | rog | 10/03/15 01:00 | On 9 March 2015 at 22:44, <murillo...@gmail.com> wrote:If all you need for a reproducible build is the source code, you are correct. However a reproducible build is not the only aim. We also want to be able to know the history of that source code so we can bisect it when looking for bugs, so that we have a convenient way of communicating information about a given build, and so it's easy to tell whether we need to update the dependencies and whether they are the same as some other project's dependencies. Suppose bitbucket.com/lunargoddess/superimportantproject/... contains both main packages and library packages that can be imported from external projects. A package external to that project that imports something from bitbucket.com/lunargoddess/superimportantproject would need to import bitbucket.com/lunargoddess/superimportantproject/vendored/github.com/someone/something instead of github.com/someone/something otherwise that package would get two copies in the final executable. This issue gets worse the more repositories use the technique. cheers, rog. |
| Re: [golang-dev] Dependencies & vendoring | murillo...@gmail.com | 10/03/15 15:29 | Hi rog, You are completely right about the dependencies nightmare, and I may be pigheaded, but it doesn't feel like go to me. What does the philosophy of go feel to me? 90% perfect, 100% of the time and this http://golang.org/ref/mem#tmp_1 Don't be clever. Simple stuff that is easy to understand and works. Coming back to the issues you pointed, IMO and I know nothing (i'm not John Snow :) there is no perfect solution for that, it doesn't matter what the solution it is, there's always going to be a use case where it gets broken, and you end up with something that is going to be over-engineered 99% of the time. Commits can be modified/deleted, so you have a pointer to something that is no longer useful. And sincerely, in the scenario you pointed, I bet my hair that in that case (super important project), there is going to be bigger problems than having a few (or lots) packages duplicated. Peace. |
| Re: Dependencies & vendoring | Andy Smith | 10/03/15 17:27 | I'm late to this party but just spent quite a long time reading through all of the replies and feel like I have a reasonable understanding of the problems and perspectives involved having worked in both the monolithic (Google) and non-monolithic (lots of projects, startups and languages and their various methods for solving these issues in different ways). Anyway, I'm tossing my money in the ring with: - Eric Myhre, his first post in this thread is somewhat epic but does a great job at summarizing the actual goals we want as developers/maintainers/consumers (isolation and reproducibility being his salient points): https://groups.google.com/d/msg/golang-dev/nMWoEAG55v8/jXPZmZe0E28J - Some interpretations of part of Russ Cox, that all I am willing to commit to deciding in this thread is a format for describing dependencies. (On which I actually don't mind much as long as it doesn't inherently _force_ path re-rewriting) My Conclusions: 1. I don't think vendoring is always the correct solution. 2. I think that sometimes vendoring _is_ the correct solution. 3. "internal" seems like a reasonable place to put something if you are vendoring. 4. A common deps config format that does not force behavior one way or the other will move everyone forward and probably let us continue to develop happily for quite some time. I love Go's strictness/opinionatedness in many things but this one may not have an answer yet and that is okay. Thanks for your time :) --termie On Monday, March 2, 2015 at 9:38:02 AM UTC-8, Brad Fitzpatrick wrote:
|
| Re: Dependencies & vendoring | Owen Ou | 10/03/15 20:11 | Whew, it took me a while to keep up with all the discussions. I think these are all good discussions. I personally think vendoring does make builds repeatable and reduce the chance of unexpected failures. I'm the maintainer of hub and we vendor dependencies with `godep save -r` (we'll soon migrate to nut though :)). Hub currently has 17 dependencies and building hub is as easy as running `go build` after checking out the project. I never need to worry about downloading the correct dependencies with yet another tool. The project is compact and has zero external dependencies (in this case, I regard the code of the dependencies as part of the project). I can also easily browse the source code of the dependencies when I open the project in an editor, as opposed to the source code of the dependencies are in different directories in GOPATH. It sounds like some Gophers have problems with checking in the dependencies to VCS. Yes, version controlling dependencies makes some commits unreadable (also a disaster for corresponding code reviews), e.g., https://github.com/github/hub/commit/992b26216c80bbaf439f1d451824178e8e9fd1eb. But in order to make a build repeatable, there seem to be only two ways: * check in the dependencies (aka, the vendor approach), a metadata file will need to be checked in as well for update of dependencies * check in a metadata file only so that a tool can replay the dependencies (examples are maven, bundler, npm etc.) Both approaches actually end up with the same project setup. And the second approach requires another tool to download specified dependencies. What we're trying agree on here is this metadata file. It's needed regardless which approach we takes. Regarding to the format of the metadata file, I think JSON is a better fit (aka External DSL). It makes tools like `nut` and `godep` easier to implement. I also like the idea of using Go code to declare dependencies (aka Internal DSL). But unfortunately Go's syntax is not very good at writing internal DSL. So any solution we come up with may look awkward. So...are we close to agree on something and move on :) ? ... |
| Re: Dependencies & vendoring | Richard Fliam | 27/03/15 13:18 | It occurs to me that one of the things missing from the "proposed" json format is the ability to override the source url. Consider the repo github.internal.com. If github.internal.com/somelibrary does not support to go-get syntax, you may not be able to checkout against it. The repo for this is git@github.internal.com:somelibrary.git, but it should be checked out to src/github.internal.com/somelibrary. As such, whether go or json the file should support Repo and RepoRoot (using the semantics from "golang.org/x/tools/go/vcs"). { "Deps": [ { "ImportPath": "rsc.io/arm/armasm", "RepoPath": "git@rsci.io:arm/armasm" "Rev": "616aea947362" }, ] } ~Regards, Richard Fliam
|
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 27/03/15 13:57 | Makes sense, I agree with this approach.
|
| Re: Dependencies & vendoring | Manlio Perillo | 29/03/15 09:38 | Il giorno lunedì 2 marzo 2015 18:38:02 UTC+1, Brad Fitzpatrick ha scritto: > [...]
What about having instead something like Python .pth files? src/cmd/internal/rsc.io/x86/x86asm.pkg: rsc.io/x86/x86asm with revision af2970a7819d This is a bit more verbose, since you need to manually create the intermediate directories. > [...] Regards Manlio |
| Dependencies & vendoring | Rob Fielding | 15/04/15 14:52 | This is a general issue that git needs a solution for; the "repo" project seems to be addressing some of it. Artifact servers only seem to solve one part, and submodule/subtree another part. It's related to always having a top-level product repo that manages the exact references to how the product is built. It includes references to source repos by commit, build scripts (nothing installed globally), compilers, previously cached builds, etc.
We are always writing wrappers around git when we are faced with making fixes that involve checking out and editing a half-dozen repositories (out of hundreds potentially). There always needs to be a top-level product repo that references all commits that projects are supposed to be up to, and allows for the implementation of a "metagit ls-modules" to get started on a bugfix. You need to be able to treat all cloned repos (under the project) as one for purposes of making branches for a bug fix, switching branches, rebasing, writing a commit message, and pushing a commit out to be reviewed pseudo-atomically (if not atomically). submodule/subtree doesn't seem to fit because the dependencies are really between a source repo and *builds* it needs that are keyed by commit. The built artifact then has a reference to the source that created it (ie: repo/commit), which you may then want to retrieve and modify. Sometimes the build is performed by a remote machine (or multiple remote machines!), other times it's compiled from source on your own machine, and other times it is simply served out of a cache that somebody else built; but that's an implementation detail of your tool doing the make. what matters is the dependency on the build artifact. But then if you have references to inconsistent versions. If you wanted ctags to work, then for a particular repo, you checkout into subdirectories the source actually referenced by the dependency file. |
| Dependencies & vendoring | Hans Korevaar | 06/05/15 10:29 | Hello,
first of all a disclaimer: I am posting this on request of a very good friend, and secondly, no, I have not read all this thread, and again no, I am not a professional Golang developer. But my friend pointed me to this problem, so ridicule me as you wish. My understanding of the problem is as follows; that this is a simple problem of getting code from A to B. Namely, from some place A, say github, to place B, say your own local computer. How is this problem solved? And how is this problem solved when you incorperate different versions of A? Well. The simple answer would be that version 1.0 of A, and version 1.1 of A, are not the same thing. Imagine the following: 'go get -v 1.0 /../a' gets you version 1.0 of a. 'go get /../a' gets you the current version of a. There is a problem with this. The solution I see is as follows: The 'go get' tool doesn't have a flag for getting different versions. This needs to be changed. Then the second problem is: websites that host code online, do not host different versions as a whole package, instead calculating differences between them. I'm not familiar with this, but its what my friend told me. The simple solution, since hosting text is cheap and efficient, is to host all different versions of code, so 1.0 and 1.1. This way 'go get' would be able to get different versions of the same project dependancy. This solution is to work out the problem remotely, on sites like github, with changes needed in Git itself. I'm not partial to Git nor think its perfect enough to not warrant changes. I'm not a true programmer myself, so take my ideas with salt. I imagine that Github hosts ALL versions of a software's code. Simple because the Vendoring solutions 'hosts' it at the project's source tree, in /vendor, say, so its either that solution, OR, the solution of Github hosting those versions itself. Its a question for Github really. Since this is a problem of getting things from A to B, and they are the means by which we do it, including Git, and including 'go get'. So do we change those tools, and github itself, to solve this problem, or do we solve it locally? That's the question that's been posed in my opinion. Solving it locally by putting dependancies into /vendor, when hosted on Github, makes many duplicates of /vendor on Github which need to be hosted. Solving it remotely by changing Git and Github to incorperate different versions in a whole package instead of differences, makes Github host all those versions of a project. I say: let hosting websites decide on the solution of this problem. I do not know the numbers. Is hosting /vendor X times worth it more than hosting Y versions of a project's code? My $0.02. Thanks for reading, Psi |
| Dependencies & vendoring | Hans Korevaar | 06/05/15 10:29 | |
| Re: Dependencies & vendoring | Andrew Chambers | 10/05/15 20:51 | Github does already host all versions of a package, this is not the problem. The problem is more complicated than what you say. One such problem is that you can run into issues when multiple packages depend on different versions of the same third party package and they are all incompatible with eachother. |
| Re: Dependencies & vendoring | Kyle Lemons | 08/06/15 10:13 | On Monday, March 2, 2015 at 9:38:02 AM UTC-8, Brad Fitzpatrick wrote:
Will there be or is there already a golang.org/x/vendor package that defines the json schema and provides functions for ast rewriting and computing the location of the config file given a package name? If the goal is to standardize, it seems like it would be good to at least have a reference implementation there, though hopefully all tools would grow to adopt it. |
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 08/06/15 22:10 | I've been trolling this conversation since the beginning, what if we can up with a tool (ala bundler or pip) that was able to dynamically define the path at runtime? Alex
--You received this message because you are subscribed to a topic in the Google Groups "golang-dev" group.To unsubscribe from this group and all its topics, send an email to golang-dev+unsubscribe@googlegroups.com. |
| Re: [golang-dev] Re: Dependencies & vendoring | Alex Smith | 08/06/15 22:10 | +1. Was replying to the previous comment.
--You received this message because you are subscribed to a topic in the Google Groups "golang-dev" group. |
| Re: [golang-dev] Re: Dependencies & vendoring | Daniel Theophanes | 09/06/15 10:32 | I think you mean at build time. Before you create your own spec please refer to https://github.com/kardianos/vendor-spec . There is a tool that uses it here: https://github.com/kardianos/vendor ... |
| Re: Dependencies & vendoring | Daniel Theophanes | 09/06/15 10:33 |
I also think that would be great. For now please see https://github.com/kardianos/vendor-spec and https://github.com/kardianos/vendor Thanks. -Daniel |
| Re: [golang-dev] Dependencies & vendoring | TR NS | 11/06/15 18:17 | On Thursday, March 5, 2015 at 10:44:32 AM UTC-5, dav...@gmail.com wrote:
I like this part of your idea, and have often thought that would be nice approach. I can't quite agree about being against vendoring though -- all the cached repo and symlinking stuff seems more complicated than it need be. |
| Re: Dependencies & vendoring | mnepi...@gmail.com | 02/07/15 23:10 | I'm beginner here, maybe not understand complexity of this question but not agree with any kind of vendoring and freezing of "local" copies any packages, also any internal parts of project possible consider as separated (tiny|compact|flat) packages. If "go get" will care about clone recursively declared depends, and later use required revisions, see below. hope need just improve Import declarations : ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . ImportSpec = [ "." | PackageName ] ImportPath . ImportTag = "hash of commit or tag?"ImportPath = string_lit . |
| Re: Dependencies & vendoring | Alex Sl | 03/07/15 06:29 | Will try keep on idea about freezing API of dependencies in package. So...maybe need add an option to 'go get', for example, '--freeze' & '--unfreeze' : this option will add to each Import declaration git versions tag, and will checkout depends in to local folder for project release purposes, also have other needs, ... in other cases on project-dev branch We can use packages from $GOPATH and add any fixes simply and easy, and still on edge version of all imported packages any time I'm not sure about all of this is right, I will try to read this topic. Maybe other ideas be better. Thank |