Files
spaceshell/Makefile
T
vasyansk 2ee2aaaffb
Build / Build & push landing (push) Successful in 14s
Build / Deploy to prod (push) Successful in 7s
Build / Notify Max (push) Successful in 2s
Update version to 0.1.10
Add deepseek to resume commands

Rename app to spaceshell

Add SurfacePicker component for preset panel configuration

Extract agent selection logic to shared agents.ts

Update landing
2026-06-15 17:25:53 +07:00

182 lines
8.1 KiB
Makefile

# spacesh — local build helpers (macOS).
# `make` or `make help` lists targets.
APP_DIR := app
TAURI_TARGET := universal-apple-darwin
DMG_DIR := $(APP_DIR)/src-tauri/target/$(TAURI_TARGET)/release/bundle/dmg
NATIVE_DMG_DIR := $(APP_DIR)/src-tauri/target/release/bundle/dmg
NATIVE_TRIPLE := $(shell rustc -vV 2>/dev/null | awk '/^host:/{print $$2}')
SIDECAR_DIR := $(APP_DIR)/src-tauri/bin
BUNDLE_CONFIG := src-tauri/tauri.bundle.conf.json
APP_BUNDLE := $(APP_DIR)/src-tauri/target/$(TAURI_TARGET)/release/bundle/macos/spaceshell.app
NATIVE_APP_BUNDLE := $(APP_DIR)/src-tauri/target/release/bundle/macos/spaceshell.app
APP_VERSION := $(shell node -p "require('./$(APP_DIR)/src-tauri/tauri.conf.json').version" 2>/dev/null || echo 0.0.0)
LANDING_IMAGE := spacesh-landing
LANDING_VERSION := $(shell cat landing/VERSION 2>/dev/null || echo 0.0.0)
REGISTRY ?= git.realmanual.ru
REPO ?= spacesh
# ---- Gitea generic package registry (versioned .dmg downloads) ----
GITEA_URL ?= https://git.realmanual.ru
GITEA_OWNER ?= pub
GITEA_PKG ?= spacesh
GITEA_TOKEN ?= # token with package:write; pass via env/CLI, never commit
# ---- Prod deploy (SSH) ----
SSH_HOST ?= 192.168.8.5
SSH_USER ?= root
SSH_REMOTE_DIR ?= /srv/spaceshell
SSH_KEY ?= $(HOME)/.ssh/id_rsa
SSH_OPTS := -i $(SSH_KEY) -o StrictHostKeyChecking=accept-new
.DEFAULT_GOAL := help
.PHONY: help
help: ## show this help
@echo "spacesh — make targets (app v$(APP_VERSION)):"
@grep -hE '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | \
awk 'BEGIN{FS=":.*?## "}{printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
# ---- App / DMG (macOS) ----
.PHONY: deps
deps: ## install frontend deps (npm ci)
cd $(APP_DIR) && npm ci
.PHONY: targets
targets: ## add rust targets for the universal build
rustup target add aarch64-apple-darwin x86_64-apple-darwin
.PHONY: bump
bump: ## increment the patch version for BOTH the GUI (tauri.conf.json) and the daemon (workspace Cargo.toml)
@node scripts/bump_version.mjs
.PHONY: dmg
dmg: bump targets ## bump version + build the universal (Intel + Apple Silicon) .dmg — UNSIGNED
# Tauri's universal build needs BOTH the per-arch sidecars (resolved during each
# arch sub-build) AND a fat spaceshd-universal-apple-darwin (copied into the final
# bundle — Tauri does not lipo sidecars itself). spaceshd ships inside
# spacesh.app/Contents/MacOS else the GUI is offline.
cargo build --release -p spaceshd --target aarch64-apple-darwin
cargo build --release -p spaceshd --target x86_64-apple-darwin
rm -rf $(SIDECAR_DIR) && mkdir -p $(SIDECAR_DIR) # avoid stale sidecars poisoning the bundle
cp target/aarch64-apple-darwin/release/spaceshd $(SIDECAR_DIR)/spaceshd-aarch64-apple-darwin
cp target/x86_64-apple-darwin/release/spaceshd $(SIDECAR_DIR)/spaceshd-x86_64-apple-darwin
lipo -create -output $(SIDECAR_DIR)/spaceshd-universal-apple-darwin \
target/aarch64-apple-darwin/release/spaceshd \
target/x86_64-apple-darwin/release/spaceshd
cd $(APP_DIR) && npm run tauri build -- --target $(TAURI_TARGET) --config $(BUNDLE_CONFIG)
@echo "$(DMG_DIR)" && ls -lh $(DMG_DIR)/*.dmg
.PHONY: dmg-native
dmg-native: bump ## bump version + build a .dmg for the current arch only (faster)
cargo build --release -p spaceshd
rm -rf $(SIDECAR_DIR) && mkdir -p $(SIDECAR_DIR) # avoid stale sidecars poisoning the bundle
cp target/release/spaceshd $(SIDECAR_DIR)/spaceshd-$(NATIVE_TRIPLE)
cd $(APP_DIR) && npm run tauri build -- --config $(BUNDLE_CONFIG)
@ls -lh $(NATIVE_DMG_DIR)/*.dmg
.PHONY: app-bundle
app-bundle: ## build just the native .app (no .dmg/hdiutil — fast, for self-install)
cargo build --release -p spaceshd
rm -rf $(SIDECAR_DIR) && mkdir -p $(SIDECAR_DIR)
cp target/release/spaceshd $(SIDECAR_DIR)/spaceshd-$(NATIVE_TRIPLE)
cd $(APP_DIR) && npm run tauri build -- --bundles app --config $(BUNDLE_CONFIG)
.PHONY: dev
dev: ## run the app in dev mode (tauri dev)
cd $(APP_DIR) && npm run tauri dev
.PHONY: daemon
daemon: ## build & run the daemon
cargo run -p spaceshd
.PHONY: kill-daemon
kill-daemon: ## stop a running spaceshd so a freshly-built one takes over
-pkill -x spaceshd
-rm -f $$HOME/.spacesh/sock
.PHONY: install
install: kill-daemon ## install the native .app to /Applications, restart daemon, clear quarantine
rm -rf /Applications/spacesh.app /Applications/spaceshell.app # drop the pre-rename app too
cp -R "$(NATIVE_APP_BUNDLE)" /Applications/
xattr -dr com.apple.quarantine /Applications/spaceshell.app
@echo "Installed (native). Quit & relaunch spaceshell; the bundled daemon restarts."
.PHONY: install-universal
install-universal: kill-daemon ## install the universal .app to /Applications
rm -rf /Applications/spacesh.app /Applications/spaceshell.app
cp -R "$(APP_BUNDLE)" /Applications/
xattr -dr com.apple.quarantine /Applications/spaceshell.app
.PHONY: reinstall
reinstall: app-bundle install ## fast self-update: build .app (no dmg), reinstall, restart daemon
# ---- Tests ----
.PHONY: test
test: ## run all tests (cargo + tsc)
cargo test
cd $(APP_DIR) && npx tsc --noEmit
# ---- Landing ----
.PHONY: landing-image
landing-image: ## build the landing nginx image
docker build -t $(LANDING_IMAGE):$(LANDING_VERSION) -t $(LANDING_IMAGE):latest landing
.PHONY: landing-run
landing-run: landing-image ## serve the landing locally on http://localhost:8088
docker run --rm -p 8088:80 $(LANDING_IMAGE):latest
.PHONY: landing-push
landing-push: landing-image ## tag & push the landing image to the registry
docker tag $(LANDING_IMAGE):latest $(REGISTRY)/$(REPO)/$(LANDING_IMAGE):$(LANDING_VERSION)
docker tag $(LANDING_IMAGE):latest $(REGISTRY)/$(REPO)/$(LANDING_IMAGE):latest
docker push $(REGISTRY)/$(REPO)/$(LANDING_IMAGE):$(LANDING_VERSION)
docker push $(REGISTRY)/$(REPO)/$(LANDING_IMAGE):latest
# ---- Prod deploy ----
.PHONY: deploy-dmg
deploy-dmg: dmg ## upload .dmg + manifest to prod, and publish the versioned .dmg to Gitea Packages
@VER=$$(node -p "require('./$(APP_DIR)/src-tauri/tauri.conf.json').version"); \
printf '{"version":"%s","url":"https://spaceshell.ru/download/spacesh.dmg"}\n' "$$VER" > /tmp/spacesh-latest.json; \
echo "manifest version → $$VER"
ssh $(SSH_OPTS) $(SSH_USER)@$(SSH_HOST) "mkdir -p $(SSH_REMOTE_DIR)/download"
scp $(SSH_OPTS) $(DMG_DIR)/*.dmg "$(SSH_USER)@$(SSH_HOST):$(SSH_REMOTE_DIR)/download/spacesh.dmg"
scp $(SSH_OPTS) /tmp/spacesh-latest.json "$(SSH_USER)@$(SSH_HOST):$(SSH_REMOTE_DIR)/download/latest.json"
@echo "Uploaded → https://spaceshell.ru/download/spacesh.dmg + latest.json"
@$(MAKE) --no-print-directory _publish-dmg
.PHONY: publish-dmg
publish-dmg: dmg _publish-dmg ## build + publish the versioned .dmg to the Gitea package registry
# Internal: upload the most recently built .dmg to Gitea's generic registry under
# the current version. No build dependency, so deploy-dmg can call it without a
# second bump/rebuild. Skips (doesn't fail) when GITEA_TOKEN is unset.
.PHONY: _publish-dmg
_publish-dmg:
@if [ -z "$(GITEA_TOKEN)" ]; then echo "GITEA_TOKEN unset — skipping Gitea Packages publish"; exit 0; fi; \
VER=$$(node -p "require('./$(APP_DIR)/src-tauri/tauri.conf.json').version"); \
DMG=$$(ls -t $(DMG_DIR)/*.dmg 2>/dev/null | head -1); \
if [ -z "$$DMG" ]; then echo "no .dmg in $(DMG_DIR) — run make dmg first"; exit 1; fi; \
URL="$(GITEA_URL)/api/packages/$(GITEA_OWNER)/generic/$(GITEA_PKG)/$$VER/spaceshell-$$VER.dmg"; \
echo "Publishing $$DMG → $$URL"; \
curl --fail-with-body -sS -H "Authorization: token $(GITEA_TOKEN)" --upload-file "$$DMG" "$$URL" && \
echo "Published spaceshell-$$VER.dmg to Gitea Packages ($(GITEA_OWNER)/$(GITEA_PKG)@$$VER)"
.PHONY: deploy-stack
deploy-stack: ## sync compose+proxy.conf to prod and pull/up (manual; CI does this on push)
ssh $(SSH_OPTS) $(SSH_USER)@$(SSH_HOST) "mkdir -p $(SSH_REMOTE_DIR)/download"
scp $(SSH_OPTS) deploy/docker-compose.yaml deploy/proxy.conf "$(SSH_USER)@$(SSH_HOST):$(SSH_REMOTE_DIR)/"
ssh $(SSH_OPTS) $(SSH_USER)@$(SSH_HOST) "cd $(SSH_REMOTE_DIR) && docker compose pull && docker compose up -d"
# ---- Clean ----
.PHONY: clean
clean: ## remove build artifacts
cargo clean
rm -rf $(APP_DIR)/dist