Compare commits
No commits in common. "38cd309b4026913f8ef1be33bbd5f914773a44a5" and "31d41060d0085ffaa56455eb1b4e74d3fed8bbba" have entirely different histories.
38cd309b40
...
31d41060d0
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
*.so
|
||||
*.bnp
|
||||
220
Makefile
220
Makefile
@ -1,59 +1,191 @@
|
||||
# gotham — build & publish helpers (wasm .bnp workflow)
|
||||
# Gotham — build & deploy helpers (.so plugin workflow)
|
||||
#
|
||||
# The theme compiles to a wasip1 reactor-mode wasm module packed into a .bnp
|
||||
# artifact (`ninja plugin build`). The legacy .so path is retired (WO-WZ-015):
|
||||
# the CMS is wasm-native and can no longer load .so plugins. Distribution is
|
||||
# publish-to-registry -> InstallFromRegistry (hot-load, no restart).
|
||||
# The plugin compiles to a .so shared object loaded by the CMS at runtime.
|
||||
# `make rebuild` copies source to the container, builds the .so, and restarts.
|
||||
#
|
||||
# Usage:
|
||||
# make build # compile wasm + pack gotham-<version>.bnp
|
||||
# make verify # validate the built .bnp (layout/abi/name/size)
|
||||
# make archive-check # prove a clean `git archive HEAD` compiles to wasm
|
||||
# make publish # ninja plugin publish --bnp (to the active registry)
|
||||
# make templ # regenerate templ Go files
|
||||
# make clean # remove build artefacts
|
||||
# make rebuild # Full rebuild: frontend + .so + CSS + migrations, restart
|
||||
# make backend # Build .so + migrations, restart
|
||||
# make build-css # Rebuild Tailwind CSS
|
||||
# make logs # Tail instance logs
|
||||
# make status # Show instance container status
|
||||
|
||||
.PHONY: build verify archive-check publish templ clean help
|
||||
.PHONY: rebuild backend build-frontend build-base-binary build-so copy-plugin-source sync-migrations build-css deploy-css logs status help spinup templ bump-patch bump-minor bump-major sync-version
|
||||
|
||||
PLUGIN_NAME := gotham
|
||||
NINJA := ninja
|
||||
BNP := $(PLUGIN_NAME)-$(shell grep '^version' plugin.mod | sed 's/.*"\(.*\)"/\1/').bnp
|
||||
# Paths
|
||||
BLOCKNINJA_DIR := $(HOME)/src/blockninja
|
||||
PLUGIN_SRC := $(CURDIR)
|
||||
PLUGIN_NAME := gotham
|
||||
MIGRATIONS_SRC := $(BLOCKNINJA_DIR)/backend/sql/migrations
|
||||
GO_BUILDER := localhost/blockninja-go-builder:latest
|
||||
CONTAINER := instance-gotham
|
||||
ACCOUNT_SLUG := blockninja
|
||||
INSTANCE_SLUG := gotham
|
||||
STYLES_DIR := /var/lib/blockninja/$(ACCOUNT_SLUG)/$(INSTANCE_SLUG)/styles
|
||||
PLUGIN_DEST := /app/data/plugins/src/$(PLUGIN_NAME)
|
||||
|
||||
# Compile to wasm and pack the .bnp (GOOS=wasip1 GOARCH=wasm, DESCRIBE probe,
|
||||
# tar.zst of plugin.wasm + plugin.mod + manifest.pb + schemas/ + assets/).
|
||||
build:
|
||||
$(NINJA) plugin build --dir .
|
||||
# Default target: build the .so locally for development.
|
||||
all: $(PLUGIN_NAME).so
|
||||
|
||||
# Validate the built .bnp exactly as the registry/loader will.
|
||||
verify:
|
||||
$(NINJA) plugin verify $(BNP)
|
||||
# Local plugin build (no container). Useful for CI / quick checks.
|
||||
$(PLUGIN_NAME).so: $(wildcard *.go) plugin.mod go.mod
|
||||
CGO_ENABLED=1 go build -buildmode=plugin -ldflags="-s -w" -o $(PLUGIN_NAME).so .
|
||||
|
||||
# Prove a clean `git archive HEAD` (what publish ships) compiles to wasm.
|
||||
archive-check:
|
||||
@T=$$(mktemp -d /tmp/archive-check-$(PLUGIN_NAME).XXXXXX) && \
|
||||
trap 'rm -rf "$$T"' EXIT && \
|
||||
git archive HEAD | tar -x -C "$$T" && \
|
||||
cd "$$T" && GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o "$$T/check.wasm" . && \
|
||||
echo "archive-check OK"
|
||||
# Ensure blockninja core services and the instance container are running.
|
||||
spinup:
|
||||
$(MAKE) -C $(BLOCKNINJA_DIR) spinup
|
||||
|
||||
# Publish the prebuilt .bnp to the active registry.
|
||||
# Pass --host https://my.localdev.blockninjacms.com for the dev orchestrator.
|
||||
publish: build
|
||||
$(NINJA) plugin publish --bnp $(BNP)
|
||||
# Full rebuild: frontend + .so plugin + CSS + migrations, restart.
|
||||
rebuild: spinup
|
||||
$(MAKE) build-frontend
|
||||
$(MAKE) build-base-binary
|
||||
$(MAKE) copy-plugin-source
|
||||
$(MAKE) build-so
|
||||
$(MAKE) build-css
|
||||
$(MAKE) sync-migrations
|
||||
podman restart $(CONTAINER)
|
||||
@sleep 2
|
||||
$(MAKE) deploy-css
|
||||
@echo ""
|
||||
@echo "Done. https://$(INSTANCE_SLUG).localdev.blockninjacms.com/"
|
||||
|
||||
# Regenerate templ Go files locally.
|
||||
# Backend-only rebuild: .so plugin + migrations, restart.
|
||||
backend: spinup
|
||||
$(MAKE) build-base-binary
|
||||
$(MAKE) copy-plugin-source
|
||||
$(MAKE) build-so
|
||||
$(MAKE) sync-migrations
|
||||
podman restart $(CONTAINER)
|
||||
@echo "Backend updated."
|
||||
|
||||
# Build host admin UI and deploy to container.
|
||||
build-frontend:
|
||||
@echo "==> Building @block-ninja/ui ..."
|
||||
cd $(BLOCKNINJA_DIR)/packages/ui && pnpm run build
|
||||
@echo "==> Building host admin UI ..."
|
||||
cd $(BLOCKNINJA_DIR)/web && pnpm run build
|
||||
@echo "==> Deploying frontend to container ..."
|
||||
podman exec $(CONTAINER) rm -rf /app/web/dist
|
||||
podman cp $(BLOCKNINJA_DIR)/web/dist $(CONTAINER):/app/web/dist
|
||||
@echo "Frontend deployed."
|
||||
|
||||
# Build the base CMS binary (without external plugins) and copy to container.
|
||||
build-base-binary:
|
||||
@echo "==> Building base CMS binary ..."
|
||||
podman run --rm \
|
||||
-v $(BLOCKNINJA_DIR)/backend:/src/backend:ro \
|
||||
-v blockninja_go_cache:/go/pkg/mod \
|
||||
-v /tmp:/out \
|
||||
-w /src/backend \
|
||||
$(GO_BUILDER) \
|
||||
go build -o /out/blockninja-server ./cmd/server
|
||||
podman cp /tmp/blockninja-server $(CONTAINER):/app/server
|
||||
rm -f /tmp/blockninja-server
|
||||
|
||||
# Copy plugin source into the container's plugin source directory.
|
||||
copy-plugin-source:
|
||||
@echo "==> Copying $(PLUGIN_NAME) source to container ..."
|
||||
podman exec $(CONTAINER) rm -rf $(PLUGIN_DEST)
|
||||
podman exec $(CONTAINER) mkdir -p $(PLUGIN_DEST)
|
||||
podman cp $(PLUGIN_SRC)/. $(CONTAINER):$(PLUGIN_DEST)/
|
||||
podman exec $(CONTAINER) rm -rf $(PLUGIN_DEST)/.git $(PLUGIN_DEST)/Makefile
|
||||
@echo "Plugin source copied."
|
||||
|
||||
# Build the .so using the go-builder container (same toolchain as CMS binary).
|
||||
# Both builds resolve block/core from the shared module cache — no local replace.
|
||||
build-so:
|
||||
@echo "==> Building $(PLUGIN_NAME).so ..."
|
||||
podman run --rm \
|
||||
-v $(PLUGIN_SRC):/src/plugin:ro \
|
||||
-v blockninja_go_cache:/go/pkg/mod \
|
||||
-v /tmp:/out \
|
||||
-w /src/plugin \
|
||||
-e CGO_ENABLED=1 \
|
||||
$(GO_BUILDER) \
|
||||
go build -buildmode=plugin -ldflags="-s -w" -o /out/$(PLUGIN_NAME).so .
|
||||
podman exec $(CONTAINER) mkdir -p /app/data/plugins/so
|
||||
podman cp /tmp/$(PLUGIN_NAME).so $(CONTAINER):/app/data/plugins/so/$(PLUGIN_NAME).so
|
||||
rm -f /tmp/$(PLUGIN_NAME).so
|
||||
@echo "$(PLUGIN_NAME).so built."
|
||||
|
||||
# Sync base blockninja migration files from host to container.
|
||||
sync-migrations:
|
||||
@echo "==> Syncing migrations ..."
|
||||
@podman unshare bash -c ' \
|
||||
M=$$(podman mount $(CONTAINER)) && \
|
||||
rm -rf "$$M/app/migrations" && \
|
||||
mkdir -p "$$M/app/migrations" && \
|
||||
podman umount $(CONTAINER)'
|
||||
@podman cp $(MIGRATIONS_SRC)/. $(CONTAINER):/app/migrations/
|
||||
@echo "Migrations synced."
|
||||
|
||||
# Rebuild Tailwind CSS.
|
||||
build-css:
|
||||
@echo "==> Building CSS ..."
|
||||
cd $(BLOCKNINJA_DIR) && make css
|
||||
|
||||
# Copy built CSS to instance styles dir and container.
|
||||
deploy-css:
|
||||
@mkdir -p $(STYLES_DIR)
|
||||
cp $(BLOCKNINJA_DIR)/data/styles/styles.css $(STYLES_DIR)/styles.css
|
||||
podman cp $(BLOCKNINJA_DIR)/data/styles/styles.css $(CONTAINER):/app/data/styles/styles.css
|
||||
podman cp $(BLOCKNINJA_DIR)/styles/input.base.css $(CONTAINER):/app/styles/input.base.css
|
||||
@echo "CSS deployed."
|
||||
|
||||
# Regenerate templ Go files locally (for development).
|
||||
templ:
|
||||
templ generate
|
||||
cd $(PLUGIN_SRC) && templ generate
|
||||
|
||||
# Remove build artefacts.
|
||||
clean:
|
||||
rm -f $(PLUGIN_NAME)-*.bnp $(PLUGIN_NAME).so plugin.wasm
|
||||
# Tail instance logs.
|
||||
logs:
|
||||
podman logs -f $(CONTAINER)
|
||||
|
||||
# Show instance container status.
|
||||
status:
|
||||
@podman inspect $(CONTAINER) --format \
|
||||
'Name: {{.Name}}\nImage: {{.Config.Image}}\nStatus: {{.State.Status}}\nHealth: {{.State.Health.Status}}\nStarted: {{.State.StartedAt}}' \
|
||||
2>/dev/null || echo "Container $(CONTAINER) not found."
|
||||
|
||||
help:
|
||||
@echo "Targets:"
|
||||
@echo " build Compile wasm + pack the .bnp"
|
||||
@echo " verify Validate the built .bnp (loader-identical checks)"
|
||||
@echo " archive-check Prove a clean git archive HEAD compiles to wasm"
|
||||
@echo " publish Publish the .bnp to the active registry"
|
||||
@echo " templ Regenerate templ Go files"
|
||||
@echo " clean Remove build artefacts"
|
||||
@echo " all Build $(PLUGIN_NAME).so locally (default)"
|
||||
@echo " spinup Start blockninja core services + instance container if stopped"
|
||||
@echo " rebuild Full rebuild: frontend + .so + CSS + migrations, restart"
|
||||
@echo " backend Build .so + migrations, restart"
|
||||
@echo " build-frontend Build host admin UI, deploy to container"
|
||||
@echo " build-base-binary Build base CMS binary, copy to container"
|
||||
@echo " copy-plugin-source Copy plugin source into container"
|
||||
@echo " build-so Build .so inside container"
|
||||
@echo " sync-migrations Copy migration files from host to container"
|
||||
@echo " build-css Rebuild Tailwind CSS"
|
||||
@echo " deploy-css Copy CSS to instance styles dir"
|
||||
@echo " templ Regenerate templ Go files locally"
|
||||
@echo " logs Tail instance container logs"
|
||||
@echo " status Show instance container status"
|
||||
|
||||
# --- Version bump targets ---
|
||||
CURRENT_VERSION := $(shell grep '^version' plugin.mod | sed 's/.*"\(.*\)"/\1/')
|
||||
|
||||
bump-patch:
|
||||
@NEW=$$(echo $(CURRENT_VERSION) | awk -F. '{printf "%d.%d.%d", $$1, $$2, $$3+1}'); \
|
||||
sed -i 's/version = "$(CURRENT_VERSION)"/version = "'$$NEW'"/' plugin.mod; \
|
||||
git add plugin.mod && git commit -m "chore: bump version to $$NEW" && git tag "v$$NEW"; \
|
||||
echo "Bumped to $$NEW and tagged v$$NEW"
|
||||
|
||||
bump-minor:
|
||||
@NEW=$$(echo $(CURRENT_VERSION) | awk -F. '{printf "%d.%d.0", $$1, $$2+1}'); \
|
||||
sed -i 's/version = "$(CURRENT_VERSION)"/version = "'$$NEW'"/' plugin.mod; \
|
||||
git add plugin.mod && git commit -m "chore: bump version to $$NEW" && git tag "v$$NEW"; \
|
||||
echo "Bumped to $$NEW and tagged v$$NEW"
|
||||
|
||||
bump-major:
|
||||
@NEW=$$(echo $(CURRENT_VERSION) | awk -F. '{printf "%d.0.0", $$1+1}'); \
|
||||
sed -i 's/version = "$(CURRENT_VERSION)"/version = "'$$NEW'"/' plugin.mod; \
|
||||
git add plugin.mod && git commit -m "chore: bump version to $$NEW" && git tag "v$$NEW"; \
|
||||
echo "Bumped to $$NEW and tagged v$$NEW"
|
||||
|
||||
sync-version:
|
||||
@TAG=$$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//'); \
|
||||
if [ -z "$$TAG" ]; then echo "No tags found"; exit 1; fi; \
|
||||
sed -i 's/version = "$(CURRENT_VERSION)"/version = "'$$TAG'"/' plugin.mod; \
|
||||
echo "Synced plugin.mod to $$TAG"
|
||||
|
||||
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module git.dev.alexdunmow.com/block/themes/gotham
|
||||
go 1.26.4
|
||||
|
||||
require (
|
||||
git.dev.alexdunmow.com/block/core v0.15.2
|
||||
git.dev.alexdunmow.com/block/core v0.14.1
|
||||
github.com/a-h/templ v0.3.1020
|
||||
)
|
||||
|
||||
|
||||
10
go.sum
10
go.sum
@ -1,7 +1,9 @@
|
||||
connectrpc.com/connect v1.20.0 h1:6TNDAB+WeNd2uolWNlYczB5E0KNNaVMNUEx8JEUsPmQ=
|
||||
connectrpc.com/connect v1.20.0/go.mod h1:A2ygJrukXwWy32vkCAAHNVguZrqZ+jeZ9rGRnGR4dN4=
|
||||
git.dev.alexdunmow.com/block/core v0.15.2 h1:qTjJxa1pClxwehkdTxXiJDpHQLr5DoXBUCa40QRO0L8=
|
||||
git.dev.alexdunmow.com/block/core v0.15.2/go.mod h1:A+mgA9oeWoPhXruv4Mjpywwl2A9B5I3cKzlJjalBdlE=
|
||||
git.dev.alexdunmow.com/block/core v0.14.0 h1:cO6QQQPndhxwh1zbDvDOzebwrFS8Ka3WsxD8JBJLw/Y=
|
||||
git.dev.alexdunmow.com/block/core v0.14.0/go.mod h1:S0ZfpGZ9BQhhmuTUd78ailH7m2vo7QRCTIionvCVm9s=
|
||||
git.dev.alexdunmow.com/block/core v0.14.1 h1:63b25yzWoqrhBd3wdDFhsJzyGNM99wYmdh4WkN35hDk=
|
||||
git.dev.alexdunmow.com/block/core v0.14.1/go.mod h1:S0ZfpGZ9BQhhmuTUd78ailH7m2vo7QRCTIionvCVm9s=
|
||||
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw=
|
||||
@ -28,14 +30,10 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tetratelabs/wazero v1.12.0 h1:DuWcpNu/FzgEXgGBDp8J1Spc+CWOvvtvVyjKlaZopYU=
|
||||
github.com/tetratelabs/wazero v1.12.0/go.mod h1:LvKtzl2RqO4gyF27BiXU+nKAjcV8f38U+kP/q2vgxh0=
|
||||
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
||||
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
|
||||
17
main.go
17
main.go
@ -1,17 +0,0 @@
|
||||
//go:build wasip1
|
||||
|
||||
// Package main compiles the gotham theme to a wasip1 reactor-mode wasm guest
|
||||
// (WO-WZ-015). The .so build path is retired; `ninja plugin build` produces the
|
||||
// .bnp artifact the registry serves.
|
||||
//
|
||||
// Reactor mode: the host runs `_initialize` once per pooled instance, which
|
||||
// runs this init func (hence wasmguest.Serve) before any bn_invoke. Serve is
|
||||
// non-blocking; all theme work then arrives over the ABI hook calls. main is
|
||||
// never called.
|
||||
package main
|
||||
|
||||
import "git.dev.alexdunmow.com/block/core/plugin/wasmguest"
|
||||
|
||||
func init() { wasmguest.Serve(Registration) }
|
||||
|
||||
func main() {} // never called — reactor mode
|
||||
@ -2,11 +2,11 @@
|
||||
name = "gotham"
|
||||
display_name = "Gotham"
|
||||
scope = "@themes"
|
||||
version = "0.1.4"
|
||||
version = "0.1.3"
|
||||
description = "Dark, high-contrast BlockNinja theme with bold typography and modern accent panels."
|
||||
kind = "theme"
|
||||
categories = ["templates"]
|
||||
tags = ["dark", "high-contrast", "agency", "blog", "professional", "modern", "serif"]
|
||||
|
||||
[compatibility]
|
||||
block_core = ">=0.15.0 <0.16.0"
|
||||
block_core = ">=0.11.0 <0.12.0"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user