Cross compilation (Linux to Windows) produces hard to debug runtime bug
(Problem) Description
The terraform provider https://github.com/kevinvalk/terraform-provider-transip is using gotransip and I just added automatic CI building. Because of the golang crossplatform support, I decided to just compile for all different platforms from Linux.
However, the time.LoadLocation method does not work well when cross compiling from Linux to Windows (this is related to #31). Hence, whenever you use the gotransip library that calls int time.LoadLocation, you will get the error: "The system cannot find the path specified.".
Steps to reproduce
- Setup a Golang toolchain on Linux
- Build from Linux using
GOOS=windows GOARCH=amd64 go build
package main
import (
"log"
"github.com/transip/gotransip/v6"
"github.com/transip/gotransip/v6/domain"
)
func main() {
client, err := gotransip.NewClient(gotransip.DemoClientConfiguration)
if err != nil {
panic(err.Error())
}
name := "transipdemo.be"
repository := domain.Repository{Client: client}
domain, err := repository.GetByDomainName(name)
if err != nil {
log.Printf("failed to lookup domain %q: %s", name, err)
}
log.Printf("Domain: %v", domain)
}
- Run the produced executable on Windows
Note: cross compiling from Windows to Linux seems to work
Expected behaviour
2020/06/12 17:41:34 Domain: {[] ########## 0001-01-01 00:00:00 +0000 UTC false false false transipdemo.be 2011-04-29 00:00:00 +0200 CEST 2021-04-29 00:00:00 +0200 CEST}
Actual behaviour
2020/06/12 17:41:08 failed to lookup domain "transipdemo.be": The system cannot find the path specified.
2020/06/12 17:41:08 Domain: {[] ########## 0001-01-01 00:00:00 +0000 UTC false false false transipdemo.be 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC}
Suggested fix
After some googling I found two issues having similar problems
- https://github.com/golang/go/issues/14276
- https://github.com/golang/go/issues/19123
The proper fix would be to transfer times from the back-end in UTC and just keep it in UTC. If the user of the library would like to present times in local time it is up to them to print it for a specific timezone. In that case time.Parse can be used instead of time.ParseInlocation (see https://golang.org/pkg/time/#Parse).
Second best fix would be transfer times from the back-end with timezone information. Then once again time.Parse can be used instead of time.ParseInlocation (see https://golang.org/pkg/time/#Parse).
If that is difficult (because all times are saved in Europe/Amsterdam in the back-end), then I guess the best thing would be to just create a fixed timezone instead of using LoadLocation
loc := time.FixedZone("CEST", 2*60*60)
t, _ := time.ParseInLocation(`"2006-01-02"`, `"2011-04-29"`, loc)
fmt.Println(t)
I created a patch that resolves this using the "worst" of the suggestions: https://gist.github.com/kevinvalk/02a4f78abe7a9705b3404f0992b55df8
The problem is actually worse. Whenever you compile for Windows it turns out the executable can only run on the same machine (or probably very similar).
So this is not only about cross compiling. If you compile on a Windows machine (W10 recently patched) and move it to another Windows machine (also W10, different account, no developer tools, recently patched) you get the same error as above.
P.S. Sorry for the commit spam... I am still searching for a good way to debug GitHub actions (or any CI for that matter).