diff --git a/changes/issue-7036-windows-msi b/changes/issue-7036-windows-msi new file mode 100644 index 0000000000..d1688974fd --- /dev/null +++ b/changes/issue-7036-windows-msi @@ -0,0 +1 @@ +* Fixed a bug preventing `.msi` installers to be generated on Windows machines. diff --git a/orbit/pkg/packaging/wix/wix.go b/orbit/pkg/packaging/wix/wix.go index 90800de082..a325238dd6 100644 --- a/orbit/pkg/packaging/wix/wix.go +++ b/orbit/pkg/packaging/wix/wix.go @@ -7,26 +7,12 @@ import ( "fmt" "os" "os/exec" - "strings" ) const ( - directoryReference = "ORBITROOT" - linuxPathSeparator = "/" - windowsPathSeparator = "\\" + directoryReference = "ORBITROOT" ) -// windowsJoin returns the result of replacing each slash ('/') character in -// each path with a Windows separator character ('\') and joining them using -// the Windows separator character. -// -// We can't use filepath.FromSlash because this func is run in a *nix -// machine. -func windowsJoin(paths ...string) string { - s := strings.Join(paths, windowsPathSeparator) - return strings.ReplaceAll(s, linuxPathSeparator, windowsPathSeparator) -} - // Heat runs the WiX Heat command on the provided directory. // // The Heat command creates XML fragments allowing WiX to include the entire @@ -39,14 +25,14 @@ func Heat(path string, native bool) error { args = append( args, "docker", "run", "--rm", "--platform", "linux/amd64", - "--volume", path+":"+path, // mount volume + "--volume", path+":/wix", // mount volume "fleetdm/wix:latest", // image name ) } args = append(args, - "heat", "dir", windowsJoin(path, "root"), // command - "-out", windowsJoin(path, "heat.wxs"), + "heat", "dir", "root", // command + "-out", "heat.wxs", "-gg", "-g1", // generate UUIDs (required by wix) "-cg", "OrbitFiles", // set ComponentGroup name "-scom", "-sfrag", "-srd", "-sreg", // suppress unneccesary generated items @@ -57,6 +43,10 @@ func Heat(path string, native bool) error { cmd := exec.Command(args[0], args[1:]...) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if native { + cmd.Dir = path + } + if err := cmd.Run(); err != nil { return fmt.Errorf("heat failed: %w", err) } @@ -75,14 +65,13 @@ func Candle(path string, native bool) error { args = append( args, "docker", "run", "--rm", "--platform", "linux/amd64", - "--volume", path+":"+path, // mount volume + "--volume", path+":/wix", // mount volume "fleetdm/wix:latest", // image name ) } args = append(args, - "candle", windowsJoin(path, "heat.wxs"), windowsJoin(path, "main.wxs"), // command - "-out", windowsJoin(path, ""), + "candle", "heat.wxs", "main.wxs", // command "-ext", "WixUtilExtension", "-arch", "x64", ) @@ -90,6 +79,10 @@ func Candle(path string, native bool) error { cmd := exec.Command(args[0], args[1:]...) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if native { + cmd.Dir = path + } + if err := cmd.Run(); err != nil { return fmt.Errorf("candle failed: %w", err) } @@ -108,22 +101,26 @@ func Light(path string, native bool) error { args = append( args, "docker", "run", "--rm", "--platform", "linux/amd64", - "--volume", path+":"+path, // mount volume + "--volume", path+":/wix", // mount volume "fleetdm/wix:latest", // image name ) } args = append(args, - "light", windowsJoin(path, "heat.wixobj"), windowsJoin(path, "main.wixobj"), // command + "light", "heat.wixobj", "main.wixobj", // command "-ext", "WixUtilExtension", - "-b", windowsJoin(path, "root"), // Set directory for finding heat files - "-out", windowsJoin(path, "orbit.msi"), + "-b", "root", // Set directory for finding heat files + "-out", "orbit.msi", "-sval", // skip validation (otherwise Wine crashes) ) cmd := exec.Command(args[0], args[1:]...) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if native { + cmd.Dir = path + } + if err := cmd.Run(); err != nil { return fmt.Errorf("light failed: %w", err) } diff --git a/orbit/pkg/packaging/wix/wix_test.go b/orbit/pkg/packaging/wix/wix_test.go deleted file mode 100644 index 2fd7fa69b5..0000000000 --- a/orbit/pkg/packaging/wix/wix_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package wix - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestWindowsJoin(t *testing.T) { - cases := []struct { - in []string - out string - }{ - {[]string{"one\\two", "three"}, "one\\two\\three"}, - {[]string{"one/two/three", "four.txt"}, "one\\two\\three\\four.txt"}, - {[]string{"one", "two", "three"}, "one\\two\\three"}, - {[]string{"one/two/three", "four/five.txt"}, "one\\two\\three\\four\\five.txt"}, - } - - for _, c := range cases { - require.Equal(t, c.out, windowsJoin(c.in...)) - } -}