CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Test (windows-latest) (push) Canceled after 0s
CI / Storage tests on PostgreSQL (push) Canceled after 0s
CI / Complement (federation off) (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
CI / Smoke test the binary (push) Canceled after 0s
CI / Admin panel (push) Canceled after 0s
CI / Web client (push) Canceled after 0s
CI / Desktop client (ubuntu-24.04) (push) Canceled after 0s
CI / Desktop client (windows-latest) (push) Canceled after 0s
Web client (also what the desktop app runs): - Simplified Sliding Sync (MSC4186) when the homeserver advertises org.matrix.simplified_msc3575. src/matrix/sliding.ts answers the SDK's GET /sync with a sliding sync request and rewrites the response into the /sync shape, as the Android app does; the SDK's own sliding sync mode doesn't sort thread replies into threads. 20 rooms first, then every room (up to 1000); to_device, e2ee, account data, receipts and typing extensions; M_UNKNOWN_POS starts a new connection. The SDK's /members?at=<sync token> drops the token, which here is ours. Settings can switch back to /sync. - Notifications for new messages and incoming calls while Warp isn't in front, by the account's push rules, evaluated after decryption. The browser's Notification API once turned on in Settings, or the desktop app's bridge (window.warpDesktop). One per room; a click opens it. - Voice messages: record from the composer, sent as m.audio with MSC3245's voice marker and MSC1767's duration and waveform (encrypted in encrypted rooms); a waveform player in the timeline. - @warp/ui: a slot for extra composer buttons; bell-off, play and pause icons. Desktop app: - System notifications through Wails' notifications service, fed by /_desktop/bridge.js (/_desktop/notify, JSON only); clicking one shows the window and opens the room. - Tray icon with Open and Quit; closing the window hides it (a one-time notification says so), File > Quit ends it. The page title goes to the window and the tray tooltip, the unread count to the taskbar or Dock badge. - Auto-update from a Wails update manifest at DESKTOP_UPDATE_URL: a quiet check a minute after start and every six hours, a notification when a newer version exists, Help > Check for updates opens the update window. Optional signature key (DESKTOP_UPDATE_KEY). Linux package installs leave updates to the package manager. build/manifest writes the manifest. - Per-user NSIS installer (make desktop-windows-installer), the macOS bundle zipped for the updater, a desktop CI job, and a Desktop release workflow that builds all three platforms and the manifest. Tested on Windows against a local homeserver: sliding sync with E2EE, threads and a server restart; notifications (toast history), close to tray, relaunch restoring the window; voice messages recorded, sent and played, encrypted too; the update check finding a newer version. Not tested: installing an update, the NSIS installer, CI, macOS and Linux. Code signing needs certificates and isn't done. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
329 lines
13 KiB
Makefile
329 lines
13 KiB
Makefile
# Warp — build, test and lint.
|
|
#
|
|
# Everything Go lives in ./server; the frontend packages (apps/*) get their
|
|
# own targets as they are created.
|
|
|
|
SHELL := /bin/sh
|
|
GO ?= go
|
|
BIN_DIR := bin
|
|
BINARY := warp
|
|
SERVER_DIR := server
|
|
|
|
COMPLEMENT_IMAGE ?= complement-warp
|
|
|
|
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo 0.0.0-dev)
|
|
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
|
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
PKG := github.com/dariuszjaniak/warp/server/internal/buildinfo
|
|
LDFLAGS := -X $(PKG).Version=$(VERSION) -X $(PKG).Commit=$(COMMIT) -X $(PKG).BuildDate=$(DATE)
|
|
|
|
# Windows builds need the .exe suffix for `make run` to work from MSYS.
|
|
ifeq ($(OS),Windows_NT)
|
|
EXE := .exe
|
|
else
|
|
EXE :=
|
|
endif
|
|
|
|
.DEFAULT_GOAL := build
|
|
|
|
.PHONY: help
|
|
help: ## List the targets
|
|
@grep -hE '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | \
|
|
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
|
|
|
|
.PHONY: build
|
|
build: ## Build the warp binary into bin/
|
|
cd $(SERVER_DIR) && $(GO) build -ldflags "$(LDFLAGS)" -o ../$(BIN_DIR)/$(BINARY)$(EXE) ./cmd/warp
|
|
|
|
.PHONY: run
|
|
run: build ## Build and run the server
|
|
./$(BIN_DIR)/$(BINARY)$(EXE) serve
|
|
|
|
.PHONY: test
|
|
test: ## Run the unit tests (sqlite only)
|
|
cd $(SERVER_DIR) && $(GO) test ./...
|
|
|
|
.PHONY: test-race
|
|
test-race: ## Run the tests with the race detector (needs cgo)
|
|
cd $(SERVER_DIR) && CGO_ENABLED=1 $(GO) test -race ./...
|
|
|
|
.PHONY: test-postgres
|
|
test-postgres: ## Run the storage tests against PostgreSQL too
|
|
@test -n "$(WARP_TEST_POSTGRES_DSN)" || \
|
|
{ echo "set WARP_TEST_POSTGRES_DSN, e.g. postgres://warp:warp@localhost/warp_test?sslmode=disable"; exit 1; }
|
|
cd $(SERVER_DIR) && WARP_TEST_POSTGRES_DSN="$(WARP_TEST_POSTGRES_DSN)" $(GO) test ./internal/storage/...
|
|
|
|
.PHONY: cover
|
|
cover: ## Run the tests and write coverage.out / coverage.html
|
|
cd $(SERVER_DIR) && $(GO) test -coverprofile=../coverage.out -covermode=count ./...
|
|
$(GO) tool cover -html=coverage.out -o coverage.html
|
|
@echo "wrote coverage.html"
|
|
|
|
.PHONY: fmt
|
|
fmt: ## Format the Go code
|
|
cd $(SERVER_DIR) && $(GO) fmt ./...
|
|
|
|
.PHONY: vet
|
|
vet: ## Run go vet
|
|
cd $(SERVER_DIR) && $(GO) vet ./...
|
|
|
|
.PHONY: lint
|
|
lint: ## Run golangci-lint
|
|
cd $(SERVER_DIR) && golangci-lint run
|
|
|
|
.PHONY: tidy
|
|
tidy: ## Tidy the Go module files
|
|
cd $(SERVER_DIR) && $(GO) mod tidy
|
|
|
|
.PHONY: check
|
|
check: vet test ## What CI runs on every push (minus the linter)
|
|
|
|
.PHONY: generate-keys
|
|
generate-keys: build ## Create the ed25519 signing key
|
|
./$(BIN_DIR)/$(BINARY)$(EXE) generate-keys
|
|
|
|
.PHONY: migrate
|
|
migrate: build ## Apply pending database migrations
|
|
./$(BIN_DIR)/$(BINARY)$(EXE) migrate
|
|
|
|
.PHONY: create-account
|
|
create-account: build ## Create an account: make create-account ACCOUNT=alice ARGS=--admin
|
|
@test -n "$(ACCOUNT)" || { echo "set ACCOUNT, e.g. make create-account ACCOUNT=alice ARGS=--admin"; exit 1; }
|
|
./$(BIN_DIR)/$(BINARY)$(EXE) create-account --username "$(ACCOUNT)" $(ARGS)
|
|
|
|
# --- Admin panel (apps/admin) -------------------------------------------
|
|
# The panel is optional and runs as its own process, warp-admin, which
|
|
# serves the built frontend and proxies to the homeserver.
|
|
|
|
PNPM ?= pnpm
|
|
ADMIN_DIR := apps/admin
|
|
ADMIN_IMAGE ?= warp-admin
|
|
|
|
.PHONY: admin-deps
|
|
admin-deps: ## Install the frontend dependencies (pnpm)
|
|
$(PNPM) install --frozen-lockfile
|
|
|
|
.PHONY: admin-web
|
|
admin-web: ## Build the admin panel frontend into apps/admin/internal/panel/build/dist
|
|
$(PNPM) --filter @warp/admin build
|
|
|
|
.PHONY: admin
|
|
admin: admin-web ## Build bin/warp-admin with the panel embedded
|
|
cd $(ADMIN_DIR) && $(GO) build -ldflags "-X main.version=$(VERSION)" -o ../../$(BIN_DIR)/warp-admin$(EXE) ./cmd/warp-admin
|
|
|
|
.PHONY: admin-run
|
|
admin-run: admin ## Run warp-admin against http://localhost:8008
|
|
./$(BIN_DIR)/warp-admin$(EXE) -homeserver http://localhost:8008
|
|
|
|
.PHONY: admin-dev
|
|
admin-dev: ## Run the panel with hot reload on :5174, proxied to localhost:8008
|
|
$(PNPM) --filter @warp/admin dev
|
|
|
|
.PHONY: admin-test
|
|
admin-test: ## Typecheck the frontend and test warp-admin
|
|
$(PNPM) -r typecheck
|
|
cd $(ADMIN_DIR) && $(GO) vet ./... && $(GO) test ./...
|
|
|
|
.PHONY: admin-docker
|
|
admin-docker: ## Build the warp-admin container image
|
|
docker build -t $(ADMIN_IMAGE):$(VERSION) -f $(ADMIN_DIR)/Dockerfile .
|
|
|
|
# --- Web client (apps/web) --------------------------------------------
|
|
# Optional too: warp-web serves the built client and proxies its Matrix
|
|
# requests to the homeserver.
|
|
|
|
WEB_DIR := apps/web
|
|
WEB_IMAGE ?= warp-web
|
|
|
|
.PHONY: web-web
|
|
web-web: ## Build the web client frontend into apps/web/client/build/dist
|
|
$(PNPM) --filter @warp/web build
|
|
|
|
.PHONY: web
|
|
web: web-web ## Build bin/warp-web with the client embedded
|
|
cd $(WEB_DIR) && $(GO) build -ldflags "-X main.version=$(VERSION)" -o ../../$(BIN_DIR)/warp-web$(EXE) ./cmd/warp-web
|
|
|
|
.PHONY: web-run
|
|
web-run: web ## Run warp-web against http://localhost:8008
|
|
./$(BIN_DIR)/warp-web$(EXE) -homeserver http://localhost:8008
|
|
|
|
.PHONY: web-dev
|
|
web-dev: ## Run the client with hot reload on :5175, proxied to localhost:8008
|
|
$(PNPM) --filter @warp/web dev
|
|
|
|
.PHONY: web-test
|
|
web-test: ## Typecheck the frontend and test warp-web
|
|
$(PNPM) -r typecheck
|
|
cd $(WEB_DIR) && $(GO) vet ./... && $(GO) test ./...
|
|
|
|
.PHONY: web-docker
|
|
web-docker: ## Build the warp-web container image
|
|
docker build -t $(WEB_IMAGE):$(VERSION) -f $(WEB_DIR)/Dockerfile .
|
|
|
|
# --- Desktop client (apps/desktop) ----------------------------------------
|
|
# The web client in a native window (Wails v3). It embeds the same build as
|
|
# warp-web, so `make desktop` builds the web frontend first.
|
|
|
|
DESKTOP_DIR := apps/desktop
|
|
|
|
# Windows builds are GUI programs: no console window behind the app.
|
|
ifeq ($(OS),Windows_NT)
|
|
DESKTOP_LDFLAGS := -H windowsgui
|
|
else
|
|
DESKTOP_LDFLAGS :=
|
|
endif
|
|
|
|
# A build checks for updates when DESKTOP_UPDATE_URL names its update
|
|
# manifest (see desktop-manifest); DESKTOP_VERSION is the version it
|
|
# compares. DESKTOP_UPDATE_KEY, a PEM public key, makes it insist on signed
|
|
# releases.
|
|
DESKTOP_UPDATE_URL ?=
|
|
DESKTOP_UPDATE_KEY ?=
|
|
DESKTOP_X := -X main.version=$(VERSION) -X main.appVersion=$(DESKTOP_VERSION) \
|
|
-X 'main.updateURL=$(DESKTOP_UPDATE_URL)' -X 'main.updateKey=$(DESKTOP_UPDATE_KEY)'
|
|
|
|
.PHONY: desktop
|
|
desktop: web-web ## Build bin/warp-desktop with the web client embedded
|
|
cd $(DESKTOP_DIR) && $(GO) build -tags production -ldflags "$(DESKTOP_X) $(DESKTOP_LDFLAGS)" -o ../../$(BIN_DIR)/warp-desktop$(EXE) ./cmd/warp-desktop
|
|
|
|
.PHONY: desktop-run
|
|
desktop-run: web-web ## Run the desktop client with the developer tools on
|
|
cd $(DESKTOP_DIR) && $(GO) run ./cmd/warp-desktop $(ARGS)
|
|
|
|
.PHONY: desktop-test
|
|
desktop-test: ## Vet and test the desktop client's Go code
|
|
cd $(DESKTOP_DIR) && $(GO) vet ./... && $(GO) test ./...
|
|
|
|
# Packaging. The inputs are in apps/desktop/build. The wails3 CLI, at the
|
|
# version go.mod pins, makes the icons and the Windows .syso and builds the
|
|
# Linux packages; `go run` fetches it, so there is nothing to install.
|
|
# DESKTOP_VERSION is the numeric version the OS sees (Windows version info,
|
|
# Info.plist, package version); `-version` still prints $(VERSION).
|
|
WAILS3 ?= $(GO) run github.com/wailsapp/wails/v3/cmd/wails3@v3.0.0-beta.27
|
|
DESKTOP_VERSION ?= 0.1.0
|
|
DESKTOP_MAINTAINER ?= $(shell git config user.name) <$(shell git config user.email)>
|
|
DESKTOP_FORMATS ?= deb rpm archlinux
|
|
DESKTOP_GEN := $(BIN_DIR)/desktop-build
|
|
DESKTOP_APP := $(BIN_DIR)/Warp.app
|
|
|
|
# The .syso files are committed, so `make desktop` needs none of this; run
|
|
# it after changing the icon, the manifest or DESKTOP_VERSION.
|
|
.PHONY: desktop-resources
|
|
desktop-resources: ## Regenerate the desktop icons and the Windows .syso files
|
|
mkdir -p $(DESKTOP_GEN)
|
|
cd $(DESKTOP_DIR) && $(WAILS3) generate icons -input build/appicon.png -sizes 256,128,64 \
|
|
-windowsfilename ../../$(DESKTOP_GEN)/tile.ico -macfilename build/darwin/icons.icns
|
|
cd $(DESKTOP_DIR) && $(GO) run build/windows/mkico.go -small build/windows/favicon.ico \
|
|
-large ../../$(DESKTOP_GEN)/tile.ico -out build/windows/icon.ico
|
|
sed 's/{{VERSION}}/$(DESKTOP_VERSION)/g' $(DESKTOP_DIR)/build/windows/info.json > $(DESKTOP_GEN)/info.json
|
|
sed 's/{{VERSION}}/$(DESKTOP_VERSION)/g' $(DESKTOP_DIR)/build/windows/warp-desktop.exe.manifest > $(DESKTOP_GEN)/warp-desktop.exe.manifest
|
|
cd $(DESKTOP_DIR) && for arch in amd64 arm64; do \
|
|
$(WAILS3) generate syso -arch $$arch -icon build/windows/icon.ico \
|
|
-manifest ../../$(DESKTOP_GEN)/warp-desktop.exe.manifest -info ../../$(DESKTOP_GEN)/info.json \
|
|
-out cmd/warp-desktop/rsrc_windows_$$arch.syso || exit 1; \
|
|
done
|
|
|
|
# Run on a Mac: the binary needs cgo. Ad-hoc signed, so it runs on the
|
|
# machine that built it; distributing it needs a Developer ID and notarizing.
|
|
.PHONY: desktop-macos
|
|
desktop-macos: desktop ## Build bin/Warp.app (on macOS)
|
|
@test "$$(uname -s)" = Darwin || { echo "desktop-macos runs on macOS"; exit 1; }
|
|
rm -rf $(DESKTOP_APP)
|
|
mkdir -p $(DESKTOP_APP)/Contents/MacOS $(DESKTOP_APP)/Contents/Resources
|
|
cp $(BIN_DIR)/warp-desktop $(DESKTOP_APP)/Contents/MacOS/
|
|
cp $(DESKTOP_DIR)/build/darwin/icons.icns $(DESKTOP_APP)/Contents/Resources/
|
|
sed 's/{{VERSION}}/$(DESKTOP_VERSION)/g' $(DESKTOP_DIR)/build/darwin/Info.plist > $(DESKTOP_APP)/Contents/Info.plist
|
|
codesign --force --deep --sign - $(DESKTOP_APP)
|
|
# The updater's macOS artifact: the bundle, zipped.
|
|
cd $(BIN_DIR) && rm -f Warp.app.zip && ditto -c -k --keepParent Warp.app Warp.app.zip
|
|
|
|
# Run on Linux: the binary needs cgo. Packages land in bin/.
|
|
.PHONY: desktop-linux
|
|
desktop-linux: desktop ## Build Linux packages of the desktop client (on Linux)
|
|
@test "$$(uname -s)" = Linux || { echo "desktop-linux runs on Linux"; exit 1; }
|
|
cd $(DESKTOP_DIR) && for format in $(DESKTOP_FORMATS); do \
|
|
VERSION=$(DESKTOP_VERSION) GOARCH=$$($(GO) env GOARCH) MAINTAINER="$(DESKTOP_MAINTAINER)" \
|
|
$(WAILS3) tool package -name warp-desktop -format $$format \
|
|
-config build/linux/nfpm.yaml -out ../../$(BIN_DIR) || exit 1; \
|
|
done
|
|
|
|
# Run on Windows with NSIS (makensis) on the PATH: a per-user installer,
|
|
# bin/warp-desktop-setup.exe. DESKTOP_SIGN, when set, signs the installer
|
|
# and uninstaller: a command with %1 for the file.
|
|
MAKENSIS ?= makensis
|
|
DESKTOP_SIGN ?=
|
|
|
|
.PHONY: desktop-windows-installer
|
|
desktop-windows-installer: desktop ## Build the Windows installer, bin/warp-desktop-setup.exe
|
|
cd $(DESKTOP_DIR)/build/windows && $(MAKENSIS) -V2 -DVERSION=$(DESKTOP_VERSION) \
|
|
-DEXE=../../../../$(BIN_DIR)/warp-desktop.exe -DOUT=../../../../$(BIN_DIR)/warp-desktop-setup.exe \
|
|
$(if $(DESKTOP_SIGN),"-DSIGN=$(DESKTOP_SIGN)") installer.nsi
|
|
|
|
# The update manifest for the binaries in DESKTOP_ARTIFACTS (os/arch=file,
|
|
# space separated), written to bin/warp-desktop.json. Host it with the
|
|
# files, at DESKTOP_UPDATE_URL.
|
|
DESKTOP_ARTIFACTS ?= $(GOOS_HOST)/$(GOARCH_HOST)=$(BIN_DIR)/warp-desktop$(EXE)
|
|
GOOS_HOST = $(shell $(GO) env GOOS)
|
|
GOARCH_HOST = $(shell $(GO) env GOARCH)
|
|
|
|
.PHONY: desktop-manifest
|
|
desktop-manifest: ## Write the desktop update manifest, bin/warp-desktop.json
|
|
$(GO) -C $(DESKTOP_DIR) run ./build/manifest -version $(DESKTOP_VERSION) -out $(CURDIR)/$(BIN_DIR)/warp-desktop.json \
|
|
$(foreach a,$(DESKTOP_ARTIFACTS),$(firstword $(subst =, ,$(a)))=$(CURDIR)/$(lastword $(subst =, ,$(a))))
|
|
|
|
# The Android app. Needs Flutter, the Android SDK, and Rust with the Android
|
|
# targets (flutter_vodozemac compiles the crypto from source); see
|
|
# apps/mobile/README.md. The APKs land in bin/.
|
|
FLUTTER ?= flutter
|
|
MOBILE_DIR := apps/mobile
|
|
MOBILE_APKS := $(MOBILE_DIR)/build/app/outputs/flutter-apk
|
|
|
|
.PHONY: mobile
|
|
mobile: ## Build the Android app (release APKs, one per ABI, into bin/)
|
|
cd $(MOBILE_DIR) && $(FLUTTER) build apk --release --split-per-abi
|
|
mkdir -p $(BIN_DIR)
|
|
for abi in arm64-v8a armeabi-v7a x86_64; do \
|
|
cp $(MOBILE_APKS)/app-$$abi-release.apk $(BIN_DIR)/warp-android-$$abi.apk || exit 1; \
|
|
done
|
|
|
|
.PHONY: mobile-run
|
|
mobile-run: ## Run the Android app on a connected device or emulator
|
|
cd $(MOBILE_DIR) && $(FLUTTER) run $(ARGS)
|
|
|
|
.PHONY: mobile-test
|
|
mobile-test: ## Analyze and test the Android app
|
|
cd $(MOBILE_DIR) && $(FLUTTER) analyze && $(FLUTTER) test
|
|
|
|
.PHONY: complement-image
|
|
complement-image: ## Build the Complement homeserver image
|
|
docker build -t $(COMPLEMENT_IMAGE) -f $(SERVER_DIR)/test/complement/Dockerfile .
|
|
|
|
.PHONY: complement
|
|
complement: ## Run the Complement C-S subset (federation off)
|
|
bash $(SERVER_DIR)/test/complement/run.sh
|
|
|
|
.PHONY: complement-federation
|
|
complement-federation: ## Run the Complement federation subset
|
|
COMPLEMENT_PROFILE=federation bash $(SERVER_DIR)/test/complement/run.sh
|
|
|
|
.PHONY: docker
|
|
docker: ## Build the container image
|
|
docker build -t warp:$(VERSION) .
|
|
|
|
.PHONY: loadtest
|
|
loadtest: ## Load a test server: make loadtest ARGS="-url http://localhost:8008 -users 50"
|
|
cd $(SERVER_DIR) && $(GO) run ./cmd/warp-loadtest $(ARGS)
|
|
|
|
.PHONY: compose-up
|
|
compose-up: ## Run Warp, PostgreSQL and the observability stack with Docker Compose
|
|
cd deploy/compose && docker compose --profile observability up -d --build
|
|
|
|
.PHONY: helm-lint
|
|
helm-lint: ## Lint and render the Helm chart (needs helm)
|
|
helm lint deploy/helm/warp
|
|
helm template warp deploy/helm/warp > /dev/null
|
|
|
|
.PHONY: clean
|
|
clean: ## Remove build output
|
|
rm -rf $(BIN_DIR) coverage.out coverage.html
|