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

Enforce consistent Go import organization using goimports #8198

Merged
merged 11 commits into from
Jan 23, 2025

Conversation

dan-stowell
Copy link
Contributor

@iain-macdonald (VSCode) and I (Zed) noticed our editors making seemingly-superfluous changes to Go imports on save. Turns out this is due to gopls running import organization logic.

It would be nice to consistently organize imports across the codebase the same way we consistently format Go code using gofmt. Luckily there's a tool that can do just that! goimports

This change adds goimports to buildfix.sh and to checkstyle.sh. Running buildfix.sh on a recent checkout touches 4 files. (Diff at the bottom). I can of course add these changes to this pull request if we want to move forward.

The downside of introducing this change is that people's editors may not adhere to goimports organization or may actively fight it. I don't want to cause headaches!

diff --git a/enterprise/server/sociartifactstore/sociartifactstore_darwin.go b/enterprise/server/sociartifactstore/sociartifactstore_darwin.go
index 8745f9b794..0b9270fb1f 100644
--- a/enterprise/server/sociartifactstore/sociartifactstore_darwin.go
+++ b/enterprise/server/sociartifactstore/sociartifactstore_darwin.go
@@ -8,7 +8,7 @@ import (
 
 	"github.com/buildbuddy-io/buildbuddy/server/environment"
 	"github.com/buildbuddy-io/buildbuddy/server/util/status"
-	"github.com/google/go-containerregistry/pkg/v1"
+	v1 "github.com/google/go-containerregistry/pkg/v1"
 
 	repb "github.com/buildbuddy-io/buildbuddy/proto/remote_execution"
 	socipb "github.com/buildbuddy-io/buildbuddy/proto/soci"
diff --git a/enterprise/server/sociartifactstore/sociartifactstore_test.go b/enterprise/server/sociartifactstore/sociartifactstore_test.go
index 84fb56bf67..057153f0e8 100644
--- a/enterprise/server/sociartifactstore/sociartifactstore_test.go
+++ b/enterprise/server/sociartifactstore/sociartifactstore_test.go
@@ -18,7 +18,7 @@ import (
 	"github.com/buildbuddy-io/buildbuddy/server/util/prefix"
 	"github.com/buildbuddy-io/buildbuddy/server/util/proto"
 	"github.com/buildbuddy-io/buildbuddy/server/util/status"
-	"github.com/google/go-containerregistry/pkg/v1"
+	v1 "github.com/google/go-containerregistry/pkg/v1"
 	"github.com/google/go-containerregistry/pkg/v1/empty"
 	"github.com/google/go-containerregistry/pkg/v1/mutate"
 	"github.com/google/go-containerregistry/pkg/v1/stream"
diff --git a/enterprise/server/util/cpuset/numcpu_linux.go b/enterprise/server/util/cpuset/numcpu_linux.go
index bd7f3b9cca..c5332c37d3 100644
--- a/enterprise/server/util/cpuset/numcpu_linux.go
+++ b/enterprise/server/util/cpuset/numcpu_linux.go
@@ -3,8 +3,9 @@
 package cpuset
 
 import (
-	"github.com/prometheus/procfs"
 	"strconv"
+
+	"github.com/prometheus/procfs"
 )
 
 func GetCPUs() []cpuInfo {
diff --git a/enterprise/server/util/fieldgetter/fieldgetter_test.go b/enterprise/server/util/fieldgetter/fieldgetter_test.go
index c91cd28df8..bfbd53ec41 100644
--- a/enterprise/server/util/fieldgetter/fieldgetter_test.go
+++ b/enterprise/server/util/fieldgetter/fieldgetter_test.go
@@ -2,9 +2,10 @@ package fieldgetter_test
 
 import (
 	"fmt"
+	"testing"
+
 	"github.com/buildbuddy-io/buildbuddy/enterprise/server/util/fieldgetter"
 	"github.com/stretchr/testify/assert"
-	"testing"
 )
 
 type Parent struct {

@dan-stowell dan-stowell requested a review from bduffany January 16, 2025 20:09
Copy link
Member

@bduffany bduffany left a comment

Choose a reason for hiding this comment

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

LGTM - would be good to get some reviews from other folks as well before merging

btw, for vscode, I had to add this to my settings.json to get goimports-on-save to work properly:

  "[go]": {
    "editor.codeActionsOnSave": {
      "source.organizeImports": "explicit"
    }
  },

we could maybe add this to our vscode setup guide in the internal site (https://github.com/buildbuddy-io/buildbuddy-internal/blob/master/website/docs/development-environment.md)

BUILD Outdated
Comment on lines 219 to 234
alias(
name = "goimports",
actual = "@org_golang_x_tools//cmd/goimports",
visibility = ["//visibility:public"],
)

genrule(
name = "goimports_bin",
outs = ["goimports.sh"],
cmd = """
echo '#!/bin/bash' > $@
echo 'exec $(location @org_golang_x_tools//cmd/goimports) "$$@"' >> $@
chmod +x $@
""",
tools = ["@org_golang_x_tools//cmd/goimports"],
)
Copy link
Member

@bduffany bduffany Jan 16, 2025

Choose a reason for hiding this comment

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

(nit - instead of using $(location) does it work if we run @org_golang_x_tools//cmd/goimports directly, similar to how we run @npm//prettier/bin:prettier which is also an external dep?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That absolutely works! Thanks. Lol, goimports.sh was failing to find goimports when run in CI.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Scratch that. What pushed me to writing the goimports.sh rule in the first place is that running bazel run //:goimports would execute outside the current working directory. I don't know how to get the absolute path of goimports without calling $(location ...).

Copy link
Contributor

@iain-macdonald iain-macdonald left a comment

Choose a reason for hiding this comment

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

I mostly just care about not having to think about stuff like this too much, so this seems like a good change in that regard. That said, we have historically grouped inputs into three groups: library-level ones (like "fmt"), unaliased imports, and then aliased imports, with each group separated by an empty line, like this:

"bytes"
"context"
"flag"
"os"
"strings"
"time"
"github.com/buildbuddy-io/buildbuddy/server/remote_cache/cachetools"
"github.com/buildbuddy-io/buildbuddy/server/remote_cache/digest"
"github.com/buildbuddy-io/buildbuddy/server/util/grpc_client"
"github.com/buildbuddy-io/buildbuddy/server/util/log"
"github.com/buildbuddy-io/buildbuddy/server/util/proto"
"github.com/buildbuddy-io/buildbuddy/server/util/status"
"github.com/mattn/go-isatty"
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/encoding/protojson"
bbspb "github.com/buildbuddy-io/buildbuddy/proto/buildbuddy_service"
capb "github.com/buildbuddy-io/buildbuddy/proto/cache"
repb "github.com/buildbuddy-io/buildbuddy/proto/remote_execution"
rspb "github.com/buildbuddy-io/buildbuddy/proto/resource"
bspb "google.golang.org/genproto/googleapis/bytestream"

Do you know if there's a way to get goimports to do that automatically?

@tylerwilliams
Copy link
Member

I'm cool with this if that's the diff!

2 minor questions/nits I have are:

  1. what's with the v1 named import thing it's doing, seems kinda fucky?
  2. I would like to keep the imports grouped the way we have them e.g.:
import (
  builtins
  
  custom packages

  alias ... aliased packages
)

I don't think goimports will break this, but I have seen some editors group aliases and non-aliased stuff together which is 🤮 This change won't break anything here, right?

@vadimberezniker
Copy link
Member

As mentioned in your other PR, I would manually alias the v1 import to something else since v1 is not a descriptive name. You can't even tell what module it's related to w/o looking at the imports.

@iain-macdonald
Copy link
Contributor

As mentioned in your other PR, I would manually alias the v1 import to something else since v1 is not a descriptive name. You can't even tell what module it's related to w/o looking at the imports.

That's what the Google Style Guide recommends: https://google.github.io/styleguide/go/decisions.html#imports so seems reasonable to me that we just adopt that convention.

BUILD Outdated Show resolved Hide resolved
Comment on lines 54 to +58
run GoFormat \
"$GOFMT_PATH" -d .

run GoImports \
"$GOIMPORTS_PATH" -d .
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: https://pkg.go.dev/golang.org/x/tools/cmd/goimports

In addition to fixing imports, goimports also formats your code in the same style as gofmt so it can be used as a replacement for your editor's gofmt-on-save hook.

So we can replace GoFormat with GoImports

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I want to test it, but yes, good point!

Co-authored-by: Fabian Meumertzheim <[email protected]>
@dan-stowell
Copy link
Contributor Author

  1. what's with the v1 named import thing it's doing, seems kinda fucky?

Does seem wrong. This blog post mentions packages named after major versions, saying that you should just use the real package name. Not sure why goimports does this.

If I explicitly alias to gcr, though, goimports does not complain or try to change it.

  1. I would like to keep the imports grouped the way we have them e.g.:
import (
  builtins
  
  custom packages

  alias ... aliased packages
)

goimports will not break this grouping. However, it won't group imports this way on its own. There are two other tools, gci and goimports-reviser that promise to have a separate group for aliased packages, but they also seem to promise other stuff.

@dan-stowell dan-stowell merged commit d5eef28 into master Jan 23, 2025
15 checks passed
@dan-stowell dan-stowell deleted the dan/goimports branch January 23, 2025 22:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants