about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAlan Pearce2024-04-21 13:49:30 +0200
committerAlan Pearce2024-04-21 13:49:30 +0200
commitc258ad4dfcd394c212073d6bd809de9754c30955 (patch)
tree6b9750c76aa5c0edf164b8fdec0a8838de15af67
parent9ece57315f2cfee0b2fb64d1fd9fb05fb7fb6301 (diff)
downloadwebsite-c258ad4dfcd394c212073d6bd809de9754c30955.tar.lz
website-c258ad4dfcd394c212073d6bd809de9754c30955.tar.zst
website-c258ad4dfcd394c212073d6bd809de9754c30955.zip
serve site from filesystem rather than embedding
It's cool to embed, but it requires server.go to be at the root. Also,
I'd like to be able to update the built site separately in the future.
-rw-r--r--cmd/build/build.go29
-rw-r--r--nix/default.nix48
-rw-r--r--server.go9
3 files changed, 53 insertions, 33 deletions
diff --git a/cmd/build/build.go b/cmd/build/build.go
index 058b82f..ea611aa 100644
--- a/cmd/build/build.go
+++ b/cmd/build/build.go
@@ -25,6 +25,7 @@ import (
 	"github.com/adrg/frontmatter"
 	"github.com/antchfx/xmlquery"
 	"github.com/antchfx/xpath"
+	"github.com/ardanlabs/conf/v3"
 	mapset "github.com/deckarep/golang-set/v2"
 	cp "github.com/otiai10/copy"
 	"github.com/pkg/errors"
@@ -519,29 +520,39 @@ func build(outDir string) error {
 	return nil
 }
 
+type IOConfig struct {
+	Source      string `conf:"default:.,short:s"`
+	Destination string `conf:"default:public,short:d"`
+}
+
 func main() {
 	if os.Getenv("DEBUG") != "" {
 		slog.SetLogLoggerLevel(slog.LevelDebug)
 	}
 	slog.Debug("starting build process")
-	_, err := os.Getwd()
-	if err != nil {
-		log.Panic(errors.Errorf("working directory does not exist: %v", err))
-	}
 
-	outDir := "public"
-	err = os.RemoveAll("public")
+	ioConfig := IOConfig{}
+	conf.Parse("", &ioConfig)
+
+	if ioConfig.Source != "." {
+		err := os.Chdir(ioConfig.Source)
+		if err != nil {
+			log.Panic("could not change to source directory")
+		}
+	}
+	err := os.RemoveAll(ioConfig.Destination)
 	if err != nil {
 		log.Panic(errors.Errorf("could not remove public directory: %v", err))
 	}
-	err = cp.Copy("static", outDir, cp.Options{
-		PreserveTimes: true,
+	err = cp.Copy(path.Join(ioConfig.Source, "static"), ioConfig.Destination, cp.Options{
+		PreserveTimes:     true,
+		PermissionControl: cp.AddPermission(0755),
 	})
 	if err != nil {
 		log.Panic(errors.Errorf("could not copy static files: %v", err))
 	}
 
-	if err := build(outDir); err != nil {
+	if err := build(ioConfig.Destination); err != nil {
 		switch cause := errors.Cause(err).(type) {
 		case *fs.PathError:
 			slog.Info("pathError")
diff --git a/nix/default.nix b/nix/default.nix
index 612e3e0..4299676 100644
--- a/nix/default.nix
+++ b/nix/default.nix
@@ -2,7 +2,7 @@
 let
   version = self.shortRev or self.dirtyShortRev or "unstable-${self.lastModified}";
   dockerTag = self.rev or self.dirtyRev or "unstable-${self.lastModified}";
-  mkDocker = type: server:
+  mkDocker = type: { server, public }:
     let
       PORT = 3000;
     in
@@ -11,6 +11,7 @@ let
       tag = dockerTag;
       contents = [
         (pkgs.writeTextDir "config.toml" (builtins.readFile ./../config.toml))
+        public
       ];
       config = {
         Cmd = [ "${server}/bin/website" ];
@@ -18,7 +19,6 @@ let
           "PRODUCTION=true"
           "LISTEN_ADDRESS=::"
           "PORT=${builtins.toString PORT}"
-          "ROOT=public"
         ];
         ExposedPorts = {
           "${builtins.toString PORT}/tcp" = { };
@@ -28,7 +28,7 @@ let
   mkDockerStream = mkDocker "streamLayeredImage";
   mkDockerImage = mkDocker "buildLayeredImage";
 in
-with pkgs; rec{
+with pkgs; rec {
   default = server;
   builder = buildGoApplication {
     pname = "website-builder";
@@ -46,6 +46,20 @@ with pkgs; rec{
     modules = ./gomod2nix.toml;
     subPackages = [ "cmd/build" ];
   };
+  public = runCommandLocal "build"
+    {
+      src = with lib.fileset; toSource {
+        root = ./..;
+        fileset = unions [
+          ./../config.toml
+          ./../content
+          ./../static
+          ./../templates
+        ];
+      };
+    } ''
+    ${builder}/bin/build -s $src -d $out/public
+  '';
   server = buildGoApplication {
     pname = "website";
     inherit version;
@@ -57,23 +71,23 @@ with pkgs; rec{
         ./../go.sum
         ./../server.go
         ./../internal
-        ./../config.toml
-        ./../content
-        ./../static
-        ./../templates
       ];
     };
-    nativeBuildInputs = [ builder ];
-    prePatch = ''
-      ${builder}/bin/build
-    '';
     modules = ./gomod2nix.toml;
     ldflags = [ "-s" "-w" "-X" "main.Commit=${version}" ];
   };
-  docker-stream = mkDockerStream server;
-  docker-stream-aarch64-linux = mkDockerStream (self.packages.aarch64-linux.server);
-  docker-stream-x86_64-linux = mkDockerStream (self.packages.x86_64-linux.server);
-  docker-image = mkDockerImage server;
-  docker-image-aarch64-linux = mkDockerImage (self.packages.aarch64-linux.server);
-  docker-image-x86_64-linux = mkDockerImage (self.packages.x86_64-linux.server);
+  docker-stream = mkDockerStream { inherit server public; };
+  docker-stream-aarch64-linux = mkDockerStream {
+    inherit public; server = (self.packages.aarch64-linux.server);
+  };
+  docker-stream-x86_64-linux = mkDockerStream {
+    inherit public; server = (self.packages.x86_64-linux.server);
+  };
+  docker-image = mkDockerImage { inherit server public; };
+  docker-image-aarch64-linux = mkDockerImage {
+    inherit public; server = (self.packages.aarch64-linux.server);
+  };
+  docker-image-x86_64-linux = mkDockerImage {
+    inherit public; server = (self.packages.x86_64-linux.server);
+  };
 }
diff --git a/server.go b/server.go
index 0835d68..935cc1e 100644
--- a/server.go
+++ b/server.go
@@ -1,7 +1,6 @@
 package main
 
 import (
-	"embed"
 	"errors"
 	"fmt"
 	"io"
@@ -45,9 +44,6 @@ type Host struct {
 	Fiber *fiber.App
 }
 
-//go:embed all:public/*
-var fs embed.FS
-
 var Commit string
 
 func main() {
@@ -130,10 +126,10 @@ func main() {
 
 	website.Use(recover.New(recover.Config{}))
 
-	files := http.FS(fs)
+	files := http.Dir("public")
 	notFoundHandler := func(c *fiber.Ctx) error {
 		c.Status(fiber.StatusNotFound).Type("html", "utf-8")
-		content, err := files.Open("public/404.html")
+		content, err := files.Open("404.html")
 		if err != nil {
 			c.Type("txt")
 			return c.SendString("404 Not Found")
@@ -143,7 +139,6 @@ func main() {
 	website.Get("/404.html", notFoundHandler)
 	website.Use("/", filesystem.New(filesystem.Config{
 		Root:               files,
-		PathPrefix:         "public",
 		ContentTypeCharset: "utf-8",
 		MaxAge:             int((24 * time.Hour).Seconds()),
 	}))