all: use make to build
This overhauls the build system.
We used to use a just-in-time clever build system
so that 'go run' and 'go install' Just Worked.
This was really nice, except that it make it
all but impossible to ship a single binary.
It also required our uses to install npm,
which some folks have an understandably negative reaction to.
This migrates to a makefile for building.
The core typescript building logic is mostly still in Go,
and untouched (boy did I learn that lesson the hard way).
The output is a single file that includes the webui, innie, and outie.
(There are still very mild shenanigans in which we write outie
out to a temp file and then 'docker cp' it into the docker container.
But this is pretty manageable.)
There are some significant follow-ups left after this commit:
- convert the nightly release builds to use the makefile
- lots of dead code removal
- maybe add -race support using a dockerfile for the cgo compilation
- maybe use 'docker cp' stdin reading with tar to avoid the temp outtie file
- all the rest of the "better release" todos (brew install, etc.)
diff --git a/dockerimg/dockerimg.go b/dockerimg/dockerimg.go
index 7b9d549..77af08a 100644
--- a/dockerimg/dockerimg.go
+++ b/dockerimg/dockerimg.go
@@ -23,9 +23,9 @@
"golang.org/x/crypto/ssh"
"sketch.dev/browser"
+ "sketch.dev/embedded"
"sketch.dev/loop/server"
"sketch.dev/skribe"
- "sketch.dev/webui"
)
// ContainerConfig holds all configuration for launching a container
@@ -171,14 +171,6 @@
return err
}
- linuxSketchBin := config.SketchBinaryLinux
- if linuxSketchBin == "" {
- linuxSketchBin, err = buildLinuxSketchBin(ctx)
- if err != nil {
- return err
- }
- }
-
cntrName := "sketch-" + config.SessionID
defer func() {
if config.NoCleanup {
@@ -236,28 +228,12 @@
config.Upstream = upstream
config.Commit = commit
- // Create the sketch container
+ // Create the sketch container, copy over linux sketch
if err := createDockerContainer(ctx, cntrName, hostPort, relPath, imgName, config); err != nil {
return fmt.Errorf("failed to create docker container: %w", err)
}
-
- // Copy the sketch linux binary into the container
- if out, err := combinedOutput(ctx, "docker", "cp", linuxSketchBin, cntrName+":/bin/sketch"); err != nil {
- return fmt.Errorf("docker cp: %s, %w", out, err)
- }
-
- // Make sure that the webui is built so we can copy the results to the container.
- _, err = webui.Build()
- if err != nil {
- return fmt.Errorf("failed to build webui: %w", err)
- }
-
- webuiZipPath, err := webui.ZipPath()
- if err != nil {
- return err
- }
- if out, err := combinedOutput(ctx, "docker", "cp", webuiZipPath, cntrName+":/root/.cache/sketch/webui/"+filepath.Base(webuiZipPath)); err != nil {
- return fmt.Errorf("docker cp: %s, %w", out, err)
+ if err := copyEmbeddedLinuxBinaryToContainer(ctx, cntrName); err != nil {
+ return fmt.Errorf("failed to copy linux binary to container: %w", err)
}
fmt.Printf("📦 running in container %s\n", cntrName)
@@ -1182,6 +1158,40 @@
return strings.TrimSpace(string(out)), nil
}
+// copyEmbeddedLinuxBinaryToContainer copies the embedded linux binary to the container
+func copyEmbeddedLinuxBinaryToContainer(ctx context.Context, containerName string) error {
+ bin := embedded.LinuxBinary()
+ if bin == nil {
+ return fmt.Errorf("nil embedded linux binary reader, did you build using `make`?")
+ }
+
+ cacheDir := filepath.Join(os.TempDir(), "sketch-binary-cache")
+ if err := os.MkdirAll(cacheDir, 0o700); err != nil {
+ return fmt.Errorf("failed to create cache directory: %w", err)
+ }
+
+ hash := sha256.Sum256(bin)
+ binaryPath := filepath.Join(cacheDir, hex.EncodeToString(hash[:]))
+ _, statErr := os.Stat(binaryPath)
+ switch {
+ case os.IsNotExist(statErr):
+ if err := os.WriteFile(binaryPath, bin, 0o700); err != nil {
+ return fmt.Errorf("failed to write binary to cache: %w", err)
+ }
+ case statErr != nil:
+ return fmt.Errorf("failed to check if cached binary exists: %w", statErr)
+ }
+ // TODO: clean up old sketch binaries from the cache dir:
+ // maybe set a max of 5, and then delete oldest after that by atime/mtime/ctime
+
+ if out, err := combinedOutput(ctx, "docker", "cp", binaryPath, containerName+":/bin/sketch"); err != nil {
+ return fmt.Errorf("docker cp failed: %s: %w", out, err)
+ }
+
+ slog.DebugContext(ctx, "copied embedded linux binary to container", "container", containerName)
+ return nil
+}
+
const seccompProfile = `{
"defaultAction": "SCMP_ACT_ALLOW",
"syscalls": [