Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/BUILD_INSTRUCTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# GitHub Actions 构建说明

## 工作流说明

此项目使用 GitHub Actions 自动构建和发布安装包。

### 工作流文件

- `.github/workflows/build-release.yml` - 主要构建和发布工作流
- `.github/workflows/pr-check.yml` - PR 检查工作流

### 构建配置

项目支持以下目标平台的交叉编译:

- `x86_64-unknown-linux-gnu` - 64位 x86 Linux
- `aarch64-unknown-linux-gnu` - 64位 ARM Linux
- `armv7-unknown-linux-gnueabihf` - 32位 ARM Linux

### 构建流程

1. 检出代码(包含子模块)
2. 构建前端(Vue.js)
3. 安装交叉编译工具链
4. 编译 Rust 代码
5. 创建发布资产
6. 上传构建产物

### 发布说明

当创建带有 `v` 前缀的标签时(如 `v0.1.0`),会触发发布流程,自动生成预构建的二进制文件并创建 GitHub Release。

### 静态构建

工作流同时构建常规版本和静态链接版本:
- 常规版本:较小,但可能需要系统库
- 静态版本:包含所有依赖,可在任何兼容系统上运行

## 本地构建

如果要在本地构建项目,请确保安装了以下依赖:

- Rust 工具链
- Node.js (用于前端构建)
- 交叉编译工具链
- 系统依赖(pkg-config, libssl-dev, libasound2-dev 等)

然后运行:

```bash
# 构建前端
cd web && npm install && npm run build && cd ..

# 构建后端
cargo build --release
```
229 changes: 229 additions & 0 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
name: Build and Release

on:
# 仅手动触发:构建完成后直接创建 Release 并上传产物。
workflow_dispatch:

env:
CARGO_TERM_COLOR: always

# 手动发布流程不自动取消,避免中断正在进行的 Release。
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
prepare:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}

steps:
- name: Generate release version
id: version
run: |
version="V$(TZ=Asia/Shanghai date +%Y%m%d%H%M%S)"
echo "version=${version}" >> "$GITHUB_OUTPUT"
echo "Release version: ${version}"

build:
needs: prepare
runs-on: ubuntu-latest

strategy:
matrix:
target:
- x86_64-unknown-linux-gnu
- aarch64-unknown-linux-gnu
- armv7-unknown-linux-gnueabihf

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Setup Node.js for frontend build
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Build frontend
working-directory: ./web
run: |
npm ci
npm run build

- name: Install cross-compilation tools
run: |
rustup target add ${{ matrix.target }}
cargo install cross --git https://github.com/cross-rs/cross

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y pkg-config libssl-dev libasound2-dev libudev-dev clang cmake protobuf-compiler

# Install target-specific packages if needed
case "${{ matrix.target }}" in
aarch64-unknown-linux-gnu)
sudo apt-get install -y gcc-aarch64-linux-gnu
;;
armv7-unknown-linux-gnueabihf)
sudo apt-get install -y gcc-arm-linux-gnueabihf
;;
esac

- name: Build with cross
run: |
# ARM build images ship a static FFmpeg built with --enable-rkmpp, so the
# rkmpp feature is required for the link step as well as for the encoders.
features=()
case "${{ matrix.target }}" in
aarch64-*|armv7-*) features=(--features rkmpp) ;;
esac
cross build --target ${{ matrix.target }} --release "${features[@]}"
# Also build size-optimized version for better portability
cross build --target ${{ matrix.target }} --profile release-static "${features[@]}"

- name: Prepare artifacts
run: |
# Create dist directory
mkdir -p dist

# Copy binaries
cp target/${{ matrix.target }}/release/one-kvm dist/one-kvm-${{ matrix.target }}
if [ -f target/${{ matrix.target }}/release-static/one-kvm ]; then
cp target/${{ matrix.target }}/release-static/one-kvm dist/one-kvm-${{ matrix.target }}-static
fi

# Make binaries executable
chmod +x dist/*

# Write release version and build metadata
echo "Version: ${{ needs.prepare.outputs.version }}" > dist/BUILD_INFO
echo "Target: ${{ matrix.target }}" >> dist/BUILD_INFO
echo "Commit: $(git rev-parse --short HEAD)" >> dist/BUILD_INFO
echo "${{ needs.prepare.outputs.version }}" > dist/VERSION

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: one-kvm-${{ matrix.target }}
path: dist/
retention-days: 7

deb:
needs: build
runs-on: ubuntu-22.04
timeout-minutes: 30

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Download binary artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Reconstruct target layout
run: |
set -euo pipefail
for target in x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu armv7-unknown-linux-gnueabihf; do
mkdir -p "target/${target}/release"
cp "artifacts/one-kvm-${target}/one-kvm-${target}" "target/${target}/release/one-kvm"
chmod +x "target/${target}/release/one-kvm"
done

- name: Install packaging tools
run: |
sudo apt-get update
sudo apt-get install -y xz-utils

- name: Package deb
run: bash build/package-deb.sh

- name: Upload deb
uses: actions/upload-artifact@v4
with:
name: one-kvm-deb
path: target/debian/*.deb
if-no-files-found: error
retention-days: 7

release:
needs: [prepare, build, deb]
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Prepare release assets
run: |
set -euo pipefail
assets_dir="$PWD/release_assets"
mkdir -p "$assets_dir"

for artifact in artifacts/*/; do
target_name=$(basename "$artifact")
echo "Processing $target_name"

