Revert "chore: make Lite edition support and related configurations hidden"
This reverts commit 88d5b303b8.
This commit is contained in:
@@ -0,0 +1,45 @@
|
|||||||
|
# WeKnora Lite 配置模板
|
||||||
|
# 复制此文件为 .env.lite 并按需修改
|
||||||
|
# cp .env.lite.example .env.lite
|
||||||
|
|
||||||
|
GIN_MODE=release
|
||||||
|
|
||||||
|
# === 数据库 ===
|
||||||
|
DB_DRIVER=sqlite
|
||||||
|
DB_PATH=./data/weknora.db
|
||||||
|
|
||||||
|
# === 检索引擎(FTS5 + sqlite-vec)===
|
||||||
|
RETRIEVE_DRIVER=sqlite
|
||||||
|
|
||||||
|
# === 文件存储 ===
|
||||||
|
STORAGE_TYPE=local
|
||||||
|
LOCAL_STORAGE_BASE_DIR=./data/files
|
||||||
|
|
||||||
|
# === 流管理(内存,无 Redis)===
|
||||||
|
STREAM_MANAGER_TYPE=memory
|
||||||
|
|
||||||
|
# === LLM 服务 ===
|
||||||
|
# Ollama 本地服务(默认地址,按需修改)
|
||||||
|
OLLAMA_BASE_URL=http://127.0.0.1:11434
|
||||||
|
# 如使用其他 OpenAI 兼容服务,取消注释:
|
||||||
|
# OPENAI_API_KEY=sk-xxx
|
||||||
|
# OPENAI_BASE_URL=https://api.openai.com/v1
|
||||||
|
|
||||||
|
# === 安全配置(生产环境请务必修改!)===
|
||||||
|
TENANT_AES_KEY=CHANGE-ME-32-char-secret-key!!!!
|
||||||
|
JWT_SECRET=CHANGE-ME-jwt-secret
|
||||||
|
|
||||||
|
# === 功能开关 ===
|
||||||
|
NEO4J_ENABLE=false
|
||||||
|
WEKNORA_SANDBOX_MODE=disabled
|
||||||
|
ENABLE_GRAPH_RAG=false
|
||||||
|
DISABLE_REGISTRATION=false
|
||||||
|
|
||||||
|
# === 性能 ===
|
||||||
|
CONCURRENCY_POOL_SIZE=3
|
||||||
|
|
||||||
|
# Docreader 地址
|
||||||
|
DOCREADER_ADDR=127.0.0.1:50051
|
||||||
|
|
||||||
|
# Docreader 传输方式
|
||||||
|
DOCREADER_TRANSPORT=grpc
|
||||||
@@ -0,0 +1,246 @@
|
|||||||
|
name: Release Lite Binaries
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: "Release tag (e.g. v0.2.0)"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: release-lite-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
GO_VERSION: "1.24"
|
||||||
|
NODE_VERSION: "22"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# ── 1. Build frontend once, share as artifact ──
|
||||||
|
build-frontend:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: npm
|
||||||
|
cache-dependency-path: frontend/package-lock.json
|
||||||
|
|
||||||
|
- name: Build frontend
|
||||||
|
working-directory: frontend
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: frontend-dist
|
||||||
|
path: frontend/dist/
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
# ── 2. Build Go binary per platform (native CGO) ──
|
||||||
|
build-binary:
|
||||||
|
needs: build-frontend
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
goos: linux
|
||||||
|
goarch: amd64
|
||||||
|
- os: ubuntu-24.04-arm
|
||||||
|
goos: linux
|
||||||
|
goarch: arm64
|
||||||
|
- os: macos-13
|
||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
- os: macos-14
|
||||||
|
goos: darwin
|
||||||
|
goarch: arm64
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CGO_ENABLED: 1
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: frontend-dist
|
||||||
|
path: web/
|
||||||
|
|
||||||
|
- name: Resolve version
|
||||||
|
id: ver
|
||||||
|
run: |
|
||||||
|
if [ -n "${{ inputs.tag }}" ]; then
|
||||||
|
VERSION="${{ inputs.tag }}"
|
||||||
|
else
|
||||||
|
VERSION="${GITHUB_REF#refs/tags/}"
|
||||||
|
fi
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Building ${VERSION} for ${{ matrix.goos }}/${{ matrix.goarch }}"
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
export EDITION=lite
|
||||||
|
eval "$(./scripts/get_version.sh env)"
|
||||||
|
LDFLAGS="-w -s $(./scripts/get_version.sh ldflags)"
|
||||||
|
export CGO_CFLAGS="-Wno-deprecated-declarations"
|
||||||
|
if [ "${{ matrix.goos }}" = "darwin" ]; then
|
||||||
|
export CGO_LDFLAGS="-Wl,-no_warn_duplicate_libraries"
|
||||||
|
fi
|
||||||
|
go build -tags "sqlite_fts5" -ldflags="${LDFLAGS}" \
|
||||||
|
-o WeKnora-lite ./cmd/server
|
||||||
|
|
||||||
|
- name: Package tarball
|
||||||
|
run: |
|
||||||
|
ARCHIVE="WeKnora-lite_${{ steps.ver.outputs.version }}_${{ matrix.goos }}_${{ matrix.goarch }}"
|
||||||
|
mkdir -p "${ARCHIVE}/web"
|
||||||
|
cp WeKnora-lite "${ARCHIVE}/"
|
||||||
|
cp -r web/* "${ARCHIVE}/web/"
|
||||||
|
cp .env.lite.example "${ARCHIVE}/"
|
||||||
|
cp docs/LITE.md "${ARCHIVE}/README.md"
|
||||||
|
if [ -d config ]; then
|
||||||
|
cp -r config "${ARCHIVE}/config"
|
||||||
|
fi
|
||||||
|
if [ -d migrations/sqlite ]; then
|
||||||
|
mkdir -p "${ARCHIVE}/migrations/sqlite"
|
||||||
|
cp -r migrations/sqlite/* "${ARCHIVE}/migrations/sqlite/"
|
||||||
|
fi
|
||||||
|
if [ -f deploy/weknora-lite.service ]; then
|
||||||
|
cp deploy/weknora-lite.service "${ARCHIVE}/"
|
||||||
|
fi
|
||||||
|
tar czf "${ARCHIVE}.tar.gz" "${ARCHIVE}"
|
||||||
|
shasum -a 256 "${ARCHIVE}.tar.gz" > "${ARCHIVE}.tar.gz.sha256"
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
|
path: |
|
||||||
|
WeKnora-lite_*.tar.gz
|
||||||
|
WeKnora-lite_*.tar.gz.sha256
|
||||||
|
retention-days: 3
|
||||||
|
|
||||||
|
# ── 3. Create GitHub Release ──
|
||||||
|
release:
|
||||||
|
needs: build-binary
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
pattern: release-*
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Resolve version
|
||||||
|
id: ver
|
||||||
|
run: |
|
||||||
|
if [ -n "${{ inputs.tag }}" ]; then
|
||||||
|
VERSION="${{ inputs.tag }}"
|
||||||
|
else
|
||||||
|
VERSION="${GITHUB_REF#refs/tags/}"
|
||||||
|
fi
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Generate release notes
|
||||||
|
id: notes
|
||||||
|
run: |
|
||||||
|
cat > notes.md << 'NOTES'
|
||||||
|
## WeKnora Lite ${{ steps.ver.outputs.version }}
|
||||||
|
|
||||||
|
单二进制部署,零外部依赖(无需 Docker / PostgreSQL / Redis)。
|
||||||
|
|
||||||
|
### 快速开始
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 解压
|
||||||
|
tar xzf WeKnora-lite_${{ steps.ver.outputs.version }}_<os>_<arch>.tar.gz
|
||||||
|
cd WeKnora-lite_${{ steps.ver.outputs.version }}_<os>_<arch>
|
||||||
|
|
||||||
|
# 2. 配置
|
||||||
|
cp .env.lite.example .env.lite
|
||||||
|
# 编辑 .env.lite,至少确认 OLLAMA_BASE_URL 正确
|
||||||
|
|
||||||
|
# 3. 启动 Ollama(如尚未运行)
|
||||||
|
ollama serve &
|
||||||
|
ollama pull qwen2.5:7b
|
||||||
|
ollama pull nomic-embed-text
|
||||||
|
|
||||||
|
# 4. 运行
|
||||||
|
set -a && source .env.lite && set +a
|
||||||
|
./WeKnora-lite
|
||||||
|
# 访问 http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
### 平台支持
|
||||||
|
|
||||||
|
| 文件 | 平台 |
|
||||||
|
|------|------|
|
||||||
|
| `WeKnora-lite_*_linux_amd64.tar.gz` | Linux x86_64 |
|
||||||
|
| `WeKnora-lite_*_linux_arm64.tar.gz` | Linux ARM64 |
|
||||||
|
| `WeKnora-lite_*_darwin_amd64.tar.gz` | macOS Intel |
|
||||||
|
| `WeKnora-lite_*_darwin_arm64.tar.gz` | macOS Apple Silicon |
|
||||||
|
|
||||||
|
详细文档见 [LITE.md](docs/LITE.md)。
|
||||||
|
NOTES
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
gh release create "${{ steps.ver.outputs.version }}" \
|
||||||
|
--title "WeKnora Lite ${{ steps.ver.outputs.version }}" \
|
||||||
|
--notes-file notes.md \
|
||||||
|
WeKnora-lite_*.tar.gz \
|
||||||
|
WeKnora-lite_*.tar.gz.sha256
|
||||||
|
|
||||||
|
# ── 4. Update Homebrew Formula ──
|
||||||
|
update-homebrew:
|
||||||
|
needs: release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: main
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Resolve version
|
||||||
|
id: ver
|
||||||
|
run: |
|
||||||
|
if [ -n "${{ inputs.tag }}" ]; then
|
||||||
|
VERSION="${{ inputs.tag }}"
|
||||||
|
else
|
||||||
|
VERSION="${GITHUB_REF#refs/tags/}"
|
||||||
|
fi
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Wait for release assets to be available
|
||||||
|
run: sleep 15
|
||||||
|
|
||||||
|
- name: Update Formula
|
||||||
|
run: ./scripts/update-homebrew-formula.sh "${{ steps.ver.outputs.version }}"
|
||||||
|
|
||||||
|
- name: Commit and push
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git add Formula/weknora-lite.rb
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
echo "No changes to Formula"
|
||||||
|
else
|
||||||
|
git commit -m "formula: update weknora-lite to ${{ steps.ver.outputs.version }}"
|
||||||
|
git push origin main
|
||||||
|
fi
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
class WeknoraLite < Formula
|
||||||
|
desc "Knowledge base management system — single-binary Lite edition"
|
||||||
|
homepage "https://github.com/Tencent/WeKnora"
|
||||||
|
version "0.0.0"
|
||||||
|
license "Apache-2.0"
|
||||||
|
|
||||||
|
on_macos do
|
||||||
|
on_arm do
|
||||||
|
url "https://github.com/Tencent/WeKnora/releases/download/v#{version}/WeKnora-lite_v#{version}_darwin_arm64.tar.gz"
|
||||||
|
sha256 "PLACEHOLDER"
|
||||||
|
end
|
||||||
|
on_intel do
|
||||||
|
url "https://github.com/Tencent/WeKnora/releases/download/v#{version}/WeKnora-lite_v#{version}_darwin_amd64.tar.gz"
|
||||||
|
sha256 "PLACEHOLDER"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
on_linux do
|
||||||
|
on_arm do
|
||||||
|
url "https://github.com/Tencent/WeKnora/releases/download/v#{version}/WeKnora-lite_v#{version}_linux_arm64.tar.gz"
|
||||||
|
sha256 "PLACEHOLDER"
|
||||||
|
end
|
||||||
|
on_intel do
|
||||||
|
url "https://github.com/Tencent/WeKnora/releases/download/v#{version}/WeKnora-lite_v#{version}_linux_amd64.tar.gz"
|
||||||
|
sha256 "PLACEHOLDER"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def install
|
||||||
|
libexec.install "WeKnora-lite"
|
||||||
|
pkgshare.install "web" if File.directory?("web")
|
||||||
|
pkgshare.install "config" if File.directory?("config")
|
||||||
|
pkgshare.install ".env.lite.example"
|
||||||
|
doc.install "README.md"
|
||||||
|
pkgshare.install "migrations" if File.directory?("migrations")
|
||||||
|
|
||||||
|
(bin/"weknora-lite").write <<~SH
|
||||||
|
#!/bin/bash
|
||||||
|
CONFIG_DIR="${WEKNORA_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/weknora}"
|
||||||
|
DATA_DIR="${WEKNORA_DATA_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/weknora}"
|
||||||
|
|
||||||
|
mkdir -p "$DATA_DIR/files" "$CONFIG_DIR/config" 2>/dev/null
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG_DIR/config/config.yaml" ]; then
|
||||||
|
cp -r "#{pkgshare}/config/" "$CONFIG_DIR/config/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$CONFIG_DIR/migrations" ] && [ -d "#{pkgshare}/migrations" ]; then
|
||||||
|
ln -sf "#{pkgshare}/migrations" "$CONFIG_DIR/migrations"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG_DIR/.env.lite" ]; then
|
||||||
|
cp "#{pkgshare}/.env.lite.example" "$CONFIG_DIR/.env.lite"
|
||||||
|
sed -i '' "s|DB_PATH=.*|DB_PATH=$DATA_DIR/weknora.db|" "$CONFIG_DIR/.env.lite"
|
||||||
|
sed -i '' "s|LOCAL_STORAGE_BASE_DIR=.*|LOCAL_STORAGE_BASE_DIR=$DATA_DIR/files|" "$CONFIG_DIR/.env.lite"
|
||||||
|
rm -f "$CONFIG_DIR/.env.lite-e"
|
||||||
|
echo ""
|
||||||
|
echo "已创建配置文件: $CONFIG_DIR/.env.lite"
|
||||||
|
echo "请根据需要编辑(如修改 LLM 地址、安全密钥等)。"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -a
|
||||||
|
source "$CONFIG_DIR/.env.lite"
|
||||||
|
set +a
|
||||||
|
|
||||||
|
export DB_PATH="${DB_PATH:-$DATA_DIR/weknora.db}"
|
||||||
|
export LOCAL_STORAGE_BASE_DIR="${LOCAL_STORAGE_BASE_DIR:-$DATA_DIR/files}"
|
||||||
|
export WEKNORA_WEB_DIR="${WEKNORA_WEB_DIR:-#{pkgshare}/web}"
|
||||||
|
|
||||||
|
cd "$CONFIG_DIR"
|
||||||
|
exec "#{libexec}/WeKnora-lite" "$@"
|
||||||
|
SH
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_install
|
||||||
|
(var/"weknora").mkpath
|
||||||
|
(var/"log").mkpath
|
||||||
|
end
|
||||||
|
|
||||||
|
service do
|
||||||
|
run [bin/"weknora-lite"]
|
||||||
|
keep_alive true
|
||||||
|
working_dir var/"weknora"
|
||||||
|
log_path var/"log/weknora-lite.log"
|
||||||
|
error_log_path var/"log/weknora-lite.log"
|
||||||
|
end
|
||||||
|
|
||||||
|
def caveats
|
||||||
|
<<~EOS
|
||||||
|
前台运行:
|
||||||
|
weknora-lite
|
||||||
|
|
||||||
|
后台服务(推荐):
|
||||||
|
brew services start weknora-lite # 启动并开机自启
|
||||||
|
brew services stop weknora-lite # 停止
|
||||||
|
brew services restart weknora-lite # 重启
|
||||||
|
brew services info weknora-lite # 查看状态
|
||||||
|
|
||||||
|
日志:
|
||||||
|
#{var}/log/weknora-lite.log
|
||||||
|
|
||||||
|
首次运行会自动创建配置文件:
|
||||||
|
~/.config/weknora/.env.lite
|
||||||
|
|
||||||
|
数据存储在:
|
||||||
|
~/.local/share/weknora/
|
||||||
|
|
||||||
|
如需修改配置(LLM 服务地址、安全密钥等):
|
||||||
|
$EDITOR ~/.config/weknora/.env.lite
|
||||||
|
brew services restart weknora-lite
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
test do
|
||||||
|
assert_predicate bin/"weknora-lite", :executable?
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
.PHONY: help build run test clean docker-build-app docker-build-docreader docker-build-frontend docker-build-all docker-run migrate-up migrate-down docker-restart docker-stop start-all stop-all start-ollama stop-ollama build-images build-images-app build-images-docreader build-images-frontend clean-images check-env list-containers pull-images show-platform dev-start dev-stop dev-restart dev-logs dev-status dev-app dev-frontend docs install-swagger
|
.PHONY: help build run test clean docker-build-app docker-build-docreader docker-build-frontend docker-build-all docker-run migrate-up migrate-down docker-restart docker-stop start-all stop-all start-ollama stop-ollama build-images build-images-app build-images-docreader build-images-frontend clean-images check-env list-containers pull-images show-platform dev-start dev-stop dev-restart dev-logs dev-status dev-app dev-frontend docs install-swagger build-lite run-lite package-lite
|
||||||
|
|
||||||
# Show help
|
# Show help
|
||||||
help:
|
help:
|
||||||
@@ -56,6 +56,11 @@ help:
|
|||||||
@echo " dev-status 查看开发环境状态"
|
@echo " dev-status 查看开发环境状态"
|
||||||
@echo " dev-app 启动后端应用(本地运行,需先运行 dev-start)"
|
@echo " dev-app 启动后端应用(本地运行,需先运行 dev-start)"
|
||||||
@echo " dev-frontend 启动前端(本地运行,需先运行 dev-start)"
|
@echo " dev-frontend 启动前端(本地运行,需先运行 dev-start)"
|
||||||
|
@echo ""
|
||||||
|
@echo "Lite 模式(零外部依赖):"
|
||||||
|
@echo " build-lite 构建 Lite 版本(先构建前端到 web/,再构建 Go;SKIP_FRONTEND=1 跳过前端)"
|
||||||
|
@echo " run-lite 构建并启动 Lite 版本"
|
||||||
|
@echo " package-lite 构建并打包 Lite 发行包(tarball)"
|
||||||
|
|
||||||
# Go related variables
|
# Go related variables
|
||||||
BINARY_NAME=WeKnora
|
BINARY_NAME=WeKnora
|
||||||
@@ -231,6 +236,35 @@ build-prod:
|
|||||||
LDFLAGS="-X 'github.com/Tencent/WeKnora/internal/handler.Version=$$VERSION' -X 'github.com/Tencent/WeKnora/internal/handler.Edition=standard' -X 'github.com/Tencent/WeKnora/internal/handler.CommitID=$$COMMIT_ID' -X 'github.com/Tencent/WeKnora/internal/handler.BuildTime=$$BUILD_TIME' -X 'github.com/Tencent/WeKnora/internal/handler.GoVersion=$$GO_VERSION' -X 'google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn'"; \
|
LDFLAGS="-X 'github.com/Tencent/WeKnora/internal/handler.Version=$$VERSION' -X 'github.com/Tencent/WeKnora/internal/handler.Edition=standard' -X 'github.com/Tencent/WeKnora/internal/handler.CommitID=$$COMMIT_ID' -X 'github.com/Tencent/WeKnora/internal/handler.BuildTime=$$BUILD_TIME' -X 'github.com/Tencent/WeKnora/internal/handler.GoVersion=$$GO_VERSION' -X 'google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn'"; \
|
||||||
go build -ldflags="-w -s $$LDFLAGS" -o $(BINARY_NAME) $(MAIN_PATH)
|
go build -ldflags="-w -s $$LDFLAGS" -o $(BINARY_NAME) $(MAIN_PATH)
|
||||||
|
|
||||||
|
# Build Lite version (single binary, SQLite + in-memory queue)
|
||||||
|
# 会先构建前端到 web/,再构建 Go 二进制;SKIP_FRONTEND=1 可跳过前端
|
||||||
|
build-lite:
|
||||||
|
@if [ -f frontend/package.json ] && [ "$${SKIP_FRONTEND:-}" != "1" ]; then \
|
||||||
|
echo ">> Building frontend for Lite..."; \
|
||||||
|
(cd frontend && npm ci --prefer-offline && npm run build) && \
|
||||||
|
rm -rf web && cp -r frontend/dist web; \
|
||||||
|
elif [ "$${SKIP_FRONTEND:-}" = "1" ]; then \
|
||||||
|
echo ">> Skipping frontend (SKIP_FRONTEND=1)"; \
|
||||||
|
else \
|
||||||
|
echo ">> No frontend/package.json, skipping frontend"; \
|
||||||
|
fi
|
||||||
|
export EDITION=lite; \
|
||||||
|
eval "$$(./scripts/get_version.sh env)"; \
|
||||||
|
LDFLAGS="$$(./scripts/get_version.sh ldflags)"; \
|
||||||
|
CGO_ENABLED=1 \
|
||||||
|
CGO_CFLAGS="-Wno-deprecated-declarations" \
|
||||||
|
CGO_LDFLAGS="-Wl,-no_warn_duplicate_libraries" \
|
||||||
|
go build -tags "sqlite_fts5" -ldflags="-w -s $$LDFLAGS" -o $(BINARY_NAME)-lite $(MAIN_PATH)
|
||||||
|
|
||||||
|
# Run Lite version with .env.lite defaults
|
||||||
|
run-lite: build-lite
|
||||||
|
@if [ ! -f .env.lite ]; then echo "Error: .env.lite not found"; exit 1; fi
|
||||||
|
@set -a && . ./.env.lite && set +a && ./$(BINARY_NAME)-lite
|
||||||
|
|
||||||
|
# Package Lite version into distributable tarball
|
||||||
|
package-lite:
|
||||||
|
./scripts/package-lite.sh
|
||||||
|
|
||||||
download_spatial:
|
download_spatial:
|
||||||
go run cmd/download/duckdb/duckdb.go
|
go run cmd/download/duckdb/duckdb.go
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=WeKnora Lite - Knowledge Base Management System
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=weknora
|
||||||
|
Group=weknora
|
||||||
|
WorkingDirectory=/opt/weknora
|
||||||
|
EnvironmentFile=/opt/weknora/.env.lite
|
||||||
|
ExecStart=/opt/weknora/WeKnora-lite
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
LimitNOFILE=65536
|
||||||
|
|
||||||
|
# Security hardening
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=true
|
||||||
|
ReadWritePaths=/opt/weknora/data
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
+165
@@ -0,0 +1,165 @@
|
|||||||
|
# WeKnora Lite
|
||||||
|
|
||||||
|
零外部依赖的单二进制部署模式。无需 Docker、PostgreSQL、Redis,适合快速体验和小规模私有部署。
|
||||||
|
|
||||||
|
## 架构
|
||||||
|
|
||||||
|
| 组件 | 标准版 | Lite 版 |
|
||||||
|
|------|--------|---------|
|
||||||
|
| 数据库 | PostgreSQL | SQLite (WAL) |
|
||||||
|
| 向量检索 | pgvector / Qdrant / ES | sqlite-vec (vec0) |
|
||||||
|
| 关键词检索 | ParadeDB BM25 / ES | SQLite FTS5 |
|
||||||
|
| 消息队列 | Redis + Asynq | 内存 SyncTaskExecutor |
|
||||||
|
| 会话存储 | Redis | 内存 |
|
||||||
|
| 流管理 | Redis / 内存 | 内存 |
|
||||||
|
| 文件存储 | MinIO / COS / 本地 | 本地 |
|
||||||
|
| 文档解析 | DocReader (gRPC) | 不可用(文本/段落导入可用)|
|
||||||
|
| 前端 | Nginx 容器 | Go 内置静态文件服务 |
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 方式一:Homebrew 安装(macOS / Linux,推荐)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew tap Tencent/weknora https://github.com/Tencent/WeKnora
|
||||||
|
brew install weknora-lite
|
||||||
|
```
|
||||||
|
|
||||||
|
安装完成后,推荐使用 **brew services** 以后台服务方式运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew services start weknora-lite # 启动服务(开机自动启动)
|
||||||
|
brew services info weknora-lite # 查看运行状态
|
||||||
|
# 首次启动自动创建配置文件 ~/.config/weknora/.env.lite
|
||||||
|
# 数据存储在 ~/.local/share/weknora/
|
||||||
|
# 访问 http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
常用服务管理命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew services stop weknora-lite # 停止服务
|
||||||
|
brew services restart weknora-lite # 重启服务(修改配置后需重启)
|
||||||
|
brew services info weknora-lite # 查看状态
|
||||||
|
```
|
||||||
|
|
||||||
|
日志位于 `$(brew --prefix)/var/log/weknora-lite.log`。
|
||||||
|
|
||||||
|
也可以前台直接运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
weknora-lite
|
||||||
|
```
|
||||||
|
|
||||||
|
如需修改配置(LLM 服务地址、安全密钥等):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$EDITOR ~/.config/weknora/.env.lite
|
||||||
|
brew services restart weknora-lite # 修改配置后重启生效
|
||||||
|
```
|
||||||
|
|
||||||
|
> **LLM 服务**:WeKnora Lite 需要一个 OpenAI 兼容的 LLM 服务来提供对话和 Embedding 能力。
|
||||||
|
> 可以使用 [Ollama](https://ollama.com/)(本地)、通义千问、OpenAI 等任何兼容服务,
|
||||||
|
> 在配置文件中设置对应的地址和 API Key 即可。
|
||||||
|
|
||||||
|
### 方式二:下载预编译包
|
||||||
|
|
||||||
|
从 [GitHub Releases](https://github.com/Tencent/WeKnora/releases) 下载对应平台的 tarball:
|
||||||
|
|
||||||
|
| 文件 | 平台 |
|
||||||
|
|------|------|
|
||||||
|
| `WeKnora-lite_*_linux_amd64.tar.gz` | Linux x86_64 |
|
||||||
|
| `WeKnora-lite_*_linux_arm64.tar.gz` | Linux ARM64 |
|
||||||
|
| `WeKnora-lite_*_darwin_amd64.tar.gz` | macOS Intel |
|
||||||
|
| `WeKnora-lite_*_darwin_arm64.tar.gz` | macOS Apple Silicon |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 解压
|
||||||
|
tar xzf WeKnora-lite_v0.2.0_darwin_arm64.tar.gz
|
||||||
|
cd WeKnora-lite_v0.2.0_darwin_arm64
|
||||||
|
|
||||||
|
# 2. 配置
|
||||||
|
cp .env.lite.example .env.lite
|
||||||
|
# 编辑 .env.lite,配置 LLM 服务地址和安全密钥
|
||||||
|
|
||||||
|
# 3. 运行
|
||||||
|
set -a && source .env.lite && set +a
|
||||||
|
./WeKnora-lite
|
||||||
|
# 访问 http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式三:从源码构建
|
||||||
|
|
||||||
|
前置条件:Go 1.22+(需要 CGO)、C 编译器 (gcc/clang)、Node.js 22+(前端构建)。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make run-lite
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置
|
||||||
|
|
||||||
|
Lite 模式通过 `.env.lite` 文件配置(模板见 `.env.lite.example`)。关键环境变量:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DB_DRIVER=sqlite # 使用 SQLite
|
||||||
|
DB_PATH=./data/weknora.db # 数据库文件路径
|
||||||
|
RETRIEVE_DRIVER=sqlite # SQLite 检索引擎 (FTS5 + sqlite-vec)
|
||||||
|
STORAGE_TYPE=local # 本地文件存储
|
||||||
|
LOCAL_STORAGE_BASE_DIR=./data/files
|
||||||
|
STREAM_MANAGER_TYPE=memory # 内存流管理
|
||||||
|
# REDIS_ADDR= # 留空 = 不使用 Redis
|
||||||
|
OLLAMA_BASE_URL=http://127.0.0.1:11434
|
||||||
|
```
|
||||||
|
|
||||||
|
完整配置参见 [.env.lite.example](../.env.lite.example)。
|
||||||
|
|
||||||
|
## 后台运行
|
||||||
|
|
||||||
|
### Homebrew 用户(macOS / Linux)
|
||||||
|
|
||||||
|
Homebrew 安装后直接使用 `brew services` 管理,详见上方「快速开始 → 方式一」。
|
||||||
|
|
||||||
|
### Linux systemd(tarball 安装)
|
||||||
|
|
||||||
|
tarball 中附带 `weknora-lite.service` 模板,按需修改路径后安装:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 创建用户和目录
|
||||||
|
sudo useradd -r -s /sbin/nologin weknora
|
||||||
|
sudo mkdir -p /opt/weknora/data
|
||||||
|
sudo cp WeKnora-lite web/ .env.lite /opt/weknora/
|
||||||
|
sudo chown -R weknora:weknora /opt/weknora
|
||||||
|
|
||||||
|
# 安装并启动服务
|
||||||
|
sudo cp weknora-lite.service /etc/systemd/system/
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now weknora-lite
|
||||||
|
|
||||||
|
# 管理
|
||||||
|
sudo systemctl status weknora-lite # 查看状态
|
||||||
|
sudo journalctl -u weknora-lite -f # 查看日志
|
||||||
|
```
|
||||||
|
|
||||||
|
## 功能限制
|
||||||
|
|
||||||
|
与标准版相比,Lite 版有以下限制:
|
||||||
|
|
||||||
|
- **文档解析**:不支持文件上传和 URL 导入的自动解析(PDF/Word/Excel 等)。可使用文本和段落方式手动导入。
|
||||||
|
- **向量检索**:sqlite-vec 使用精确 KNN(非近似),适合 10 万条以下的小规模数据集。
|
||||||
|
- **并发**:SQLite 单写者模型,高并发写入场景下性能不如 PostgreSQL。
|
||||||
|
- **任务队列**:无持久化队列,进程重启后未完成的异步任务会丢失。
|
||||||
|
- **知识图谱**:默认禁用 (`NEO4J_ENABLE=false`)。
|
||||||
|
- **Agent Skills 沙箱**:默认禁用 (`WEKNORA_SANDBOX_MODE=disabled`)。
|
||||||
|
|
||||||
|
## 数据目录
|
||||||
|
|
||||||
|
默认所有数据存储在 `./data/` 目录下:
|
||||||
|
|
||||||
|
```
|
||||||
|
data/
|
||||||
|
├── weknora.db # SQLite 数据库
|
||||||
|
├── weknora.db-wal # WAL 日志
|
||||||
|
└── files/ # 上传文件
|
||||||
|
```
|
||||||
|
|
||||||
|
备份只需复制整个 `data/` 目录。
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
<div class="logo_row" v-if="!uiStore.sidebarCollapsed">
|
<div class="logo_row" v-if="!uiStore.sidebarCollapsed">
|
||||||
<div class="logo_box" @click="router.push('/platform/knowledge-bases')" style="cursor: pointer;">
|
<div class="logo_box" @click="router.push('/platform/knowledge-bases')" style="cursor: pointer;">
|
||||||
<img class="logo" src="@/assets/img/weknora.png" alt="">
|
<img class="logo" src="@/assets/img/weknora.png" alt="">
|
||||||
|
<span v-if="isLiteEdition" class="lite-badge">Lite</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar-toggle"
|
<div class="sidebar-toggle"
|
||||||
@click="uiStore.toggleSidebar"
|
@click="uiStore.toggleSidebar"
|
||||||
@@ -137,6 +138,7 @@ import { MessagePlugin, DialogPlugin, Icon as TIcon } from "tdesign-vue-next";
|
|||||||
import UserMenu from '@/components/UserMenu.vue';
|
import UserMenu from '@/components/UserMenu.vue';
|
||||||
import TenantSelector from '@/components/TenantSelector.vue';
|
import TenantSelector from '@/components/TenantSelector.vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { getSystemInfo } from '@/api/system';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const usemenuStore = useMenuStore();
|
const usemenuStore = useMenuStore();
|
||||||
@@ -157,6 +159,7 @@ const hasMore = computed(() => currentPage.value < totalPages.value);
|
|||||||
type MenuItem = { title: string; icon: string; path: string; childrenPath?: string; children?: any[] };
|
type MenuItem = { title: string; icon: string; path: string; childrenPath?: string; children?: any[] };
|
||||||
const { menuArr } = storeToRefs(usemenuStore);
|
const { menuArr } = storeToRefs(usemenuStore);
|
||||||
let activeSubmenu = ref<string>('');
|
let activeSubmenu = ref<string>('');
|
||||||
|
const isLiteEdition = ref(false);
|
||||||
|
|
||||||
// 批量管理状态
|
// 批量管理状态
|
||||||
const batchMode = ref(false)
|
const batchMode = ref(false)
|
||||||
@@ -539,6 +542,10 @@ onMounted(async () => {
|
|||||||
currentSecondpath.value = `chat/${route.params.chatid}`;
|
currentSecondpath.value = `chat/${route.params.chatid}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSystemInfo().then(res => {
|
||||||
|
isLiteEdition.value = res.data?.edition === 'lite'
|
||||||
|
}).catch(() => {})
|
||||||
|
|
||||||
// 初始化知识库信息
|
// 初始化知识库信息
|
||||||
const kbId = (route.params as any)?.kbId as string
|
const kbId = (route.params as any)?.kbId as string
|
||||||
if (kbId && isInKnowledgeBase.value) {
|
if (kbId && isInKnowledgeBase.value) {
|
||||||
@@ -836,6 +843,19 @@ const onDragHandleMouseDown = (e: MouseEvent) => {
|
|||||||
width: 134px;
|
width: 134px;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
.lite-badge {
|
||||||
|
margin-left: 4px;
|
||||||
|
padding: 1px 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #07c05f;
|
||||||
|
background: #07c05f1a;
|
||||||
|
border: 1px solid #07c05f40;
|
||||||
|
border-radius: 4px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo_img {
|
.logo_img {
|
||||||
|
|||||||
@@ -33,11 +33,11 @@
|
|||||||
{{ systemInfo?.version || $t('system.unknown') }}
|
{{ systemInfo?.version || $t('system.unknown') }}
|
||||||
<t-tag
|
<t-tag
|
||||||
v-if="systemInfo?.edition"
|
v-if="systemInfo?.edition"
|
||||||
theme="default"
|
:theme="systemInfo.edition === 'lite' ? 'primary' : 'default'"
|
||||||
variant="light"
|
variant="light"
|
||||||
size="small"
|
size="small"
|
||||||
style="margin-left: 8px;"
|
style="margin-left: 8px;"
|
||||||
>{{ systemInfo.edition || 'Standard' }}</t-tag>
|
>{{ systemInfo.edition === 'lite' ? 'Lite' : 'Standard' }}</t-tag>
|
||||||
<span v-if="systemInfo?.commit_id" class="commit-info">
|
<span v-if="systemInfo?.commit_id" class="commit-info">
|
||||||
({{ systemInfo.commit_id }})
|
({{ systemInfo.commit_id }})
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Executable
+97
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#
|
||||||
|
# 本地构建 + 打包 WeKnora Lite 发行包
|
||||||
|
#
|
||||||
|
# 用法:
|
||||||
|
# ./scripts/package-lite.sh # 自动检测版本
|
||||||
|
# ./scripts/package-lite.sh v0.2.0 # 指定版本号
|
||||||
|
# SKIP_FRONTEND=1 ./scripts/package-lite.sh # 跳过前端构建(使用已有 web/)
|
||||||
|
#
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||||
|
cd "${ROOT_DIR}"
|
||||||
|
|
||||||
|
# Resolve version
|
||||||
|
if [ -n "${1:-}" ]; then
|
||||||
|
VERSION="$1"
|
||||||
|
elif command -v git >/dev/null 2>&1; then
|
||||||
|
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "dev")
|
||||||
|
else
|
||||||
|
VERSION="dev"
|
||||||
|
fi
|
||||||
|
|
||||||
|
GOOS=$(go env GOOS)
|
||||||
|
GOARCH=$(go env GOARCH)
|
||||||
|
ARCHIVE="WeKnora-lite_${VERSION}_${GOOS}_${GOARCH}"
|
||||||
|
DIST_DIR="dist/${ARCHIVE}"
|
||||||
|
|
||||||
|
echo "=== WeKnora Lite Packager ==="
|
||||||
|
echo " Version : ${VERSION}"
|
||||||
|
echo " Platform: ${GOOS}/${GOARCH}"
|
||||||
|
echo " Output : dist/${ARCHIVE}.tar.gz"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── Step 1: Build frontend (if not skipped) ──
|
||||||
|
if [ "${SKIP_FRONTEND:-}" != "1" ]; then
|
||||||
|
if [ -f frontend/package.json ]; then
|
||||||
|
echo ">> Building frontend..."
|
||||||
|
(cd frontend && npm ci --prefer-offline && npm run build)
|
||||||
|
rm -rf web
|
||||||
|
cp -r frontend/dist web
|
||||||
|
else
|
||||||
|
echo ">> No frontend/package.json found, skipping frontend build"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f web/index.html ]; then
|
||||||
|
echo "WARNING: web/index.html not found — package will not include frontend"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Step 2: Build Go binary ──
|
||||||
|
echo ">> Building WeKnora-lite binary..."
|
||||||
|
export EDITION=lite
|
||||||
|
eval "$(./scripts/get_version.sh env)"
|
||||||
|
LDFLAGS="-w -s $(./scripts/get_version.sh ldflags)"
|
||||||
|
export CGO_CFLAGS="-Wno-deprecated-declarations"
|
||||||
|
if [ "$(uname)" = "Darwin" ]; then
|
||||||
|
export CGO_LDFLAGS="-Wl,-no_warn_duplicate_libraries"
|
||||||
|
fi
|
||||||
|
CGO_ENABLED=1 go build -tags "sqlite_fts5" -ldflags="${LDFLAGS}" \
|
||||||
|
-o WeKnora-lite ./cmd/server
|
||||||
|
|
||||||
|
# ── Step 3: Assemble package ──
|
||||||
|
echo ">> Assembling package..."
|
||||||
|
rm -rf "${DIST_DIR}"
|
||||||
|
mkdir -p "${DIST_DIR}/web"
|
||||||
|
|
||||||
|
cp WeKnora-lite "${DIST_DIR}/"
|
||||||
|
if [ -d web ] && [ -f web/index.html ]; then
|
||||||
|
cp -r web/* "${DIST_DIR}/web/"
|
||||||
|
fi
|
||||||
|
cp .env.lite.example "${DIST_DIR}/"
|
||||||
|
cp docs/LITE.md "${DIST_DIR}/README.md"
|
||||||
|
if [ -d config ]; then
|
||||||
|
cp -r config "${DIST_DIR}/config"
|
||||||
|
fi
|
||||||
|
if [ -d migrations/sqlite ]; then
|
||||||
|
mkdir -p "${DIST_DIR}/migrations/sqlite"
|
||||||
|
cp -r migrations/sqlite/* "${DIST_DIR}/migrations/sqlite/"
|
||||||
|
fi
|
||||||
|
if [ -f deploy/weknora-lite.service ]; then
|
||||||
|
cp deploy/weknora-lite.service "${DIST_DIR}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Step 4: Create tarball ──
|
||||||
|
echo ">> Creating tarball..."
|
||||||
|
(cd dist && tar czf "${ARCHIVE}.tar.gz" "${ARCHIVE}")
|
||||||
|
(cd dist && shasum -a 256 "${ARCHIVE}.tar.gz" > "${ARCHIVE}.tar.gz.sha256")
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Done ==="
|
||||||
|
echo " dist/${ARCHIVE}.tar.gz"
|
||||||
|
echo " dist/${ARCHIVE}.tar.gz.sha256"
|
||||||
|
SIZE=$(du -h "dist/${ARCHIVE}.tar.gz" | cut -f1)
|
||||||
|
echo " Size: ${SIZE}"
|
||||||
Executable
+178
@@ -0,0 +1,178 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#
|
||||||
|
# 本地测试 Homebrew Formula
|
||||||
|
#
|
||||||
|
# 流程:打包 → 创建本地 tap → 写入 Formula → brew install → 验证
|
||||||
|
#
|
||||||
|
# 用法:
|
||||||
|
# ./scripts/test-homebrew.sh # 完整测试(含前端构建)
|
||||||
|
# SKIP_FRONTEND=1 ./scripts/test-homebrew.sh # 跳过前端构建
|
||||||
|
# SKIP_BUILD=1 ./scripts/test-homebrew.sh # 跳过构建(使用已有 tarball)
|
||||||
|
#
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||||
|
cd "${ROOT_DIR}"
|
||||||
|
|
||||||
|
TAP_NAME="weknora/test"
|
||||||
|
FORMULA_NAME="weknora-lite-test"
|
||||||
|
VERSION="test"
|
||||||
|
GOOS=$(go env GOOS)
|
||||||
|
GOARCH=$(go env GOARCH)
|
||||||
|
ARCHIVE="WeKnora-lite_${VERSION}_${GOOS}_${GOARCH}"
|
||||||
|
TARBALL="${ROOT_DIR}/dist/${ARCHIVE}.tar.gz"
|
||||||
|
|
||||||
|
# ── Step 1: Build package ──
|
||||||
|
if [ "${SKIP_BUILD:-}" != "1" ]; then
|
||||||
|
echo "=== Step 1: Build local package ==="
|
||||||
|
SKIP_FRONTEND="${SKIP_FRONTEND:-0}" ./scripts/package-lite.sh "${VERSION}"
|
||||||
|
else
|
||||||
|
echo "=== Step 1: Skipped (SKIP_BUILD=1) ==="
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "${TARBALL}" ]; then
|
||||||
|
echo "Error: tarball not found at ${TARBALL}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SHA=$(shasum -a 256 "${TARBALL}" | awk '{print $1}')
|
||||||
|
echo ""
|
||||||
|
echo " Tarball: ${TARBALL}"
|
||||||
|
echo " SHA256: ${SHA}"
|
||||||
|
|
||||||
|
# ── Step 2: Create local tap ──
|
||||||
|
echo ""
|
||||||
|
echo "=== Step 2: Set up local tap ==="
|
||||||
|
|
||||||
|
# Create tap if it doesn't exist
|
||||||
|
TAP_DIR="$(brew --repository)/Library/Taps/weknora/homebrew-test"
|
||||||
|
if [ ! -d "${TAP_DIR}" ]; then
|
||||||
|
mkdir -p "${TAP_DIR}/Formula"
|
||||||
|
(cd "${TAP_DIR}" && git init -q && git commit --allow-empty -m "init" -q)
|
||||||
|
echo " Created tap: ${TAP_NAME}"
|
||||||
|
else
|
||||||
|
echo " Tap already exists: ${TAP_NAME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Step 3: Write Formula into tap ──
|
||||||
|
echo ""
|
||||||
|
echo "=== Step 3: Generate Formula ==="
|
||||||
|
|
||||||
|
cat > "${TAP_DIR}/Formula/${FORMULA_NAME}.rb" << RUBY
|
||||||
|
class WeknoraLiteTest < Formula
|
||||||
|
desc "WeKnora Lite (local test)"
|
||||||
|
homepage "https://github.com/Tencent/WeKnora"
|
||||||
|
version "${VERSION}"
|
||||||
|
license "Apache-2.0"
|
||||||
|
|
||||||
|
url "file://${TARBALL}"
|
||||||
|
sha256 "${SHA}"
|
||||||
|
|
||||||
|
def install
|
||||||
|
libexec.install "WeKnora-lite"
|
||||||
|
pkgshare.install "web" if File.directory?("web")
|
||||||
|
pkgshare.install "config" if File.directory?("config")
|
||||||
|
pkgshare.install ".env.lite.example"
|
||||||
|
if File.directory?("migrations")
|
||||||
|
pkgshare.install "migrations"
|
||||||
|
end
|
||||||
|
|
||||||
|
(bin/"weknora-lite-test").write <<~SH
|
||||||
|
#!/bin/bash
|
||||||
|
CONFIG_DIR="\\\${WEKNORA_CONFIG_DIR:-\\\${XDG_CONFIG_HOME:-\\\$HOME/.config}/weknora-test}"
|
||||||
|
DATA_DIR="\\\${WEKNORA_DATA_DIR:-\\\${XDG_DATA_HOME:-\\\$HOME/.local/share}/weknora-test}"
|
||||||
|
|
||||||
|
mkdir -p "\\\$DATA_DIR/files" "\\\$CONFIG_DIR/config" 2>/dev/null
|
||||||
|
|
||||||
|
if [ ! -f "\\\$CONFIG_DIR/config/config.yaml" ]; then
|
||||||
|
cp -r "#{pkgshare}/config/" "\\\$CONFIG_DIR/config/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "\\\$CONFIG_DIR/migrations" ] && [ -d "#{pkgshare}/migrations" ]; then
|
||||||
|
ln -sf "#{pkgshare}/migrations" "\\\$CONFIG_DIR/migrations"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "\\\$CONFIG_DIR/.env.lite" ]; then
|
||||||
|
cp "#{pkgshare}/.env.lite.example" "\\\$CONFIG_DIR/.env.lite"
|
||||||
|
sed -i'' -e "s|DB_PATH=.*|DB_PATH=\\\$DATA_DIR/weknora.db|" "\\\$CONFIG_DIR/.env.lite"
|
||||||
|
sed -i'' -e "s|LOCAL_STORAGE_BASE_DIR=.*|LOCAL_STORAGE_BASE_DIR=\\\$DATA_DIR/files|" "\\\$CONFIG_DIR/.env.lite"
|
||||||
|
echo ""
|
||||||
|
echo "已创建配置文件: \\\$CONFIG_DIR/.env.lite"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -a
|
||||||
|
source "\\\$CONFIG_DIR/.env.lite"
|
||||||
|
set +a
|
||||||
|
|
||||||
|
export DB_PATH="\\\${DB_PATH:-\\\$DATA_DIR/weknora.db}"
|
||||||
|
export LOCAL_STORAGE_BASE_DIR="\\\${LOCAL_STORAGE_BASE_DIR:-\\\$DATA_DIR/files}"
|
||||||
|
export WEKNORA_WEB_DIR="\\\${WEKNORA_WEB_DIR:-#{pkgshare}/web}"
|
||||||
|
|
||||||
|
cd "\\\$CONFIG_DIR"
|
||||||
|
exec "#{libexec}/WeKnora-lite" "\\\$@"
|
||||||
|
SH
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_install
|
||||||
|
(var/"weknora-test").mkpath
|
||||||
|
(var/"log").mkpath
|
||||||
|
end
|
||||||
|
|
||||||
|
service do
|
||||||
|
run [bin/"weknora-lite-test"]
|
||||||
|
keep_alive true
|
||||||
|
working_dir var/"weknora-test"
|
||||||
|
log_path var/"log/weknora-lite-test.log"
|
||||||
|
error_log_path var/"log/weknora-lite-test.log"
|
||||||
|
end
|
||||||
|
|
||||||
|
test do
|
||||||
|
assert_predicate bin/"weknora-lite-test", :executable?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
(cd "${TAP_DIR}" && git add -A && git commit -m "update formula" -q --allow-empty)
|
||||||
|
echo " Formula written to: ${TAP_DIR}/Formula/${FORMULA_NAME}.rb"
|
||||||
|
|
||||||
|
# ── Step 4: Install ──
|
||||||
|
echo ""
|
||||||
|
echo "=== Step 4: Install ==="
|
||||||
|
brew reinstall "${TAP_NAME}/${FORMULA_NAME}" 2>&1 || brew install "${TAP_NAME}/${FORMULA_NAME}"
|
||||||
|
|
||||||
|
# ── Step 5: Verify ──
|
||||||
|
echo ""
|
||||||
|
echo "=== Step 5: Verify ==="
|
||||||
|
echo ""
|
||||||
|
echo " which:"
|
||||||
|
which weknora-lite-test || true
|
||||||
|
echo ""
|
||||||
|
echo " Installed files:"
|
||||||
|
brew list "${TAP_NAME}/${FORMULA_NAME}"
|
||||||
|
echo ""
|
||||||
|
echo " Test paths (isolated from production):"
|
||||||
|
echo " Config: ~/.config/weknora-test/.env.lite"
|
||||||
|
echo " Data: ~/.local/share/weknora-test/"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Done ==="
|
||||||
|
echo ""
|
||||||
|
echo "前台运行:"
|
||||||
|
echo " weknora-lite-test"
|
||||||
|
echo ""
|
||||||
|
echo "后台服务:"
|
||||||
|
echo " brew services start ${TAP_NAME}/${FORMULA_NAME}"
|
||||||
|
echo " brew services info ${TAP_NAME}/${FORMULA_NAME}"
|
||||||
|
echo " brew services stop ${TAP_NAME}/${FORMULA_NAME}"
|
||||||
|
echo ""
|
||||||
|
echo "日志:"
|
||||||
|
echo " $(brew --prefix)/var/log/weknora-lite-test.log"
|
||||||
|
echo ""
|
||||||
|
echo "卸载测试:"
|
||||||
|
echo " brew services stop ${FORMULA_NAME} 2>/dev/null"
|
||||||
|
echo " brew uninstall ${FORMULA_NAME}"
|
||||||
|
echo " brew untap ${TAP_NAME}"
|
||||||
|
echo " rm -rf ~/.config/weknora-test ~/.local/share/weknora-test"
|
||||||
Executable
+74
@@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#
|
||||||
|
# 更新 Homebrew Formula 中的版本号和 sha256
|
||||||
|
#
|
||||||
|
# 用法:
|
||||||
|
# ./scripts/update-homebrew-formula.sh v0.2.0
|
||||||
|
#
|
||||||
|
# 会自动从 GitHub Releases 下载 .sha256 文件来填充 Formula。
|
||||||
|
# 在 CI 中被 release-lite workflow 调用。
|
||||||
|
#
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||||
|
|
||||||
|
VERSION="${1:?Usage: $0 <version> (e.g. v0.2.0)}"
|
||||||
|
VERSION_BARE="${VERSION#v}"
|
||||||
|
FORMULA="${ROOT_DIR}/Formula/weknora-lite.rb"
|
||||||
|
REPO="Tencent/WeKnora"
|
||||||
|
BASE_URL="https://github.com/${REPO}/releases/download/${VERSION}"
|
||||||
|
|
||||||
|
if [ ! -f "${FORMULA}" ]; then
|
||||||
|
echo "Error: Formula not found at ${FORMULA}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Updating Formula to version ${VERSION_BARE}..."
|
||||||
|
|
||||||
|
fetch_sha256() {
|
||||||
|
local file="$1"
|
||||||
|
local url="${BASE_URL}/${file}.sha256"
|
||||||
|
local sha
|
||||||
|
sha=$(curl -sSL "${url}" | awk '{print $1}')
|
||||||
|
if [ -z "${sha}" ] || [ "${#sha}" -ne 64 ]; then
|
||||||
|
echo "Error: Failed to fetch sha256 from ${url}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "${sha}"
|
||||||
|
}
|
||||||
|
|
||||||
|
SHA_DARWIN_ARM64=$(fetch_sha256 "WeKnora-lite_${VERSION}_darwin_arm64.tar.gz")
|
||||||
|
SHA_DARWIN_AMD64=$(fetch_sha256 "WeKnora-lite_${VERSION}_darwin_amd64.tar.gz")
|
||||||
|
SHA_LINUX_ARM64=$(fetch_sha256 "WeKnora-lite_${VERSION}_linux_arm64.tar.gz")
|
||||||
|
SHA_LINUX_AMD64=$(fetch_sha256 "WeKnora-lite_${VERSION}_linux_amd64.tar.gz")
|
||||||
|
|
||||||
|
echo " darwin_arm64 : ${SHA_DARWIN_ARM64}"
|
||||||
|
echo " darwin_amd64 : ${SHA_DARWIN_AMD64}"
|
||||||
|
echo " linux_arm64 : ${SHA_LINUX_ARM64}"
|
||||||
|
echo " linux_amd64 : ${SHA_LINUX_AMD64}"
|
||||||
|
|
||||||
|
# Use a temp file for portable sed
|
||||||
|
TMP=$(mktemp)
|
||||||
|
cp "${FORMULA}" "${TMP}"
|
||||||
|
|
||||||
|
# Update version
|
||||||
|
sed -i.bak "s/^ version \".*\"/ version \"${VERSION_BARE}\"/" "${TMP}"
|
||||||
|
|
||||||
|
# Update sha256 values in order of appearance.
|
||||||
|
# The formula has sha256 lines in this order:
|
||||||
|
# 1. darwin arm64
|
||||||
|
# 2. darwin amd64
|
||||||
|
# 3. linux arm64
|
||||||
|
# 4. linux amd64
|
||||||
|
awk -v s1="${SHA_DARWIN_ARM64}" \
|
||||||
|
-v s2="${SHA_DARWIN_AMD64}" \
|
||||||
|
-v s3="${SHA_LINUX_ARM64}" \
|
||||||
|
-v s4="${SHA_LINUX_AMD64}" \
|
||||||
|
'BEGIN{n=0} /sha256 "/{n++; if(n==1) sub(/"[^"]*"$/,"\"" s1 "\""); else if(n==2) sub(/"[^"]*"$/,"\"" s2 "\""); else if(n==3) sub(/"[^"]*"$/,"\"" s3 "\""); else if(n==4) sub(/"[^"]*"$/,"\"" s4 "\"")} {print}' \
|
||||||
|
"${TMP}" > "${FORMULA}"
|
||||||
|
|
||||||
|
rm -f "${TMP}" "${TMP}.bak"
|
||||||
|
|
||||||
|
echo "Formula updated: ${FORMULA}"
|
||||||
Reference in New Issue
Block a user