Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Go modules #751

Merged
merged 6 commits into from
Oct 30, 2019
Merged

Add support for Go modules #751

merged 6 commits into from
Oct 30, 2019

Conversation

abhinav
Copy link
Collaborator

@abhinav abhinav commented Oct 29, 2019

This switches Zap to using Go modules instead of Glide for managing
dependencies, while keeping the glide.yaml around to provide
constraints for legacy ecosystems.

The change ended up being more complicated than a go mod init because
Zap has a few tests that verify its behavior inside GOPATH and a
vendor/ directory. Those tests were passing fine in CI for #742 because
of the go_import_path directive in the Travis configuration which
places it under $GOPATH/src/go.uber.org/zap. This isn't necessary
with Go modules but I've left it in-place for now.

Note that to keep the direct dependencies of Zap small, the benchmarks/
directory was turned into its own Go module with a replace clause
pointing to the local copy of Zap. We will not tag a release of the
benchmarks/ module.

Supersedes #742
Resolves #639


Note to reviewers: Each commit is meant to be reviewed individually.
The change should not be squashed when merged.

This switches Zap to using Go modules.

To keep the list of direct dependencies of Zap minimal, benchmarks are
placed in their own Go module as per [Multi-Module Repositories][1].

This change deletes the glide.lock but keeps the glide.yaml around for
legacy ecosystems.

[1]: https://github.com/golang/go/wiki/Modules#faqs--multi-module-repositories
With Go modules, the location of global_test on disk does not have to be
in `$GOPATH/src/go.uber.org/zap`, or even in a directory named `zap`.
This simplifies the assertion to verify just the file name.
@abhinav abhinav force-pushed the abg/modules branch 3 times, most recently from 3c19977 to 3c78cc9 Compare October 29, 2019 23:38
@codecov
Copy link

codecov bot commented Oct 29, 2019

Codecov Report

Merging #751 into master will increase coverage by 0.64%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #751      +/-   ##
==========================================
+ Coverage   97.44%   98.09%   +0.64%     
==========================================
  Files          40       42       +2     
  Lines        2117     2150      +33     
==========================================
+ Hits         2063     2109      +46     
+ Misses         46       33      -13     
  Partials        8        8
Impacted Files Coverage Δ
internal/ztest/writer.go 100% <0%> (ø)
internal/ztest/timeout.go 86.66% <0%> (ø)
zapcore/console_encoder.go 100% <0%> (+3.5%) ⬆️
zapcore/entry.go 94.5% <0%> (+4.39%) ⬆️
zapcore/write_syncer.go 90.47% <0%> (+11.9%) ⬆️
buffer/buffer.go 100% <0%> (+12.9%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0065243...39ba1b2. Read the comment docs.

Copy link
Collaborator

@prashantv prashantv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, minor simplication suggest for stacktrace_ext_test

Makefile Outdated
GO_VERSION := $(shell go version | cut -d " " -f 3)
GO_MINOR_VERSION := $(word 2,$(subst ., ,$(GO_VERSION)))
LINTABLE_MINOR_VERSIONS := 12
LINTABLE_MINOR_VERSIONS := 13
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional: should we just the LINT=yes in travis to control this, so lint versions are controlled in the same place go versions we test against are controlled?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reasonable. That's what we do in the other projects. Switching.

Makefile Outdated
.PHONY: test
test:
go test -race $(PKGS)
go test -race ./...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even though the benchmarks module has no tests, in case we add future modules, should this also be a $(foreach dir,$(MODULE_DIRS),...)

otherwise let's add a comment near MODULE_DIRS that we only test the main module

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding foreach for make test but not for cover because then we'll have to deal with cross-module coverage merging. Adding a comment that we track coverage only for the main module.

cmd := exec.Command("go", "test", "-v", "-run", "TestStacktraceFiltersZap")
cmd.Dir = testDir
cmd.Env = envWith(t, "GO111MODULE=off")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this could be simplified to:

cmd.Env = append(os.Environ(), "GO11MODULE=off")

since duplicate entries causes the last value to be used;

// If Env contains duplicate environment keys, only the last
// value in the slice for each duplicate key is used.

https://golang.org/pkg/os/exec/#Cmd

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♀

func downloadDependencies(t *testing.T) []dependency {
cmd := exec.Command("go", "mod", "download", "-json")

stdout, err := cmd.StdoutPipe()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is streaming worth it here, suggest simplifying to:

stdout, err := cmd.Output()
require.NoError(t, err, ...)

dec := json.NewDecoder(bytes.NewReader(stdout))

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, streaming is necessary here. The output contains a series of newline-delimited JSON objects.

Per go help mod download,

By default, download reports errors to standard error but is otherwise silent.
The -json flag causes download to print a sequence of JSON objects
to standard output, describing each downloaded module (or failure),
corresponding to this Go struct:

    type Module struct {
        Path     string // module path
        Version  string // module version
        Error    string // error loading module
        Info     string // absolute path to cached .info file
        GoMod    string // absolute path to cached .mod file
        Zip      string // absolute path to cached .zip file
        Dir      string // absolute path to cached source root directory
        Sum      string // checksum for path, version (as in go.sum)
        GoModSum string // checksum for go.mod (as in go.sum)
    }

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to use json.NewDecoder since the output has multiple objects, but I don't think we need to use a pipe -- we can get all the output at once and then use json.NewDecoder

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see what you mean. Switching.

@abhinav
Copy link
Collaborator Author

abhinav commented Oct 30, 2019

Updated based on comments.

This fixes TestStacktraceFiltersVendorZap to work with Go modules.

For context, the test previously did the following:

- Set up a temporary GOPATH
- Copy stacktrace_ext_test.go into it
- Symlink Zap and relevant dependencies into a vendor/ directory in the
  temporary GOPATH
- Run specific tests from stacktrace_ext_test.go with Zap inside the
  vendor/ directory

We're no longer using GOPATH or vendor/ directories, but this behavior
of Zap when *it* is inside a vendor/ directory should be retained.

To that end, this changes TestStacktraceFiltersVendorZap to continue to
run with the following changes:

- Use `go mod download -json` to retrieve the locations of all of Zap's
  dependencies on-disk, and symlink them into the temporary GOPATH's
  vendor/.
- Explicitly set `GO111MODULE=off` before running `go test` because we
  may be running in an environment where `GO111MODULE=on` is set.
The benchmarks package has been placed inside its own module so that its
dependencies are not considered Zap's dependencies.

This changes the README update script to run the benchmark inside the
benchmark module's directory since we can no longer invoke it from Zap's
top-level directory.
This switches the Makefile and travis setup to rely on Go modules and
`./...` instead of `glide nv`.

Note that a tradeoff of making `benchmarks/` its own module is that
`./...` in the Zap directory will no longer include the `benchmarks/`
directory. So where necessary, we need to run commands separately in
that directory as well, which complicates the build script ever so
slightly.
Rather than hard-coding the Go version we lint against in the Makefile,
this switches to managing that in the .travis.yml -- the same place we
manage the versions we're testing against.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Go Modules
2 participants