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

go run support for versioned modules (Go 1.17+) #134

Merged

Conversation

svengreb
Copy link
Owner

@svengreb svengreb commented Jul 9, 2023

Resolves #133

As of Go 1.17 the `go run` command can finally run in module-aware
mode [1] while not "polluting" the current module in the working
directory, if there is one (`go.mod` file present) 🎉
This finally allows to run commands "on-the-fly" [10] of Go `main`
module packages without installing them or without changing dependencies
of the current module!

To support this feature with wand a new `task.GoModule` [2] has been
implemented in a new `golang/run` [3] package.
It can be run using a command runner [4] that handles tasks of kind
`KindGoModule` [5] so mainly `gotool.Runner` [6].

The new `golang/run.Task` [3] is customizable through the following
functions:

- `WithArgs(...string) run.Option` - sets additional arguments to pass
  to the command.
- `WithEnv(map[string]string) run.Option` - sets the task specific
  environment.
- `WithModulePath(string) run.Option` - sets the module import path.
- `WithModuleVersion(*semver.Version) run.Option` - sets the module
  version.

Next to the new task the `gotool.Runner` [6] has been extended with a
new `WithCache(bool)` [9] runner option to toggle the usage of the local
cache directory in the root directory of the module. The runner has been
made "smart" in the way that it either...

- installing the executable through a `golang.Runner` [8], which runs
  `go install pkg@version` to leverage Go 1.16's feature [12], and
  execute it afterwards. This is the current default behavior of this
  runner which will be used when `WithCache(true)` [9] is used.
- pass the task to a `golang.Runner` [8], using the new `golang/run` [3]
  package task, so that it can run `go run pkg@version <args>` instead.
  This is the new "smart" behavior of the runner which will be used when
  `WithCache(false)` [9] (default) is used.

The new default behavior is to not use a local cache so that caching
will be a opt-in!
This decision was made because native support for running commands
"on-the-fly" should always be preferred to custom logic which is what
the local cache directory and [gotool.Runner` [6] purpose is.

!!!
  Note that the minimum Go version for task runners, the new
  `golang/run`
  task [3] and the "Elder" wand [7] has been increased to `1.17.0` since
  this version initially introduced `go run` support in module-awar
  mode [1]!
  This is enforced through a build constraint [11] (`go:build go1.17`).
!!!

The `Elder` [7] reference implementation has also adapted to this new
feature by...

1. deprecating the `*elder.Elder.Bootstrap(...string) []error` method!
   As of wand version `0.9.0` it will be a no-op and will be removed in
   version `0.10.0`. To install executables anyway the new
   `*elder.Elder.CacheExecutables error` method should be used instead.
   To ensure that the wand is properly initialized and operational the
   `*elder.Elder.Validate(..task.Runner) []error` method is the way to
   go. A warning message will be printed when the method is called to
   ensure that users adapt accordionally.
2. providing a new `*elder.Elder.CacheExecutables(...string) error`
   method which allows to pass paths of Go modules that should be
   explicitly installed to the local cache directory. This method is a
   kind of workaround for the, now deprecated,
   `*elder.Elder.Bootstrap(...string) []error` method to allows users to
   still cache command executables locally.
3. changing the signature of the `*elder.Elder.Validate() error` method
   to `*elder.Elder.Validate(...task.Runner) []error` method which
   allows users to ensure that the _wand_ is properly initialized an
    operational. Optionally command runner [4] can be passed that will
    be validated while passing nothing will validate all currently
    supported runners.

[1]: https://go.dev/doc/go1.17#go%20run
[2]: https://pkg.go.dev/github.com/svengreb/wand@v0.9.0/pkg/task#GoModule
[3]: https://pkg.go.dev/github.com/svengreb/wand@v0.9.0/pkg/task/golang/run
[4]: https://pkg.go.dev/github.com/svengreb/wand@v0.9.0/pkg/task#Runner
[5]: https://pkg.go.dev/github.com/svengreb/wand@v0.9.0/pkg/task#KindGoModule
[6]: https://pkg.go.dev/github.com/svengreb/wand@v0.9.0/pkg/task/gotool#Runner
[7]: https://pkg.go.dev/github.com/svengreb/wand@v0.9.0/pkg/elder
[8]: https://pkg.go.dev/github.com/svengreb/wand@v0.9.0/pkg/task/golang#Runner
[9]: https://pkg.go.dev/github.com/svengreb/wand@v0.9.0/pkg/task/golang/run#WithCache
[10]: https://pkg.go.dev/cmd/go#hdr-Compile_and_run_Go_program
[11]: https://pkg.go.dev/cmd/go#hdr-Build_constraints
[12]: #89

GH-133
@svengreb svengreb added this to the version-next milestone Jul 9, 2023
@svengreb svengreb self-assigned this Jul 9, 2023
@svengreb svengreb merged commit 37858a3 into main Jul 9, 2023
1 of 3 checks passed
@svengreb svengreb deleted the feature/gh-133-go-1.17-run-support-versioned-modules branch July 9, 2023 13:14
@svengreb svengreb removed their assignment Jul 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

go run support for versioned modules (Go 1.17+)
1 participant