-
Notifications
You must be signed in to change notification settings - Fork 70
feat(compute/build): support native go #995
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
Conversation
|
NOTE: I had an internal discussion with reviewer @joeshaw and after a lengthy back-and-forth about how to avoid a major release, we decided that a major release was probably the best approach (as none of the alternatives were clear winners and each approach had its own set of caveats). |
|
@joeshaw once you've merged fastly/compute-starter-kit-go-default#8 let me know so I can quickly retest this PRs changes to be sure |
.fastly/config.toml
Outdated
| [language.go] | ||
| tinygo_constraint = ">= 0.26.0-0" # NOTE -0 indicates to the CLI's semver package that we accept pre-releases (TinyGo users commonly use pre-releases). | ||
| toolchain_constraint = ">= 1.18" | ||
| tinygo_constraint = ">= 0.26.0-0" # NOTE -0 indicates to the CLI's semver package that we accept pre-releases (TinyGo users commonly use pre-releases). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mentioned this in fastly/compute-starter-kit-go-default#8 but version 0.2.0 of the SDK brings the TinyGo requirement up to >= 0.28.1.
pkg/commands/compute/language_go.go
Outdated
| // who don't have a `scripts.build` defined. | ||
| // | ||
| // NOTE: Only used if `toolchain = "go"` and if Go 1.21+ is installed. | ||
| const GoDefaultBuildCommand = "env GOARCH=wasm GOOS=wasip1 go build -o bin/main.wasm ./" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not confident env is going to work on Windows, so it's worth checking this if CI doesn't already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I wasn't confident this would work on Windows but CI (which runs the full test suite) seems to think there were no issues 🤔
In general would we just remove the env and just prefix the build script with GOARCH/GOOS? Not sure if exec.Command needs env.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
env is required because exec.Command doesn't run a shell. We could set the environment outside of the command-line, but that obviously complicates things if we want the end user control over things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can set the environment with https://pkg.go.dev/os/exec#Cmd.Environ , although that would require parsing the command line with https://pkg.go.dev/github.com/google/shlex or something to extract the environment variable settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dgryski I think it's fine to set the environment without shlex because we know what the default values for those should be (i.e. they're already hard-coded into the binary GOARCH=wasm GOOS=wasip1). So I'll look at doing that on Wednesday when I'm back from PTO.
Once the user starts defining their own build script, then things are a little out of our hands but I imagine if someone wants to define their own build script, then they could just do an export directly in their shell as a workaround. I'm not sure in practice how many people are going to stray from the pre-defined default paths in the CLI (for either Go or TinyGo)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Integralist Do you mind making make test pass -v to go test (or making a target that does)? It'd be good to see the verbose output of the tests in the CI build logs and give me more confidence that the Windows build is working as it should.
Running TEST_COMPUTE_BUILD=1 go test -v ./pkg/commands/compute on my Mac gives me:
=== RUN TestBuildGo/build_success
build_test.go:333: Fastly API token not provided
Fastly API endpoint: https://api.fastly.com
| Verifying fastly.toml...
✓ Verifying fastly.toml
| Identifying package name...
✓ Identifying package name
| Identifying toolchain...
✓ Identifying toolchain
INFO: Creating ./bin directory (for Wasm binary)
INFO: No [scripts.build] found in fastly.toml. The following default build command for Go will be used: `env GOARCH=wasm GOOS=wasip1 go build -o bin/main.wasm ./`
INFO: The standard Go compiler >= 1.21 now supports WASI. To keep using TinyGo set `[scripts.toolchain]` to 'tinygo'.
INFO: The Fastly CLI requires a go version '>= 1.21'.
Build script to execute:
sh -c env GOARCH=wasm GOOS=wasip1 go build -o bin/main.wasm ./
INFO: Command output:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
✓ Running [scripts.build]
| Creating package archive...
/ Creating package archive...
✓ Creating package archive
SUCCESS: Built package (pkg/test.tar.gz)
Which also shows that the script is run inside a shell, so I think env is unnecessary, at least on Unix.
|
Question: Is there some reasons about why |
|
@JakeChampion I originally had it top-level but moved it to scripts as it felt out of place at the top level. Also, as per https://developer.fastly.com/reference/compute/fastly-toml/
So as this is customising the build process it made sense (to me) to have toolchain added to scripts. |
|
I'm quite confused about scripts.toolchain. I expect my build to be executed using scripts.build, and so I wonder at what point does the scripts.toolchain command get executed on the shell? |
|
Oh, catching up on your comment about the definition of "scripts" @Integralist... that's not how I interpret scripts, scripts are surely executable commands? |
|
@triblondon I'm happy to move this back to the top-level if you feel it's more appropriate there. |
|
I am not a Go developer, so feel free to override me if this is expected in the Go community. I would have a hard time understanding how Is it not possible to just change the default build command in the CLI? It seems to me that we are already going to switch tinygo users to go automatically, with a warning about adding |
c08f58c to
1fda128
Compare
Looks like we'll have to go down the https://pkg.go.dev/os/exec#Cmd.Environ route. This would mean not setting those environment variables in the build script command for Windows users. |
242f8d4 to
78cc351
Compare
|
@joeshaw @dgryski last commit fixed Windows issue |
|
@Integralist did |
|
It looks like I think we might want to not automatically set |
Specifically, |
bfb9747 to
5efa4a6
Compare
This reverts commit 242793a.
|
@joeshaw I'm not sure what problem exists in the test suite implementation that would cause it to fail for the tests but work in practice (as demonstrated by the CI job you linked to). |
|
@joeshaw looks like my tests neglected to include So all is good now and ready for your final review. |
|
UPDATE: The use of I'm PTO for just over a week, so I'll wrap up this outstanding work when I return. |
|
An additional feature request as part of this PR: we should ensure that the binary output is actually a wasm file. If you ran a There's nothing we can do about this for existing versions (and The binary format (including the magic and version info at the start of a file) are defined here: https://webassembly.github.io/spec/core/binary/modules.html#binary-module |
|
@joeshaw OK I've implemented the Have another review and give this PR an official 'approval' if you're happy with it. Thanks! |
| magic = magic[1:] // Remove the first byte which is a null character "\x00" | ||
| } | ||
| if string(magic) != "asm" { | ||
| return bt.handleError(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err will be nil in this case, so you'll need to construct your own error here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs addressing. err will be nil here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EURGH! Sorry 😞
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pushed a change.
|
@joeshaw one more review if you can please 🙂 🙇🏻 |
| // NOTE: The `configConstraint` is the latest CLI application config version. | ||
| // If there are any errors trying to parse the go.mod we'll default to the | ||
| // config constraint. | ||
| func identifyTinyGoConstraint(configConstraint, fallback string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this turns out to be too fragile, we can switch to https://pkg.go.dev/golang.org/x/mod/modfile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool thanks. I think our use case is simple enough but yeah if in the real-world it's starts being a problem we can pick up a tool like that 👍🏻
joeshaw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for your persistence on this. 👍 LGTM
@joeshaw thank you for all the great feedback and patience with my silly mistakes 🙂 I'm just sorry this took so much of your time to review, so I appreciate your efforts here. |
This PR adds support for native Go when using the latest SDK (0.2.0) and an updated Go starter kit (not yet released).
For screenshots and details see here
This PR is blocking: fastly/compute-starter-kit-go-default#8
This is NOT a breaking-release, even though we bump the constraints for tinygo and standard go (required for the new Go SDK). That's because we parse the go.mod to see if the user has an SDK version
< 0.2.0and if so we (at runtime) downgrade the constraint to>= 0.26.0rather than use the new constraint of>= 0.28.1.Original PR description/details below...
This PR switches from using TinyGo to native Go.
Users are able to continue using TinyGo by adding a[scripts.toolchain]into theirfastly.tomlmanifest file:Examples
1
The following example demonstrates a new user, with go1.21 installed, and no other non-standard configuration.
We can see that the native Go build command is used (as it now supports WASI).
We can also see that we display a message to the user informing them of what they need to do to continue using TinyGo (if they are trying to build a pre-existing project that previously would have used TinyGo).
2
The following example demonstrates the error the user will see if they have go1.21 installed but have
[scripts.toolchain]set to TinyGo.Notice that TinyGo itself doesn't yet support go1.21.
3
The following example demonstrates a new user, with go1.18 installed, who has
[scripts.toolchain]set to TinyGo.4
The following example demonstrates the error the user will see if they have go1.18 installed but have
[scripts.toolchain]set to native Go.Notice the CLI has an explicit constraint on
toolchain = "go"using Go 1.21 and that the version of Go the user has installed doesn't yet support WASI.5
The following example demonstrates a new user, with go1.21 installed, who has no
[scripts.toolchain]set but does have a custom[scripts.build]configured to use native Go.6
The following example demonstrates a new user, with go1.18 installed, who has no
[scripts.toolchain]set but does have a custom[scripts.build]configured to use TinyGo.Notice how although native Go is now the default behaviour, because the user has go1.18 installed, and TinyGo, and they've configured their custom build script to use TinyGo, the CLI does indicate a warning that the constraint wasn't met (and also that the user should add
toolchain = "tinygo") but ultimately the build succeeded as they were using all the right tools and scripts.The reason this is slightly problematic is because the toolchain constraint defaults to native Go (i.e. go1.21) and only changes to go1.18 when
[scripts.toolchain]is configured. If that's not configured, like in this example, we don't then want to get into the business of trying to manually parse[scripts.build]to understand what a user has entered. We could try and do a glob search for "tinygo" but we don't know if a user has tinygo aliased or they downloaded it manually astgoor whatever the situation might be. We can't presume to know the context of the custom build script.