Go modules

Is the Go plugin going to need any work done to support the new Go modules in Go 1.11?

2 Likes

@eberkund did you ever get a answer regarding this? I’m wondering about that right now actually.

Yeah I got it working using the go snap rather than the built in plugin. See below.

  myapp:
    plugin: nil
    source: .
    build-snaps: [go]
    override-build: |
      export GOBIN=$SNAPCRAFT_PART_INSTALL/bin
      export GO111MODULE=on
      export CGO_ENABLED=0
      go build

If all you need is that environment, just use bases, as the go snap is the default there, and in the part using the go plugin add

build-environment:
- GO11MODULE: on

Cool, I just tried that and it looks like it would work in cases where your main package uses a name like “github.com/my/app” but it doesn’t work in cases where the the modules use just “app” as the root namespace.

erik@ubuntu ~/C/myapp> snapcraft --debug
Using 'snap/snapcraft.yaml': Project assets will be searched for from the 'snap' directory.
Launching a VM.
Using 'snap/snapcraft.yaml': Project assets will be searched for from the 'snap' directory.
Updating pull step for defaults (source changed)
Pulling myapp 
go get -t -d ./project/...
go get: -t flag is a no-op when using modules
go: cannot find main module; see 'go help modules'
Failed to run 'go get -t -d ./project/...' for 'myapp': Exited with code 1.
Verify that the part is using the correct parameters and try again.
snapcraft-myapp # go get -t -d ./project/...
package myapp/cmd: unrecognized import path "myapp/cmd" (import path does not begin with hostname)
...

It’s more than just setting an environment variable. The part source needs to be outside of $GOPATH/src. This blog post includes a quick rundown of the new build system:

I think the main take-aways are:

  1. We can detect Go projects using the new build system by the presence of a go.mod in the base source directory. If found, we require Go >= 1.11 to build, and should not try to symlink the source into $GOPATH/src. We still need $GOPATH to be set, however.

  2. The project’s Go package name can be determined by reading the module line in go.mod. It should not be taken from go-importpath. A warning should be issued if go-importpath is specified in the snapcraft.yaml, or if it differs from what is specified in go.mod.

  3. For the pull stage, dependencies should be downloaded using go mod download in the source directory rather than go get. This will ensure versions matching the go.mod file are downloaded.

  4. To build packages that are part of the source part, run go build in the source directory.

2 Likes

There’s an issue for this in Launchpad: https://bugs.launchpad.net/snapcraft/+bug/1802256

I ran into the same issue as @eberkund too.

Pulling fluxctl 
go get -t -d ./github.com/weaveworks/flux/...
go get: -t flag is a no-op when using modules
go: cannot find main module; see 'go help modules'
Failed to run 'go get -t -d ./github.com/weaveworks/flux/...' for 'fluxctl': Exited with code 1.

In my spare time, I started looking at updating the plugin. I didn’t get anything working before GUADEC, but pushed the results up here:

This is completely untested: it might be useful for anyone else who wants to try implementing the feature, but is nowhere near ready for people wanting to build Go snaps.

2 Likes

@jamesh Thanks for starting on this! I saved your modified plugin as a local plugin and it worked for my go modules project. I am unfamiliar with the snapcraft src but I’ll update your fork if I make changes or run into issues.

steps:

  1. Fetch the plugin

     # from project root
     mkdir -p snap/plugins
     wget -O snap/plugins/go_local.py https://raw.githubusercontent.com/jhenstridge/snapcraft/5b94b2ab30e53d3a3339bdba31b29c06a70b4145/snapcraft/plugins/go.py
    
  2. Then modify snapcraft.yaml to use the local plugin:

    snapcraft.yaml

     ...
     parts:
       my-project:
         plugin: go-local
    
  3. Run snapcraft as usual.

     $ snapcraft
     Launching a VM.
     Searching for local plugin for go-local
     ...
     Ignoring `go-importpath' for the 'kubectl-iexec' part, in favour of go.mod definition