set dotenv-load := true default: @just --list dev-back: go run ./cmd/cdropd dev-front: cd web && npm run dev build-back: mkdir -p dist go build -o dist/cdropd ./cmd/cdropd build-front: cd web && npm run build build: build-back build-front test: go test ./... typecheck-front: cd web && npm run typecheck fmt: gofmt -w . vet: go vet ./... # 生成一对 VAPID 密钥(Web Push 用)。输出两行 env,写进部署密钥后固定不变—— # 更换会使所有既有浏览器订阅失效。两者皆设才启用推送。 vapid-keygen: go run ./cmd/vapidgen # ---- desktop client (Wails · macOS 主开发,Windows 在 Parallels 验证) ---- # wails CLI 在 go install 后落在 $(go env GOPATH)/bin/wails, # 用绝对路径避免依赖 shell PATH 配置。 wails := `go env GOPATH` + "/bin/wails" # 起 wails dev 热重载,前端走 Vite dev server。 desktop-dev: cd desktop && {{wails}} dev # 构建 macOS universal .app(含 darwin/arm64 + darwin/amd64)。 # 不加 -clean,让 mac/win 产物在 build/bin/ 共存;清理走 desktop-clean。 # # ⚠️ 先手动构建前端再 `wails build -s`(跳过 wails 自带前端步骤):wails build 的 # frontend:build 在本仓库结构下不可靠(不实际重建 web/ → 嵌入旧 JS)。显式构建 # web → desktop/frontend/dist,再用 -s 让 go:embed 嵌入这份新 dist。 desktop-build-mac: cd web && npm run build -- --outDir ../desktop/frontend/dist --emptyOutDir cd desktop && {{wails}} build -s -platform darwin/universal # 交叉编译 Windows amd64 .exe。macOS 原生即可——Windows 侧无 cgo(darwin 的 # NSStatusBar/NSPasteboard CGO 走 build tag 排除,WebView2 是纯 Go),不需 mingw。 # 与 mac 同:先手动构建前端再 -s(wails 自带 frontend:build 在本仓库不可靠)。 # 产物 build/bin/desktop.exe;真测试经 RDP 到 Windows 机器跑。 desktop-build-win: cd web && npm run build -- --outDir ../desktop/frontend/dist --emptyOutDir cd desktop && {{wails}} build -s -platform windows/amd64 # 清空 build/bin/ 产物。 desktop-clean: rm -rf desktop/build/bin # 环境自检。 desktop-doctor: {{wails}} doctor # ---- iOS 真机 ---- # 列出已连接的真机(手机插 USB 后取 UDID,填进门户 Devices + just ios-device)。 ios-devices: xcrun devicectl list devices # 拉取品牌字体(不入库——Orbit Gothic 专有;统一从 CDN / Google Fonts 拉,镜像 web 思路)。幂等:已存在 # 则跳过。ios-sim-build / ios-device 构建前已 chain 本步。前置:curl;造 Fredoka 静态实例需 python3 + # fonttools(python3 -m pip install --user fonttools)。见 ios/CDrop/Sources/Fonts/README.md。 ios-fonts: mkdir -p ios/CDrop/Sources/Fonts ios/CDrop/Shared/Fonts [ -f ios/CDrop/Sources/Fonts/OrbitGothicCJKsc-Regular.woff2 ] || curl -fsSL "https://orbit-gothic.cdn.commilitia.net/WOFF2/CJKsc/OrbitGothicCJKsc-Regular.woff2" -o ios/CDrop/Sources/Fonts/OrbitGothicCJKsc-Regular.woff2 [ -f ios/CDrop/Sources/Fonts/OrbitGothicCJKsc-SemiBold.woff2 ] || curl -fsSL "https://orbit-gothic.cdn.commilitia.net/WOFF2/CJKsc/OrbitGothicCJKsc-SemiBold.woff2" -o ios/CDrop/Sources/Fonts/OrbitGothicCJKsc-SemiBold.woff2 [ -f ios/CDrop/Sources/Fonts/MapleMono-Regular.woff2 ] || curl -fsSL "https://maple-mono.cdn.commilitia.net/MapleMono-Regular.ttf.woff2" -o ios/CDrop/Sources/Fonts/MapleMono-Regular.woff2 [ -f ios/CDrop/Shared/Fonts/Fredoka-SemiBold.ttf ] || just ios-fonts-fredoka # Fredoka 字标:从 Google Fonts 变量字体实例化出静态 SemiBold(wght=600, wdth=100)。 ios-fonts-fredoka: curl -fsSL "https://raw.githubusercontent.com/google/fonts/main/ofl/fredoka/Fredoka%5Bwdth%2Cwght%5D.ttf" -o /tmp/Fredoka-VF.ttf python3 -m fontTools.varLib.instancer /tmp/Fredoka-VF.ttf wght=600 wdth=100 -o ios/CDrop/Shared/Fonts/Fredoka-SemiBold.ttf --update-name-table rm -f /tmp/Fredoka-VF.ttf # 模拟器编译验证(无需签名 / Apple 账号):拉字体 + xcodegen + xcodebuild iphonesimulator。原生数据面 # 引擎走 SPM 的 libwebrtc(首次构建自动拉取 WebRTC.xcframework),无需预构建步骤。用于改动自检。 ios-sim-build: just ios-fonts cd ios/CDrop && xcodegen generate cd ios/CDrop && xcodebuild -project CDrop.xcodeproj -scheme CDrop -sdk iphonesimulator -destination 'generic/platform=iOS Simulator' -derivedDataPath build/DD build # 真机构建 + 装机(自动 provisioning,经 ASC API Key)。前置:付费 ADP;App ID 的 App Groups / # Push 能力(门户建好或自动建);根目录 gitignore 的 .env 配齐:CDROP_TEAM_ID / CDROP_ASC_KEY_PATH # (.p8 路径)/ CDROP_ASC_KEY_ID / CDROP_ASC_ISSUER_ID。-allowProvisioningUpdates 自动登记连接的 # 设备 + 建 profile(绕过手动 profile 的设备选择坑)。模拟器构建不需这些(base ad-hoc)。原生数据面 # 经 SPM 拉 libwebrtc,无 gomobile 预构建步骤(早先 ios-engine recipe 已随 pion-on-iOS 废弃移除)。 # 用法:just ios-device <设备UDID>(UDID 见 just ios-devices)。 ios-device udid: [ -n "$CDROP_TEAM_ID" ] && [ -n "$CDROP_ASC_KEY_PATH" ] && [ -n "$CDROP_ASC_KEY_ID" ] && [ -n "$CDROP_ASC_ISSUER_ID" ] || { echo "缺 .env(CDROP_TEAM_ID / CDROP_ASC_KEY_PATH / CDROP_ASC_KEY_ID / CDROP_ASC_ISSUER_ID)——见 ios/CDrop/REALDEVICE.md"; exit 1; } just ios-fonts cd ios/CDrop && xcodegen generate cd ios/CDrop && xcodebuild -project CDrop.xcodeproj -scheme CDrop -configuration Debug -destination "platform=iOS,id={{udid}}" -derivedDataPath build/DD-device -allowProvisioningUpdates -authenticationKeyPath "$CDROP_ASC_KEY_PATH" -authenticationKeyID "$CDROP_ASC_KEY_ID" -authenticationKeyIssuerID "$CDROP_ASC_ISSUER_ID" DEVELOPMENT_TEAM="$CDROP_TEAM_ID" CODE_SIGN_STYLE=Automatic CODE_SIGN_IDENTITY="Apple Development" build xcrun devicectl device install app --device {{udid}} ios/CDrop/build/DD-device/Build/Products/Debug-iphoneos/CDrop.app # ---- deploy plumbing ---- # 一次性预热:把 Go modules + node_modules 烤进 cdrop-base:latest。 # 仅 go.mod/go.sum 或 web/package*.json 改动时需要重跑。 # 用宿主原生 arch(macOS arm64 → linux/arm64),让 BUILDPLATFORM 跨编译走原生。 docker-base: docker buildx build -f docker/Dockerfile.base -t cdrop-base:latest --load . # 应用镜像:从 cdrop-base 起步只编译源码,最终落 linux/amd64 distroless。 # dev mode 部署时 export VITE_CDROP_DEV_TOKEN=<同后端 token> 把它烤进前端 bundle。 docker-image: docker buildx build --platform linux/amd64 \ --build-arg VITE_CDROP_DEV_TOKEN="${VITE_CDROP_DEV_TOKEN:-}" \ --build-arg VITE_CDROP_STUN_URLS="${VITE_CDROP_STUN_URLS:-}" \ -f docker/Dockerfile -t cdrop:latest --load .