mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-11 01:36:37 +08:00
make build
This commit is contained in:
@@ -36,11 +36,17 @@ build-test:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
cross-build:
|
cross-build:
|
||||||
@echo "==> Cross-compiling for linux/darwin/windows × amd64/arm64..."
|
@echo "==> Cross-compiling \
|
||||||
|
$(if $(GOOS),$(GOOS),linux/darwin/windows) × \
|
||||||
|
$(if $(GOARCH),$(GOARCH),amd64/arm64) \
|
||||||
|
(version=$(or $(VERSION),dev))..."
|
||||||
@mkdir -p bin
|
@mkdir -p bin
|
||||||
docker build \
|
docker build \
|
||||||
--file docker/Dockerfile.cross \
|
--file docker/Dockerfile.cross \
|
||||||
--target export \
|
--target export \
|
||||||
|
--build-arg VERSION=$(or $(VERSION),dev) \
|
||||||
|
$(if $(GOOS),--build-arg TARGET_OS=$(GOOS)) \
|
||||||
|
$(if $(GOARCH),--build-arg TARGET_ARCH=$(GOARCH)) \
|
||||||
--output type=local,dest=./bin \
|
--output type=local,dest=./bin \
|
||||||
.
|
.
|
||||||
@echo "==> Done. Binaries written to ./bin/"
|
@echo "==> Done. Binaries written to ./bin/"
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ pnpm format
|
|||||||
wavelet/
|
wavelet/
|
||||||
├── main.go # Entry point (delegates to internal/cmd)
|
├── main.go # Entry point (delegates to internal/cmd)
|
||||||
├── config.example.yaml # Configuration template
|
├── config.example.yaml # Configuration template
|
||||||
├── Makefile # Common commands (swagger, tidy, license)
|
├── Makefile # Common commands (swagger, tidy, license, cross-build)
|
||||||
├── docker/ # Docker image build files (integrated/frontend/backend)
|
├── docker/ # Docker image build files (integrated/frontend/backend)
|
||||||
├── docs/ # Swagger auto-generated docs
|
├── docs/ # Swagger auto-generated docs
|
||||||
├── frontend/ # Next.js frontend application
|
├── frontend/ # Next.js frontend application
|
||||||
@@ -257,6 +257,47 @@ cd frontend && pnpm lint
|
|||||||
|
|
||||||
## 🚀 Deployment
|
## 🚀 Deployment
|
||||||
|
|
||||||
|
### Cross-platform Binary
|
||||||
|
|
||||||
|
Build static binaries for all 6 targets (Linux / macOS / Windows × amd64 / arm64) with a single command.
|
||||||
|
The compiled frontend is embedded in every binary — no separate deployment needed.
|
||||||
|
|
||||||
|
**Prerequisites:** Docker with BuildKit enabled (Docker 23+ defaults to on).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build all 6 binaries → ./bin/
|
||||||
|
make cross-build
|
||||||
|
|
||||||
|
# Stamp a release version
|
||||||
|
make cross-build VERSION=v1.2.3
|
||||||
|
|
||||||
|
# Build only a specific OS (both architectures)
|
||||||
|
make cross-build GOOS=linux
|
||||||
|
make cross-build GOOS=darwin
|
||||||
|
make cross-build GOOS=windows
|
||||||
|
|
||||||
|
# Build only a specific architecture (all OSes)
|
||||||
|
make cross-build GOARCH=amd64
|
||||||
|
make cross-build GOARCH=arm64
|
||||||
|
|
||||||
|
# Combine filters — single binary
|
||||||
|
make cross-build GOOS=linux GOARCH=arm64
|
||||||
|
make cross-build GOOS=darwin GOARCH=amd64 VERSION=v1.2.3
|
||||||
|
```
|
||||||
|
|
||||||
|
Output files in `./bin/`:
|
||||||
|
|
||||||
|
| File | Platform |
|
||||||
|
|------|----------|
|
||||||
|
| `wavelet_linux_amd64` | Linux x86-64 |
|
||||||
|
| `wavelet_linux_arm64` | Linux ARM64 |
|
||||||
|
| `wavelet_darwin_amd64` | macOS Intel |
|
||||||
|
| `wavelet_darwin_arm64` | macOS Apple Silicon |
|
||||||
|
| `wavelet_windows_amd64.exe` | Windows x86-64 |
|
||||||
|
| `wavelet_windows_arm64.exe` | Windows ARM64 |
|
||||||
|
|
||||||
|
> The version string is accessible at runtime via `wavelet --version`.
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
+42
-1
@@ -212,7 +212,7 @@ pnpm format
|
|||||||
wavelet/
|
wavelet/
|
||||||
├── main.go # 程序入口(委托给 internal/cmd)
|
├── main.go # 程序入口(委托给 internal/cmd)
|
||||||
├── config.example.yaml # 配置模板
|
├── config.example.yaml # 配置模板
|
||||||
├── Makefile # 常用命令(swagger、tidy、license)
|
├── Makefile # 常用命令(swagger、tidy、license、cross-build)
|
||||||
├── docker/ # Docker 镜像构建文件(集成/前端/后端)
|
├── docker/ # Docker 镜像构建文件(集成/前端/后端)
|
||||||
├── docs/ # Swagger 自动生成文档
|
├── docs/ # Swagger 自动生成文档
|
||||||
├── frontend/ # Next.js 前端应用
|
├── frontend/ # Next.js 前端应用
|
||||||
@@ -257,6 +257,47 @@ cd frontend && pnpm lint
|
|||||||
|
|
||||||
## 🚀 部署
|
## 🚀 部署
|
||||||
|
|
||||||
|
### 跨平台二进制编译
|
||||||
|
|
||||||
|
一条命令构建全部 6 个平台的静态二进制文件(Linux / macOS / Windows × amd64 / arm64)。
|
||||||
|
前端已内嵌到每个二进制文件中,无需单独部署。
|
||||||
|
|
||||||
|
**前提条件:** 已安装 Docker 且启用 BuildKit(Docker 23+ 默认开启)。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建全部 6 个二进制文件 → ./bin/
|
||||||
|
make cross-build
|
||||||
|
|
||||||
|
# 指定版本号
|
||||||
|
make cross-build VERSION=v1.2.3
|
||||||
|
|
||||||
|
# 只构建指定系统(两种架构均会构建)
|
||||||
|
make cross-build GOOS=linux
|
||||||
|
make cross-build GOOS=darwin
|
||||||
|
make cross-build GOOS=windows
|
||||||
|
|
||||||
|
# 只构建指定架构(所有系统均会构建)
|
||||||
|
make cross-build GOARCH=amd64
|
||||||
|
make cross-build GOARCH=arm64
|
||||||
|
|
||||||
|
# 同时指定系统和架构 — 只生成单个文件
|
||||||
|
make cross-build GOOS=linux GOARCH=arm64
|
||||||
|
make cross-build GOOS=darwin GOARCH=amd64 VERSION=v1.2.3
|
||||||
|
```
|
||||||
|
|
||||||
|
输出到 `./bin/` 目录:
|
||||||
|
|
||||||
|
| 文件名 | 平台 |
|
||||||
|
|--------|------|
|
||||||
|
| `wavelet_linux_amd64` | Linux x86-64 |
|
||||||
|
| `wavelet_linux_arm64` | Linux ARM64 |
|
||||||
|
| `wavelet_darwin_amd64` | macOS Intel |
|
||||||
|
| `wavelet_darwin_arm64` | macOS Apple Silicon |
|
||||||
|
| `wavelet_windows_amd64.exe` | Windows x86-64 |
|
||||||
|
| `wavelet_windows_arm64.exe` | Windows ARM64 |
|
||||||
|
|
||||||
|
> 版本号可通过 `wavelet --version` 在运行时查看。
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
+71
-9
@@ -1,52 +1,114 @@
|
|||||||
# syntax=docker/dockerfile:1.7
|
# syntax=docker/dockerfile:1.7
|
||||||
# Cross-platform build workflow — produces 6 static binaries under ./bin/
|
# Cross-platform build workflow — produces up to 6 static binaries under ./bin/
|
||||||
|
# Each binary embeds the compiled frontend and is stamped with VERSION.
|
||||||
|
#
|
||||||
|
# Build args:
|
||||||
|
# VERSION — version string injected at link time (default: dev)
|
||||||
|
# TARGET_OS — restrict to one OS: linux | darwin | windows (default: all)
|
||||||
|
# TARGET_ARCH — restrict to one arch: amd64 | arm64 (default: all)
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# docker build -f docker/Dockerfile.cross --output ./bin .
|
# docker build -f docker/Dockerfile.cross --output ./bin .
|
||||||
|
# docker build -f docker/Dockerfile.cross \
|
||||||
|
# --build-arg VERSION=v1.2.3 --output ./bin .
|
||||||
|
# docker build -f docker/Dockerfile.cross \
|
||||||
|
# --build-arg TARGET_OS=linux --build-arg TARGET_ARCH=arm64 \
|
||||||
|
# --output ./bin .
|
||||||
#
|
#
|
||||||
# Or via Makefile:
|
# Or via Makefile:
|
||||||
# make cross-build
|
# make cross-build
|
||||||
|
# make cross-build VERSION=v1.2.3
|
||||||
|
# make cross-build GOOS=linux GOARCH=arm64
|
||||||
|
# make cross-build GOOS=darwin
|
||||||
|
|
||||||
ARG GO_VERSION=1.25
|
ARG GO_VERSION=1.25
|
||||||
|
ARG NODE_VERSION=22
|
||||||
ARG ALPINE_VERSION=3.23
|
ARG ALPINE_VERSION=3.23
|
||||||
|
|
||||||
|
# ── Stage 1: Build frontend (static export for embedding) ────────────────────
|
||||||
|
FROM node:${NODE_VERSION}-alpine AS frontend-builder
|
||||||
|
|
||||||
|
ARG VERSION=dev
|
||||||
|
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV NEXT_STANDALONE_EXPORT=true
|
||||||
|
|
||||||
|
RUN corepack enable && corepack prepare pnpm@10.10.0 --activate
|
||||||
|
|
||||||
|
WORKDIR /workspace/frontend
|
||||||
|
|
||||||
|
# Cache dependency layer
|
||||||
|
COPY frontend/package.json frontend/pnpm-lock.yaml ./
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
COPY frontend/ ./
|
||||||
|
|
||||||
|
# Stamp version into package.json when VERSION is not "dev"
|
||||||
|
RUN if [ "$VERSION" != "dev" ]; then \
|
||||||
|
node -e " \
|
||||||
|
const fs = require('fs'); \
|
||||||
|
const pkg = require('./package.json'); \
|
||||||
|
pkg.version = process.env.VERSION.replace(/^v/, ''); \
|
||||||
|
fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n'); \
|
||||||
|
"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
RUN pnpm build:embed
|
||||||
|
|
||||||
|
# ── Stage 2: Cross-compile Go backend ──────────────────────────────────────
|
||||||
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS builder
|
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS builder
|
||||||
|
|
||||||
|
ARG VERSION=dev
|
||||||
|
# Empty string means "build all"; set to a specific value to filter.
|
||||||
|
ARG TARGET_OS=
|
||||||
|
ARG TARGET_ARCH=
|
||||||
|
|
||||||
# git — needed by go mod download for VCS-stamped modules
|
# git — needed by go mod download for VCS-stamped modules
|
||||||
# ca-certificates — needed for HTTPS during module download
|
# ca-certificates — needed for HTTPS during module download
|
||||||
RUN apk add --no-cache ca-certificates git
|
RUN apk add --no-cache ca-certificates git
|
||||||
|
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
|
||||||
# Cache dependency downloads separately from source
|
# Cache dependency layer
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Build matrix: GOOS × GOARCH
|
# Overlay the compiled frontend into the embed path
|
||||||
# CGO_ENABLED=0 ensures fully static, portable binaries (no libc dependency).
|
COPY --from=frontend-builder /workspace/frontend/out ./internal/router/dist
|
||||||
# -trimpath removes local path info; -s -w strips debug info for smaller output.
|
|
||||||
ARG BUILD_FLAGS="-trimpath -ldflags=-s -w"
|
|
||||||
|
|
||||||
|
# Build matrix: GOOS × GOARCH
|
||||||
|
# CGO_ENABLED=0 — fully static, no libc dependency, required for cross-compilation.
|
||||||
|
# -trimpath — strip local filesystem paths from the binary.
|
||||||
|
# -s -w — omit symbol table and DWARF debug info (smaller output).
|
||||||
|
# -X — stamp version string at link time.
|
||||||
|
# TARGET_OS / TARGET_ARCH — when non-empty, skip non-matching combinations.
|
||||||
RUN set -e; \
|
RUN set -e; \
|
||||||
mkdir -p /out; \
|
mkdir -p /out; \
|
||||||
|
FILTER_OS="${TARGET_OS}"; \
|
||||||
|
FILTER_ARCH="${TARGET_ARCH}"; \
|
||||||
for GOOS in linux darwin windows; do \
|
for GOOS in linux darwin windows; do \
|
||||||
|
[ -n "$FILTER_OS" ] && [ "$GOOS" != "$FILTER_OS" ] && continue; \
|
||||||
for GOARCH in amd64 arm64; do \
|
for GOARCH in amd64 arm64; do \
|
||||||
|
[ -n "$FILTER_ARCH" ] && [ "$GOARCH" != "$FILTER_ARCH" ] && continue; \
|
||||||
EXT=""; \
|
EXT=""; \
|
||||||
[ "$GOOS" = "windows" ] && EXT=".exe"; \
|
[ "$GOOS" = "windows" ] && EXT=".exe"; \
|
||||||
OUTPUT="/out/wavelet_${GOOS}_${GOARCH}${EXT}"; \
|
OUTPUT="/out/wavelet_${GOOS}_${GOARCH}${EXT}"; \
|
||||||
echo "==> Building ${OUTPUT}..."; \
|
echo "==> Building ${OUTPUT} (version=${VERSION})..."; \
|
||||||
CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} \
|
CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} \
|
||||||
go build \
|
go build \
|
||||||
|
-tags embed_frontend \
|
||||||
-trimpath \
|
-trimpath \
|
||||||
-ldflags="-s -w" \
|
-ldflags="-s -w -X github.com/Rain-kl/Wavelet/internal/cmd.Version=${VERSION}" \
|
||||||
-o "${OUTPUT}" \
|
-o "${OUTPUT}" \
|
||||||
./main.go; \
|
./main.go; \
|
||||||
done; \
|
done; \
|
||||||
done
|
done
|
||||||
|
|
||||||
# ── Export stage ─────────────────────────────────────────────────────────────
|
# ── Export stage ─────────────────────────────────────────────────────────────
|
||||||
# `docker build --output ./bin .` will copy everything from /out into the host.
|
# `docker build --output ./bin .` copies everything from /out to the host.
|
||||||
FROM scratch AS export
|
FROM scratch AS export
|
||||||
COPY --from=builder /out/ /
|
COPY --from=builder /out/ /
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {motion} from "motion/react"
|
|||||||
import {useUser} from "@/contexts/user-context"
|
import {useUser} from "@/contexts/user-context"
|
||||||
import {Card, CardHeader, CardTitle} from "@/components/ui/card"
|
import {Card, CardHeader, CardTitle} from "@/components/ui/card"
|
||||||
import {Button} from "@/components/ui/button"
|
import {Button} from "@/components/ui/button"
|
||||||
import {ArrowRight, ExternalLink, FileText, HelpCircle, Layers, Shield, ShieldCheck, User} from "lucide-react"
|
import {ArrowRight, ExternalLink, FileText, HelpCircle, Layers, Shield, ShieldCheck, Terminal, User} from "lucide-react"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
|
||||||
export function HomeMain() {
|
export function HomeMain() {
|
||||||
@@ -80,6 +80,15 @@ export function HomeMain() {
|
|||||||
bgColor: "bg-teal-500/10",
|
bgColor: "bg-teal-500/10",
|
||||||
borderColor: "hover:border-teal-500/30",
|
borderColor: "hover:border-teal-500/30",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "系统日志",
|
||||||
|
description: "查看异步任务执行日志与系统运行状态详情",
|
||||||
|
icon: Terminal,
|
||||||
|
url: "/admin/logs",
|
||||||
|
color: "text-cyan-500",
|
||||||
|
bgColor: "bg-cyan-500/10",
|
||||||
|
borderColor: "hover:border-cyan-500/30",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -163,7 +172,7 @@ export function HomeMain() {
|
|||||||
<div className="px-5 pb-5">
|
<div className="px-5 pb-5">
|
||||||
<Button variant="link" className="p-0 h-auto text-xs text-indigo-500 font-medium" asChild>
|
<Button variant="link" className="p-0 h-auto text-xs text-indigo-500 font-medium" asChild>
|
||||||
<Link href={link.url}>
|
<Link href={link.url}>
|
||||||
管理配置 <ArrowRight className="size-3 ml-1" />
|
立即进入 <ArrowRight className="size-3 ml-1" />
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -24,6 +24,13 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Version is the application version string. It is set at link time via:
|
||||||
|
//
|
||||||
|
// -ldflags="-X github.com/Rain-kl/Wavelet/internal/cmd.Version=<version>"
|
||||||
|
//
|
||||||
|
// When not set (e.g. local `go run`), the value defaults to "dev".
|
||||||
|
var Version = "dev"
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "wavelet",
|
Use: "wavelet",
|
||||||
PreRun: func(_ *cobra.Command, _ []string) {
|
PreRun: func(_ *cobra.Command, _ []string) {
|
||||||
@@ -52,6 +59,7 @@ var rootCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
rootCmd.Version = Version
|
||||||
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user