diff --git a/.dockerignore b/.dockerignore index f92b950..40ae805 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,6 @@ .env /docker-compose.* -/result +/result* /.direnv/ /build/ diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7152848..c65e1d9 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -28,13 +28,20 @@ jobs: authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - name: Build - run: nix develop --command trevstack-build + run: >- + nix build + .#trevstack-linux-amd64 + .#trevstack-linux-arm64 + .#trevstack-linux-arm + .#trevstack-windows-amd64 + .#trevstack-darwin-amd64 + .#trevstack-darwin-arm64 - name: Create Release uses: softprops/action-gh-release@v2 with: files: |- - build/** + result*/bin/* # https://docs.docker.com/build/ci/github-actions/manage-tags-labels/ package: diff --git a/.gitignore b/.gitignore index 025065e..798fe10 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .env /docker-compose.* -/result +/result* /.direnv/ /build/ \ No newline at end of file diff --git a/.scripts/build.sh b/.scripts/build.sh deleted file mode 100755 index b14b4e6..0000000 --- a/.scripts/build.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -git_root=$(git rev-parse --show-toplevel) -url=$(git config --get remote.origin.url) -name=$(basename -s .git "${url}") -git_version=$(git describe --tags --abbrev=0) -version=${git_version#v} - -echo "building client" -cd "${git_root}" -nix build .#trevstack-client -cp -a result/. server/client -chmod -R u+w server/client - -echo "building server" -cd "${git_root}/server" -echo "Building ${name}-windows-amd64-${version}.exe" -GOOS=windows GOARCH=amd64 go build -o "./build/${name}-windows-amd64-${version}.exe" . -echo "Building ${name}-linux-amd64-${version}" -GOOS=linux GOARCH=amd64 go build -o "./build/${name}-linux-amd64-${version}" . -echo "Building ${name}-linux-amd64-${version}" -GOOS=linux GOARCH=arm64 go build -o "./build/${name}-linux-arm64-${version}" . -echo "Building ${name}-linux-arm-${version}" -GOOS=linux GOARCH=arm go build -o "./build/${name}-linux-arm-${version}" . \ No newline at end of file diff --git a/flake.nix b/flake.nix index 699f617..bf5e0d3 100644 --- a/flake.nix +++ b/flake.nix @@ -23,14 +23,40 @@ pname = "trevstack"; version = "0.0.18"; - supportedSystems = [ + build-systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + host-systems = [ + { + GOOS = "linux"; + GOARCH = "amd64"; + } + { + GOOS = "linux"; + GOARCH = "arm64"; + } + { + GOOS = "linux"; + GOARCH = "arm"; + } + { + GOOS = "windows"; + GOARCH = "amd64"; + } + { + GOOS = "darwin"; + GOARCH = "amd64"; + } + { + GOOS = "darwin"; + GOARCH = "arm64"; + } + ]; forSystem = f: - nixpkgs.lib.genAttrs supportedSystems ( + nixpkgs.lib.genAttrs build-systems ( system: f { inherit system; @@ -74,7 +100,6 @@ sha256 = "sha256-3XBQCc9H9N/AZm/8J5bJRgBhVtoZKFvbdTB+glHxYdA="; }; vendorHash = "sha256-CIiG/XhV8xxjYY0sZcSvIFcJ1Wh8LyDDwqem2cSSwBA="; - nativeCheckInputs = with pkgs; [less]; }) # Client @@ -148,29 +173,54 @@ formatter = forSystem ({pkgs, ...}: pkgs.alejandra); - packages = forSystem ({pkgs, ...}: rec { - trevstack-client = pkgs.buildNpmPackage { - pname = "${pname}-client"; - inherit version; - src = ./client; - npmDepsHash = "sha256-u7zkBgaxDEB2XFrNl0f7/HtW0Oy2B7FVPot9MLPzXGc="; - nodejs = pkgs.nodejs_22; + packages = forSystem ( + {pkgs, ...}: let + server = pkgs.buildGoModule { + inherit client pname version; + src = ./server; + vendorHash = "sha256-uXyCYODrBWNm7nbibm66oO90SYXRvrNtjF0K4ZI7IkM="; + env.CGO_ENABLED = 0; - installPhase = '' - cp -r build "$out" - chmod -R u+w "$out" - ''; - }; - trevstack = pkgs.buildGoModule { - inherit trevstack-client pname version; - src = ./server; - vendorHash = "sha256-uXyCYODrBWNm7nbibm66oO90SYXRvrNtjF0K4ZI7IkM="; + preBuild = '' + cp -r ${client} client + ''; + }; + client = pkgs.buildNpmPackage { + pname = "${pname}-client"; + inherit version; + src = ./client; + npmDepsHash = "sha256-u7zkBgaxDEB2XFrNl0f7/HtW0Oy2B7FVPot9MLPzXGc="; - preBuild = '' - cp -r ${trevstack-client} client - ''; - }; - default = trevstack; - }); + installPhase = '' + cp -r build "$out" + ''; + }; + in + { + default = server; + } + // builtins.listToAttrs (builtins.map (x: { + name = "${pname}-${x.GOOS}-${x.GOARCH}"; + value = server.overrideAttrs { + nativeBuildInputs = server.nativeBuildInputs ++ [ + pkgs.rename + ]; + env.CGO_ENABLED = 0; + env.GOOS = x.GOOS; + env.GOARCH = x.GOARCH; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + find $GOPATH/bin -type f -exec mv -t $out/bin {} + + rename 's/(.+\/)(.+?)(\.[^.]*$|$)/$1${pname}-${x.GOOS}-${x.GOARCH}-${version}$3/' $out/bin/* + + runHook postInstall + ''; + }; + }) + host-systems) + ); }; } diff --git a/server/main.go b/server/cmd/trevstack/main.go similarity index 94% rename from server/main.go rename to server/cmd/trevstack/main.go index 7df1e90..87e40d8 100644 --- a/server/main.go +++ b/server/cmd/trevstack/main.go @@ -3,7 +3,6 @@ package main import ( "context" - "embed" "errors" "fmt" "log" @@ -18,6 +17,7 @@ import ( "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" + embed "github.com/spotdemo4/trevstack/server" "github.com/spotdemo4/trevstack/server/internal/database" "github.com/spotdemo4/trevstack/server/internal/handlers/client" "github.com/spotdemo4/trevstack/server/internal/handlers/file" @@ -26,9 +26,6 @@ import ( "github.com/spotdemo4/trevstack/server/internal/interceptors" ) -var clientFS *embed.FS -var dbFS *embed.FS - func main() { logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{})) slog.SetDefault(logger) @@ -40,7 +37,7 @@ func main() { } // Migrate database - err = database.Migrate(env.DatabaseURL, dbFS) + err = database.Migrate(env.DatabaseURL, embed.DBFS) if err != nil { log.Fatal(err.Error()) } @@ -59,7 +56,7 @@ func main() { // Serve web interface mux := http.NewServeMux() - mux.Handle("/", client.NewClientHandler(env.Key, clientFS)) + mux.Handle("/", client.NewClientHandler(env.Key, embed.ClientFS)) mux.Handle("/file/", file.NewFileHandler(sqlc, env.Key)) mux.Handle("/grpc/", http.StripPrefix("/grpc", api)) diff --git a/server/embed.go b/server/embed.go new file mode 100644 index 0000000..cbc1916 --- /dev/null +++ b/server/embed.go @@ -0,0 +1,13 @@ +//go:build !dev + +package embed + +import ( + "embed" +) + +//go:embed all:client +var ClientFS embed.FS + +//go:embed db/migrations/*.sql +var DBFS embed.FS diff --git a/server/embed_dev.go b/server/embed_dev.go new file mode 100644 index 0000000..ce2ee20 --- /dev/null +++ b/server/embed_dev.go @@ -0,0 +1,10 @@ +//go:build dev + +package embed + +import ( + "embed" +) + +var ClientFS embed.FS +var DBFS embed.FS diff --git a/server/internal/database/migrate.go b/server/internal/database/migrate.go index 78ee37c..d1dfbb0 100644 --- a/server/internal/database/migrate.go +++ b/server/internal/database/migrate.go @@ -2,6 +2,7 @@ package database import ( "embed" + "io" "log" "net/url" @@ -9,8 +10,9 @@ import ( _ "github.com/spotdemo4/dbmate-sqlite-modernc/pkg/driver/sqlite" // Modernc sqlite ) -func Migrate(dsn string, dbFS *embed.FS) error { - if dbFS == nil { +func Migrate(dsn string, dbFS embed.FS) error { + _, err := dbFS.ReadDir(".") + if err == io.EOF { return nil } @@ -22,6 +24,7 @@ func Migrate(dsn string, dbFS *embed.FS) error { db := dbmate.New(dburl) db.Driver() db.FS = dbFS + db.AutoDumpSchema = false log.Println("Migrations:") migrations, err := db.FindMigrations() diff --git a/server/internal/handlers/client/client.go b/server/internal/handlers/client/client.go index 238fa18..9d75c0b 100644 --- a/server/internal/handlers/client/client.go +++ b/server/internal/handlers/client/client.go @@ -2,14 +2,16 @@ package client import ( "embed" + "io" "io/fs" "net/http" "github.com/spotdemo4/trevstack/server/internal/interceptors" ) -func NewClientHandler(key string, clientFS *embed.FS) http.Handler { - if clientFS == nil { +func NewClientHandler(key string, clientFS embed.FS) http.Handler { + _, err := clientFS.ReadDir(".") + if err == io.EOF { return http.NotFoundHandler() } diff --git a/server/prod.go b/server/prod.go deleted file mode 100644 index a54d8cf..0000000 --- a/server/prod.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build !dev - -package main - -import ( - "embed" - "log" -) - -//go:embed all:client -var cFS embed.FS - -//go:embed db/migrations/*.sql -var dFS embed.FS - -func init() { - log.Println("initializing for production") - clientFS = &cFS - dbFS = &dFS -}