This is an experience report onboarding vgo for a relatively complex
project (multiple binaries, vast import tree, tricky unidiomatic imports).
I leave it here in the hopes that it guides other people, and potentially
illustrates places where vgo falls short of great. TL;DR it went pretty
well, modulo a couple of UX speed bumps.

The result is the `vgo-test` branch of https://github.com/google/metallb/ .
Cloning that repository should allow you to `vgo test ./...`, `vgo build
./controller`, `vgo build ./speaker`, and a few others. I don't make any
representation that the code does what it should, merely that it builds and
passes tests.

The resultant go.mod, https://github.com/google/metallb/blob/vgo-test/go.mod
, is quite messy. This is mostly due to the number of dependencies that
have no semver at all, forcing vgo to use commit hash "versions". The
result is a lot of visual noise in the file, but hopefully that will
improve over time as both vgo and dep nudge people towards semver releases.

I encountered two major roadblocks on the road to `vgo test ./...`: the
Kubernetes client library, and mixed case packages. These are
https://github.com/golang/go/issues/24032 and
https://github.com/spf13/jWalterWeatherman/issues/22 respectively.


The Kubernetes client library is a worst case scenario for vgo. It releases
a new major version every 3 months under the same module name, with real
incompatibilities between versions; and it relies extensively on a
transitive version lock to force a specific package selection on its
dependents. Making this library usable from vgo required the following:

   - Fix up client-go in a fork
      - Fork github.com/kubernetes/client-go to
      github.com/danderson/client-go
      - Add a go.mod to the fork, containing only: module "
      k8s.io/client-go/v6"
      - Update all internal self-references within client-go: perl -pi -e
      's#"k8s.io/client-go#"k8s.io/client-go/v6#g' **/*.go
      - Commit the result,
      
https://github.com/danderson/client-go/commit/7d8481153a9edbf8eacc176ce29f8d58949c3a77
      . Tag as v0.0.0-vgo-prototype-compat and push.
   - Make my repository use my fork of client-go:
      - Update all uses of client-go to the new versioned package name: perl
      -pi -e 's#"k8s.io/client-go#"k8s.io/client-go/v6#g' **/*.go
      - Require the right version in mod.go: require "k8s.io/client-go/v6"
      v6.0.0
      - Replace upstream with my fork in mod.go: replace "
      k8s.io/client-go/v6" v6.0.0 => "github.com/danderson/client-go"
      v0.0.0-vgo-prototype-compat

I'm curious how we could upstream the changes I had to make to client-go. I
had to rename module-internal imports, which will break existing non-vgo
uses of the library, but vgo offers no alternative to this renaming that
I'm aware of. It looks to me like there's no graceful upgrade path for this
module. The repo structure works either for pre-vgo clients, or for vgo,
but not both at once.

The UX was lacking to explain the reason for failures, before I made any of
the changes. Given just my repository, vgo inferred that I wanted v1.5.2 of
client-go (3+ years old), continued resolving dependencies, and eventually
barfed when it found an import for a client-go subpackage that didn't exist
in 1.5.2. The error was simply a bunch of "no such file or directory", and
required some head-scratching to understand what had happened. Once I
understood why vgo was making that decision, and how to correct it, vgo
provided the right tools (mostly replace-with-fork) to correct the issue
without waiting on the library to fix itself.


The second issue I hit is github.com/spf13/jwalterweatherman. The actual
repository name in github is "jWalterWeatherman", but everyone (including
the package's author :) ) imports it lowercase. vgo disallows this casing
mismatch.

To solve that, I just added a require + replacement to "fix" the
case: replace "github.com/spf13/jwalterweatherman"
v0.0.0-20180109140146-7c0cea34c8ec => "github.com/spf13/jWalterWeatherman"
v0.0.0-20180109140146-7c0cea34c8ec

The version to use in that replacement was hard to come by. Since vgo was
unable to compute the right dependency list without this replacement, it
bailed without giving me any version I might use. The date+hash format is
irritating to construct by hand, but could be trivially lifted into a tool
(perhaps even vgo itself). Instead, I opted to create a separate dummy
module, with a dummy main.go that imported and used the camelCased package,
and run vgo on that. This produced a tiny go.mod with a constructed commit
hash version, which I then used in MetalLB's go.mod. It would have been
nice for vgo to help me a bit more there.

- Dave



On Tue, Feb 20, 2018 at 9:20 AM, Russ Cox <r...@golang.org> wrote:

> Hi everyone,
>
> I have a new blog post you might be interested in.
> https://research.swtch.com/vgo.
>
> I'll try to watch this thread to answer any questions.
>
> Best,
> Russ
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to