nanobox-io / nanobox-engine-golang

Engine for running Go apps with Nanobox
https://nanobox.io
MIT License
4 stars 6 forks source link

Placing code straight into 'code_dir' may not work in all cases #2

Closed glinton closed 8 years ago

glinton commented 8 years ago

In some go projects apps require parts of themselves in full GOPATH syntax: "github.com/nanopack/yoke/config" and others relative: "./api". The relative-ly required projects will build and run just fine "as-is" using the golang engine. Unless we can somehow determine where on the GOPATH we need to place code, we need to create a way for users to specify where to place their code.

Errors from using GOPATH syntax look like this:

   main.go:4:2: cannot find package "github.com/blobstache/blobstache/api" in any of:
    /data/go/src/github.com/blobstache/blobstache/api (from $GOROOT)
    /opt/code/_vendor/src/github.com/blobstache/blobstache/api (from $GOPATH)
    /opt/code/src/github.com/blobstache/blobstache/api
    /opt/code/_vendor/src/github.com/blobstache/blobstache/api
tylerflint commented 8 years ago

Ok, I've spent some time thinking about this and discussing potential solutions with some of the go developers on the team. We can do this, but it will be a bit tricky! This solution will have to be broken into multiple parts, and one of them being a new feature added to nanobox-server (which is currently published to dev).

So here's what it looks like, broken down into each piece:

gopath as a lib_dir

We'll need to start by ensuring that GOPATH is actually stored inside of a lib_dir. This is just so that deps installed with 'go get' while in 'nanobox dev' mode will be persistent between sessions. The official go code guide calls it a "workspace". Perhaps we could call the lib_dir '.workspace'.

package path

Following the guide, a project should be located within the $GOPATH at the following: $GOPATH/src/github.com/user.

The problem to address here is that we have no way of knowing either the repository root (github.com, bitbucket.com, etc) or the user. We can't rely on the .git/config for at least 3 reasons: 1) the .git directory is ignored when copying source code into the build 2) a project using nanobox desktop isn't guaranteed to use git at all and 3) when using nanobox cloud, the git repo will not be the github repo.

Technically, the package path could be anything, say $GOPATH/src/foo/bar. This will work, except when the source depends on sub-packages of itself and uses the absolute path to do so. Here is an example.

To determine a package path, I propose that we first try to deduce the official repo/user of the project from the imports in main.go. If the project doesn't import a sub-package of itself, then we fallback to a default of $GOPATH/src/nanobox.io/<app_name>. Lastly, we allow a Boxfile attribute 'package_path' to explicitly set the path.

I imagine there are several ways that the official path could be determined, assuming the package imports itself. Grep, sed, awk, could be used, or also go list -f {{.Imports}} could provide the initial list.

working directory

The last problem to deal with, is that for go build to work, the working directory must be inside of the application source within the $GOPATH. This means that we cannot simply run go build from inside the /code directory. In order for this to work, we will need to do two things: 1) create a symlink from /code to the package_path as determined above and 2) we will need to drop the user into the gopath directory instead of /code in a 'nanobox dev' session.

nanobox-server has recently added a new feature, that will allow an engine to specify the working directory of a dev session. The 'dev' section of the Boxfile can use the 'working_dir' attribute to specify this, which can be provided in the boxfile bin script. For example:

dev:
    working_dir: '/code/.workspace/src/github.com/nanopack/yoke'

With all of these pieces working together, the go engine should work!