# Pastel Dream — build & deploy helpers (.so plugin workflow) # # 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 # Local single-shot build (CGO go build -buildmode=plugin) # make rebuild # Full rebuild against a running CMS instance # make backend # .so + migrations only, restart # make build-css # Rebuild Tailwind CSS # make logs # Tail instance logs # make status # Show instance container status # make templ # Regenerate *_templ.go files locally .PHONY: all clean 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 # Paths BLOCKNINJA_DIR := $(HOME)/src/blockninja PLUGIN_SRC := $(CURDIR) PLUGIN_NAME := pastel-dream MIGRATIONS_SRC := $(BLOCKNINJA_DIR)/cms/backend/sql/migrations GO_BUILDER := localhost/blockninja-go-builder:latest CONTAINER := instance-pastel-dream ACCOUNT_SLUG := blockninja INSTANCE_SLUG := pastel-dream STYLES_DIR := /var/lib/blockninja/$(ACCOUNT_SLUG)/$(INSTANCE_SLUG)/styles PLUGIN_DEST := /app/data/plugins/src/$(PLUGIN_NAME) # Default target: build the .so locally for development. all: $(PLUGIN_NAME).so # 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 . # Remove the compiled .so. clean: rm -f $(PLUGIN_NAME).so # Regenerate templ Go files locally (for development). templ: cd $(PLUGIN_SRC) && $(HOME)/go/bin/templ generate # Ensure blockninja core services and the instance container are running. spinup: $(MAKE) -C $(BLOCKNINJA_DIR) spinup # 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/" # 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)/cms/packages/ui && pnpm run build @echo "==> Building host admin UI ..." cd $(BLOCKNINJA_DIR)/cms/web && pnpm run build @echo "==> Deploying frontend to container ..." podman exec $(CONTAINER) rm -rf /app/web/dist podman cp $(BLOCKNINJA_DIR)/cms/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)/cms/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). 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)/cms && make css # Copy built CSS to instance styles dir and container. deploy-css: @mkdir -p $(STYLES_DIR) cp $(BLOCKNINJA_DIR)/cms/data/styles/styles.css $(STYLES_DIR)/styles.css podman cp $(BLOCKNINJA_DIR)/cms/data/styles/styles.css $(CONTAINER):/app/data/styles/styles.css podman cp $(BLOCKNINJA_DIR)/cms/styles/input.base.css $(CONTAINER):/app/styles/input.base.css @echo "CSS deployed." # 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 " all Build $(PLUGIN_NAME).so locally (default)" @echo " clean Remove the compiled $(PLUGIN_NAME).so" @echo " templ Regenerate templ Go files locally" @echo " spinup Start blockninja core services + instance container" @echo " rebuild Full rebuild: frontend + .so + CSS + migrations, restart" @echo " backend .so + migrations only, restart" @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"