if [ "$target_name" = "one-kvm-deb" ]; then
# Keep deb packages as release assets instead of tarring them.
cp "$artifact"/*.deb "$assets_dir"/
continue
fi

# Artifact names already contain the one-kvm- prefix, so do not add it twice.
tar -czf "$assets_dir/${target_name}.tar.gz" -C "$artifact" .
done

ls -lh "$assets_dir"

- name: Create Release
uses: softprops/action-gh-release@v2
with:
name: Release ${{ needs.prepare.outputs.version }}
tag_name: ${{ needs.prepare.outputs.version }}
target_commitish: ${{ github.sha }}
draft: false
prerelease: false
make_latest: 'true'
files: release_assets/*
body: |
## One-KVM Release ${{ needs.prepare.outputs.version }}

This release includes pre-built binaries and Debian packages for multiple platforms.

### Platforms
- `x86_64-unknown-linux-gnu`: 64-bit x86 Linux (most desktop/server systems)
- `aarch64-unknown-linux-gnu`: 64-bit ARM Linux (Raspberry Pi 4, ARM servers)
- `armv7-unknown-linux-gnueabihf`: 32-bit ARM Linux (Raspberry Pi 3 and earlier)

### Packages
- `one-kvm-<target>.tar.gz`: raw Linux binaries
- `one-kvm_*.deb`: Debian/Ubuntu packages (`amd64`, `arm64`, `armhf`)

### Installation
1. Download the appropriate binary for your platform
2. Extract: `tar -xzf one-kvm-*.tar.gz`
3. Make executable: `chmod +x one-kvm-*`
4. Run: `./one-kvm-* --help` to see available options
5. Debian/Ubuntu: `sudo dpkg -i one-kvm_*.deb`

### Changes
Please see the commit history for detailed changes in this release.

### Notes
- The static builds (`-static` suffix) have all dependencies included and should run on any compatible system
- Regular builds are smaller but may require system libraries to be installed
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Build

on:
# 功能分支推送不跑前端/deb/Windows 构建,仅由 build-release.yml 编译二进制。
pull_request:
workflow_dispatch:
inputs:
Expand Down
62 changes: 62 additions & 0 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: PR Check

on:
# 功能分支推送只构建二进制(build-release.yml),不跑格式检查/check/测试。
pull_request:
branches: [ main, master ]

env:
CARGO_TERM_COLOR: always

jobs:
test-build:
runs-on: ubuntu-latest
strategy:
matrix:
target:
- x86_64-unknown-linux-gnu
# 只在一个平台上测试以节省CI时间

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Setup Node.js for frontend build
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Build frontend
working-directory: ./web
run: |
npm ci
npm run build

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y pkg-config libssl-dev libasound2-dev libudev-dev clang cmake protobuf-compiler

- name: Install rust target
run: rustup target add ${{ matrix.target }}

- name: Check formatting
run: |
rustup component add rustfmt
cargo fmt --check

- name: Check for warnings
run: |
RUSTFLAGS="-D warnings" cargo check --target ${{ matrix.target }}

- name: Run tests
run: cargo test --target ${{ matrix.target }}

- name: Build release
run: cargo build --target ${{ matrix.target }} --release

- name: Verify binary
run: |
file target/${{ matrix.target }}/release/one-kvm
ldd target/${{ matrix.target }}/release/one-kvm || echo "Binary built successfully"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ CLAUDE.md
secrets.toml
.env
/docs/

# Local feedback server (PHP backend must never be committed)
/server/
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ audiopus = { version = "0.2", optional = true }
one-kvm-bluetooth-hid = { path = "libs/bluetooth-hid", optional = true }

# Utilities
nix = { version = "0.31", default-features = false, features = ["fs", "socket", "net", "hostname", "poll"], optional = true }
nix = { version = "0.31", default-features = false, features = ["fs", "socket", "net", "hostname", "poll", "term"], optional = true }

# Video capture (V4L2)
v4l2r = { path = "libs/v4l2r", optional = true }
Expand Down
4 changes: 3 additions & 1 deletion Cross.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Cross-compilation configuration for One-KVM
# Uses pre-built custom Debian 12 based images for consistent build/runtime environment
# Uses pre-built custom Debian 11 based images for consistent build/runtime environment
# Building on Debian 11 keeps the glibc baseline at 2.31, so binaries run on
# Debian 11/12, Ubuntu 20.04+, and Raspberry Pi OS bullseye/bookworm.
# See: https://github.com/cross-rs/cross

[build]
Expand Down
Loading