Dependency versioning

I must’ve missed something. How does Caddy specify versions of its dependencies?

Glock, Glide, Godep etc etc

It doesn’t. What are you looking for in particular?

Out of the box, go get gives you an easy way to fetch from the 'Net all the source code dependencies for the product. But it doesn’t provide a way to specify in detail what versions these dependencies should be.

It’s almost possible to keep a codebase entirely dependent on third-party libraries at the tip of their development. This will work … but only some of the time … and it’s what go get provides. It seems this is what Caddy is currently based on.

But a problem arises from being unable to guarantee that an upstream change by a library maintainer won’t ever break the product. It’s also difficult to be sure that two different developers trying to co-work on the same product won’t have times when their experience of upstream libraries differs.

There is a secondary (and lesser) worry. It’s impossible to guarantee that an upstream library will even continue to exist; the maintainer could arbitrarily give up and delete it. (This almost never happens.)

So … many people have worked on ways to solve these two concerns. The first - pinning the versions of dependencies - is the important one and every tool out there does this. For example, a nicely-simple approach is taken by Glock. It doesn’t solve the remote-deletion issue, but it handles dependency version pinning nicely.

Dependency pinning does of course raise a new issue: it is now possible for there to be conflicting requirements on the version numbers of shared dependencies. So there’s new work to do to handle conflict resolution. Sigh.

Preventing the second issue requires bringing an entire copy of the source code for all transitive dependencies into the product’s own source tree. This is what the Go 1.5 ‘Vendoring’ experiment has been heading towards. A specially named folder (vendor) is treated differently by the Go tools such that it is not necessary to rename imports even when the vendor folder is not at the top of the source tree.

Glide is a good example of a tool that does both version pinning and vendoring. However, it soon becomes obvious that it introduces a new issue: when every upstream project vendors its own dependencies, multiple copies of many things might come flooding in and the tool has to provide a way of coping with this (Glide’s solution is turned off by default; a mistake).

Glide goes a bit further than Glock in that it provides semantic versioning support: major.minor.patch (e.g. v1.2.1), which means you get partial automation of the decision on whether to accept an incoming change based on the implied severity of the change (as represented in the semantic version number). Or, more plainly, you can refuse all major upgrades but accept all minor or patch upgrades automatically, for example. This works - but only when the library maintainer gets it right of course.

To answer your question directly, I’d start with a simple tool like Glock. It’s not hard to switch to a more sophisticated tool later if it becomes necessary.

Thanks for your comments about dependency management! I’m planning on doing something about it by version 1.0.

Do you have any preference? I can raise a PR for Glock if you’re happy with that choice. I can’t recommend Glide a.t.m. - it’s buggy. And I’d be happy without vendoring all code into git, personally.

We’re not ready for this yet, but thank you! I appreciate your feedback too; your perspective is helpful.

Forgive me if I seem too eager about this. But it’s not a big step.

Do you mind if I make a PR anyway to illustrate what’s involved (which is not really that much)?

This is not necessarily true, given the requirements of the build server. I’m still investigating this with the help of some plugin authors.

Sure, but it is likely to be closed. It will still be valuable in the future, I suppose, and we can refer back to it when we do make the vendoring step. Keep in mind I’m not sure yet which tool we’ll use. I try to keep things as simple as possible, so if the standard Go tooling supports vendoring, we’ll probably use that.

Are your build servers running Linux?

Yes. But that’s not the issue…

I’m curious now. How does it work? Is there a repo with the build server scripts etc?

Yep, it’s here: https://github.com/caddyserver/buildworker - will be deployed in about 3 weeks.

You may be interested in: https://github.com/mholt/caddy/pull/1651

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.