feat: MarkBase initial version

Phase 1 (Infrastructure):
- Docs: README.md, AGENTS.md, CHANGELOG.md
- Tests: 26 tests (modes_test, filetree_api_test)
- Examples: examples/sample.md, sample.json
- CI/CD: .gitea/workflows/test.yml, release.yml
- Runner: configuration scripts and guides

Phase 2 (Quality):
- Code quality: rustfmt/clippy config
- Security: environment variables
- Test coverage: 62 tests (+36)
- Documentation: CONTRIBUTING.md, docs/api.yaml
- Showcase: demo_features.md, developer_quickstart.md

Test coverage: 75%
Test pass rate: 100%
This commit is contained in:
Warren
2026-05-16 15:37:37 +08:00
commit e3d6b60825
50 changed files with 7758 additions and 0 deletions

753
docs/api.yaml Normal file
View File

@@ -0,0 +1,753 @@
openapi: 3.0.0
info:
title: MarkBase API
description: Momentry Display Engine - Markdown渲染與檔案樹管理系統
version: 0.1.0
contact:
name: MarkBase Team
servers:
- url: http://localhost:11438
description: 本地開發伺服器
- url: https://gitea.momentry.ddns.net
description: 生產伺服器
tags:
- name: Display
description: 內容顯示與渲染
- name: File Tree
description: 檔案樹管理
- name: Files
description: 檔案操作
- name: System
description: 系統狀態與控制
- name: Audio
description: macOS音訊控制
paths:
# Display相關路由
/:
get:
tags: [Display]
summary: 主頁顯示
description: 返回當前顯示的HTML內容
responses:
'200':
description: HTML內容
content:
text/html:
schema:
type: string
/display:
post:
tags: [Display]
summary: 更新顯示內容
description: 根據內容類型更新顯示內容
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
type:
type: string
enum: [md, markdown, json, url, video, image, html]
description: 內容類型
data:
type: string
description: 內容資料
file:
type: string
description:檔案路徑
url:
type: string
description: URL地址
html:
type: string
description: HTML內容
step_id:
type: string
step_num:
type: integer
step_total:
type: integer
responses:
'200':
description: 更新成功
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
/version:
get:
tags: [System]
summary: 取得版本號
responses:
'200':
content:
application/json:
schema:
type: object
properties:
v:
type: integer
/status:
get:
tags: [System]
summary: 取得狀態
responses:
'200':
content:
application/json:
schema:
type: object
properties:
paused:
type: boolean
step:
type: integer
total:
type: integer
id:
type: string
label:
type: string
voice:
type: string
/body:
get:
tags: [Display]
summary: 取得內容body
responses:
'200':
content:
text/html:
schema:
type: string
/labels:
get:
tags: [System]
summary: 取得標籤列表
responses:
'200':
content:
application/json:
schema:
type: array
items:
type: object
post:
tags: [System]
summary:更新標籤列表
requestBody:
content:
application/json:
schema:
type: array
items:
type: object
responses:
'200':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
# Audio相關路由
/devices:
get:
tags: [Audio]
summary: 取得音訊裝置
description: 列出所有音訊輸入/輸出裝置macOS
responses:
'200':
content:
application/json:
schema:
type: object
properties:
output:
type: array
items:
type: string
input:
type: array
items:
type: string
current_out:
type: string
current_in:
type: string
/volume:
get:
tags: [Audio]
summary: 取得音量
description: 取得當前音量級別macOS
responses:
'200':
content:
application/json:
schema:
type: object
properties:
level:
type: integer
# Command相關路由
/command:
get:
tags: [System]
summary: 取得指令隊列
responses:
'200':
content:
application/json:
schema:
type: array
items:
type: object
properties:
cmd:
type: string
val:
type: string
post:
tags: [System]
summary: 提交指令
requestBody:
content:
application/json:
schema:
type: object
properties:
cmd:
type: string
val:
type: string
out:
type: string
responses:
'200':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
# File Tree相關路由
/api/v2/tree/{user_id}:
get:
tags: [File Tree]
summary: 取得檔案樹
parameters:
- name: user_id
in: path
required: true
schema:
type: string
- name: mode
in: query
schema:
type: string
enum: [tree, list, grid_sm, grid_lg]
responses:
'200':
content:
application/json:
schema:
type: object
properties:
mode:
type: string
nodes:
type: array
items:
$ref: '#/components/schemas/FileNode'
delete:
tags: [File Tree]
summary: 刪除所有節點
parameters:
- name: user_id
in: path
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
deleted:
type: integer
/api/v2/tree/{user_id}/node:
post:
tags: [File Tree]
summary: 建立節點
parameters:
- name: user_id
in: path
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateNodeRequest'
responses:
'201':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
node_id:
type: string
/api/v2/tree/{user_id}/node/{node_id}:
put:
tags: [File Tree]
summary: 更新節點
parameters:
- name: user_id
in: path
required: true
- name: node_id
in: path
required: true
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateNodeRequest'
responses:
'200':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
delete:
tags: [File Tree]
summary: 刪除節點
parameters:
- name: user_id
in: path
required: true
- name: node_id
in: path
required: true
responses:
'200':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
/api/v2/tree/{user_id}/node/{node_id}/move:
put:
tags: [File Tree]
summary: 移動節點
parameters:
- name: user_id
in: path
required: true
- name: node_id
in: path
required: true
requestBody:
content:
application/json:
schema:
type: object
properties:
parent_id:
type: string
responses:
'200':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
/api/v2/tree/{user_id}/node/{node_id}/alias:
patch:
tags: [File Tree]
summary: 更新別名
parameters:
- name: user_id
in: path
required: true
- name: node_id
in: path
required: true
requestBody:
content:
application/json:
schema:
type: object
properties:
lang:
type: string
value:
type: string
responses:
'200':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
/api/v2/tree/{user_id}/restore:
post:
tags: [File Tree]
summary: 從外部API恢復檔案樹
parameters:
- name: user_id
in: path
required: true
responses:
'200':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
deleted:
type: integer
imported:
type: integer
/api/v2/modes:
get:
tags: [File Tree]
summary: 取得顯示模式列表
responses:
'200':
content:
application/json:
schema:
type: object
properties:
modes:
type: array
items:
$ref: '#/components/schemas/DisplayMode'
# Files相關路由
/api/v2/dupes/{user_id}:
get:
tags: [Files]
summary: 取得重複檔案
parameters:
- name: user_id
in: path
required: true
responses:
'200':
content:
application/json:
schema:
type: object
/api/v2/unregister/{file_uuid}:
post:
tags: [Files]
summary: 取消註冊檔案
parameters:
- name: file_uuid
in: path
required: true
responses:
'200':
content:
application/json:
schema:
type: object
/api/v2/upload/{user_id}:
post:
tags: [Files]
summary: 上傳檔案
parameters:
- name: user_id
in: path
required: true
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
'201':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
filename:
type: string
file_uuid:
type: string
sha256:
type: string
size:
type: integer
/api/v2/render/{file_uuid}:
get:
tags: [Files]
summary: 渲染檔案
parameters:
- name: file_uuid
in: path
required: true
responses:
'200':
content:
text/html:
schema:
type: string
/api/v2/render/{file_uuid}/body:
get:
tags: [Files]
summary: 取得檔案渲染內容
parameters:
- name: file_uuid
in: path
required: true
responses:
'200':
content:
text/html:
schema:
type: string
/api/v2/files/{file_uuid}/info:
get:
tags: [Files]
summary: 取得檔案資訊
parameters:
- name: file_uuid
in: path
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/FileInfo'
/api/v2/files/{file_uuid}/probe:
get:
tags: [Files]
summary: 取得檔案探測資訊
parameters:
- name: file_uuid
in: path
required: true
responses:
'200':
content:
application/json:
schema:
type: object
/api/v2/files/{file_uuid}/stream:
get:
tags: [Files]
summary: 串流檔案
parameters:
- name: file_uuid
in: path
required: true
responses:
'200':
content:
application/octet-stream:
schema:
type: string
format: binary
/api/v2/files/{file_uuid}/locations:
post:
tags: [Files]
summary: 新增檔案位置
parameters:
- name: file_uuid
in: path
required: true
requestBody:
content:
application/json:
schema:
type: object
properties:
location:
type: string
label:
type: string
responses:
'200':
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
components:
schemas:
FileNode:
type: object
properties:
node_id:
type: string
label:
type: string
aliases:
type: object
file_uuid:
type: string
sha256:
type: string
parent_id:
type: string
node_type:
type: string
enum: [folder, file]
icon:
type: string
color:
type: string
bg_color:
type: string
file_size:
type: integer
registered_at:
type: string
children:
type: array
items:
type: string
CreateNodeRequest:
type: object
required: [label]
properties:
label:
type: string
node_type:
type: string
enum: [folder, file]
parent_id:
type: string
file_uuid:
type: string
sha256:
type: string
file_size:
type: integer
file_type:
type: string
UpdateNodeRequest:
type: object
properties:
label:
type: string
icon:
type: string
color:
type: string
bg_color:
type: string
DisplayMode:
type: object
properties:
name:
type: string
sort_options:
type: array
items:
$ref: '#/components/schemas/SortOption'
filter_options:
type: array
items:
$ref: '#/components/schemas/FilterOption'
SortOption:
type: object
properties:
key:
type: string
label:
type: string
FilterOption:
type: object
properties:
key:
type: string
label:
type: string
FileInfo:
type: object
properties:
file_uuid:
type: string
original_name:
type: string
file_size:
type: integer
file_type:
type: string
registered_at:
type: string
status:
type: string

413
docs/filetree.md Normal file
View File

@@ -0,0 +1,413 @@
# File Tree Architecture
## Overview
File Tree是MarkBase的核心模組提供檔案樹管理功能。
**Location:** `src/filetree/`
**Total Lines:** 1234行
---
## Module Structure
```
src/filetree/
├── mod.rs (553行) -核心CRUD操作
├── convert.rs (253行) -檔案轉換功能
├── mode.rs (43行) - DisplayMode trait定義
├── node.rs (82行) -節點資料結構
└── modes/
├── tree.rs (57行) -樹狀顯示模式
├── list.rs (87行) -列表顯示模式
├── grid_sm.rs (72行) -小格狀顯示模式
├── grid_lg.rs (83行) -大格狀顯示模式
└── mod.rs (4行) -模式匯出
```
---
## Database Design
### SQLite Tables
**Location:** `data/users/<user_id>.sqlite`
|Table |Purpose |
|------|--------|
| file_registry |檔案註冊資訊 |
| file_nodes |檔案樹節點 |
| file_locations |檔案位置記錄 |
### file_nodes Schema
```sql
CREATE TABLE file_nodes (
node_id TEXT PRIMARY KEY,
label TEXT NOT NULL,
aliases_json TEXT NOT NULL DEFAULT '{}',
file_uuid TEXT,
sha256 TEXT,
parent_id TEXT,
children_json TEXT NOT NULL DEFAULT '[]',
node_type TEXT NOT NULL DEFAULT 'folder',
icon TEXT,
color TEXT,
bg_color TEXT,
file_size INTEGER,
registered_at TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
sort_order INTEGER NOT NULL DEFAULT 0
);
```
### Node Types
- **folder** -資料夾節點(可包含子節點)
- **file** -檔案節點(指向實體檔案)
---
## Public API13 Functions
### CRUD Operationsmod.rs
|Function |Location |Description |
|----------|----------|-------------|
| user_db_path | 58 |取得資料庫路徑 |
| init_user_db | 62 |初始化資料庫 |
| open_user_db | 74 |開啟資料庫連接 |
| load | 79 |載入檔案樹 |
| insert_node | 120 |插入節點 |
| update_node | 149 |更新節點屬性 |
| update_node_alias | 187 |更新多語言別名 |
| delete_node | 214 |刪除節點 |
| move_node | 220 |移動節點位置 |
| build_tree | 240 |建立樹狀結構 |
### Node Creationnode.rs
|Function |Location |Description |
|----------|----------|-------------|
| new_folder | 27 |建立資料夾節點 |
| new_file_node | 300 |建立檔案節點 |
### Utilities
|Function |Location |Description |
|----------|----------|-------------|
| add_location | 346 |新增檔案位置 |
| get_file_info | 359 |取得檔案資訊 |
---
## REST API7 Routes
### Endpoints
|Route |Method |Function |server.rs |
|------|--------|----------|-----------|
| `/api/v2/tree/:user_id` | GET | get_tree | 61 |
| `/api/v2/tree/:user_id` | DELETE | delete_all_nodes | 64 |
| `/api/v2/tree/:user_id/node` | POST | create_node | 62 |
| `/api/v2/tree/:user_id/node/:node_id` | PUT | update_node | 63 |
| `/api/v2/tree/:user_id/node/:node_id` | DELETE | delete_node | 63 |
| `/api/v2/tree/:user_id/node/:node_id/move` | PUT | move_node | 71 |
| `/api/v2/tree/:user_id/node/:node_id/alias` | PATCH | update_alias | 72 |
| `/api/v2/tree/:user_id/restore` | POST | restore_tree | 65 |
### Query Parameters
- `mode` -顯示模式tree, list, grid_sm, grid_lg
### Examples
```bash
#取得檔案樹(樹狀顯示)
curl http://localhost:11438/api/v2/tree/demo?mode=tree
#取得檔案樹(列表顯示)
curl http://localhost:11438/api/v2/tree/demo?mode=list
#建立節點
curl -X POST http://localhost:11438/api/v2/tree/demo/node \
-H "Content-Type: application/json" \
-d '{"label":"NewFolder", "node_type":"folder"}'
#更新別名
curl -X PATCH http://localhost:11438/api/v2/tree/demo/node/<node_id>/alias \
-H "Content-Type: application/json" \
-d '{"lang":"zh_tw", "value":"新資料夾"}'
```
---
## DisplayMode Trait
### Definitionmode.rs:19
```rust
pub trait DisplayMode: Send + Sync {
fn name(&self) -> &'static str;
fn render(&self, tree: &FileTree) -> Value;
fn sort_options(&self) -> Vec<SortOption>;
fn filter_options(&self) -> Vec<FilterOption>;
}
```
### Implementations
|Mode |File |Purpose |
|------|------|---------|
| Tree | modes/tree.rs |層級樹狀結構顯示 |
| List | modes/list.rs |簡潔列表顯示 |
| GridSm | modes/grid_sm.rs |緊湊格狀顯示 |
| GridLg | modes/grid_lg.rs |寬鬆格狀顯示 |
### Usage
```rust
//取得顯示模式
let mode = filetree::mode::get_mode("tree");
//渲染檔案樹
let rendered = mode.render(&tree);
//取得排序選項
let sort_options = mode.sort_options();
//取得過濾選項
let filter_options = mode.filter_options();
```
---
## File Conversionconvert.rs
### Supported Formats
|Tool |Formats |
|------|---------|
| textutilmacOS | doc, docx, rtf |
| macOS Tools | pages, key, numbers |
| soffice/qlmanage | pptx, ppt, xlsx, xls, odt, epub |
### Functions
- `is_document_ext(ext)` - 檢查是否為文檔格式
- `is_textutil_ext(ext)` - 檢查是否為textutil支援格式
- `is_apple_format_ext(ext)` - 檢查是否為Apple格式
- `get_cached_preview(file_uuid, ext)` - 生成緩存預覽
### Cache Directory
**Location:** `data/cache/`
---
## Testing
### Current Tests7 Tests
|Test |Status |Description |
|------|--------|-------------|
| test_init_and_load_empty_tree | ✅ OK |初始化空檔案樹 |
| test_insert_and_load_node | ✅ OK |插入節點 |
| test_update_node | ✅ OK |更新節點屬性 |
| test_delete_node | ✅ OK |刪除節點 |
| test_move_node | ✅ OK |移動節點位置 |
| test_update_alias | ✅ OK |更新多語別別名 |
| test_build_tree | ✅ OK |建立樹狀結構 |
### Missing Tests
- ❌ convert.rs -檔案轉換功能
- ❌ modes/*.rs - DisplayMode渲染
- ❌ REST API - endpoint測試
### Test Cleanup
Tests create temporary databases: `data/users/test_*.sqlite`
```bash
#清理暫存資料庫
rm data/users/test_*.sqlite
```
---
## Development Examples
### Create Folder
```rust
use crate::filetree::{FileTree, FileNode};
//建立資料夾節點
let folder = FileTree::new_folder("Videos", None);
//插入到資料庫
let conn = FileTree::open_user_db("demo")?;
let mut tree = FileTree::load(&conn, "demo")?;
tree.insert_node(&conn, &folder)?;
```
### Create File Node
```rust
//建立檔案節點
let (file_node, register_sql) = FileTree::new_file_node(
"demo.mp4",
"abc123def456...", // file_uuid
Some("sha256hash"), // sha256
"demo.mp4", // original_name
Some(1024000), // file_size
Some("video/mp4"), // file_type
None, // registered_at
Some(folder.node_id), // parent_id
);
//插入到資料庫
tree.insert_node(&conn, &file_node)?;
```
### Load and Query
```rust
//載入檔案樹
let conn = FileTree::open_user_db("demo")?;
let tree = FileTree::load(&conn, "demo")?;
//建立樹狀結構
let roots = tree.build_tree();
//取得特定顯示模式
let mode = filetree::mode::get_mode("tree");
let rendered = mode.render(&tree);
```
### Update Alias
```rust
//更新多語言別名
tree.update_node_alias(&conn, &node_id, "zh_tw", "影片")?;
tree.update_node_alias(&conn, &node_id, "en_us", "Videos")?;
tree.update_node_alias(&conn, &node_id, "ja_jp", "動画")?;
```
---
## Demo Database
**Location:** `data/users/demo.sqlite`
**Statistics:**
- Total Nodes: 50
- Folders: 5
- Files: 45
**Structure:**
```
Home根資料夾
├── Movies9個檔案
│ ├── view7.mp4
│ ├── Charade_YouTube_24fps.mp4
│ └── ...
├── Marketing26個檔案
│ ├── Screenshot *.png
│ ├── diagram-*.svg
│ └── ...
├── Cartoons5個檔案
│ ├── animal11.jpg
│ ├── animal10.jpg
│ └── ...
└── Other4個檔案
├── people.jpg
└── ...
```
---
## Architecture Diagram
```
┌─────────────────────────────────────┐
│ server.rs │
│ REST API HandlersAxum
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ filetree/mod.rs │
│ FileTree CRUD Operations │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ SQLite Database │
│ data/users/<user_id>.sqlite │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ filetree/mode.rs │
│ DisplayMode Trait │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ filetree/modes/*.rs │
│ Tree, List, GridSm, GridLg │
└─────────────────────────────────────┘
```
---
## Best Practices
### Database Management
- Each user has independent database
- Use UUID for node_id
- Maintain parent-child relationships via parent_id
- Update updated_at timestamp on modifications
### Performance
- Use spawn_blocking for SQLite operationsAxum async
- Cache file_tree in memory if frequently accessed
- Batch operations when possible
### Security
- Validate node_type before insertion
- Check parent_id existence before moving
- Sanitize aliases_json input
---
## Future Improvements
### Planned Features
- Pagination for large file trees
- Search and filter functionality
- File versioning
- Trash binsoft delete
- Batch import/export
### Performance Optimization
- Database connection pooling
- Caching layerRedis
- Async SQLite drivertokio-rusqlite
### Testing Coverage
- convert.rs tests
- DisplayMode tests
- REST API integration tests
- Performance benchmarks
---
**Last Updated:** 2026-05-16
**Version:** 1.0

300
docs/gitea_runner_setup.md Normal file
View File

@@ -0,0 +1,300 @@
# Gitea Actions Runner配置指南
##環境資訊
- **Gitea Server**: https://gitea.momentry.ddns.net
- **Gitea版本**: 1.25.3(支援 Actions
- **Runner位置**:本機Mac
- **目標**:實機測試 macOS音訊功能
---
##配置步驟
### 1. 取得 Runner Token
1.登入 Gitea: https://gitea.momentry.ddns.net
2.進入 **Settings → Actions → Runners**
3.建立新 Runner複製 Token
**Token格式範例**
```
A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6
```
---
### 2.下載並安裝 Runner
**macOS ARM版本**
```bash
#下載 act_runnerGitea官方Runner
wget https://dl.gitea.com/act_runner/latest/act_runner-darwin-arm64
#設定執行權限
chmod +x act_runner-darwin-arm64
#移動到系統路徑
sudo mv act_runner-darwin-arm64 /usr/local/bin/act_runner
#驗證安裝
act_runner --version
```
---
### 3.註冊 Runner
**連接遠端 Gitea**
```bash
#註冊 Runner使用步驟1取得的Token
act_runner register --instance https://gitea.momentry.ddns.net --token <YOUR_TOKEN>
#交互式配置
#會提示輸入 Runner名稱、標籤等資訊
```
**建議配置:**
- Runner名稱`macos-runner`
- Labels`macos-latest`
- Runner groupdefault
---
### 4.啟動 Runner
**前景執行(測試用):**
```bash
act_runner daemon
```
**背景服務macOS launchd**
建立服務配置檔案:
```xml
<!-- ~/Library/LaunchAgents/com.gitea.runner.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.gitea.runner</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/act_runner</string>
<string>daemon</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/gitea-runner.log</string>
<key>StandardErrorPath</key>
<string>/tmp/gitea-runner.err</string>
</dict>
</plist>
```
**載入服務:**
```bash
#載入服務
launchctl load ~/Library/LaunchAgents/com.gitea.runner.plist
#驗證服務狀態
launchctl list | grep gitea
```
---
### 5.驗證 Runner狀態
**在 Gitea網頁驗證**
1.登入 Gitea
2. Settings → Actions → Runners
3.確認 Runner已連接狀態為 green
**在本機驗證:**
```bash
#檢查 Runner狀態
act_runner list
#檢查 Runner日誌
tail -f /tmp/gitea-runner.log
```
---
##必要環境配置
### Rust Toolchain
```bash
#確認 Rust環境
rustc --version
cargo --version
#若未安裝
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
### SwitchAudioSource音訊測試
```bash
#安裝
brew install switchaudio-source
#驗證
SwitchAudioSource -a
```
###其他工具
```bash
#確認 clippy
cargo clippy --version
#確認 rustfmt
cargo fmt -- --version
```
---
## Workflow觸發測試
###觸發方式
**Push觸發**
```bash
git push origin main
```
**PR觸發**
```bash
git checkout -b feature/test
git push origin feature/test
#在 Gitea建立 Pull Request
```
**查看執行結果:**
1.進入專案頁面
2. Actions →查看workflow執行狀態
---
##常見問題
### Runner無法連接 Gitea
**檢查網路連接:**
```bash
curl -I https://gitea.momentry.ddns.net
```
**確認 Token正確**
```bash
act_runner list
```
### Workflow執行失敗
**檢查日誌:**
```bash
tail -f /tmp/gitea-runner.log
```
**常見錯誤:**
- Rust未安裝 →安裝 Rust toolchain
- SwitchAudioSource未安裝 → brew install
- clippy警告 →修復代碼
---
## Runner維護
###更新 Runner
```bash
#停止服務
launchctl unload ~/Library/LaunchAgents/com.gitea.runner.plist
#下載新版本
wget https://dl.gitea.com/act_runner/latest/act_runner-darwin-arm64
#重新安裝
chmod +x act_runner-darwin-arm64
sudo mv act_runner-darwin-arm64 /usr/local/bin/act_runner
#重新啟動
launchctl load ~/Library/LaunchAgents/com.gitea.runner.plist
```
###清理緩存
```bash
#清理 cargo緩存
cargo clean
#清理測試暫存檔
rm -f data/users/test_*.sqlite
```
---
##進階配置
###多 Runner支援
若有多台機器,可配置多個 Runner
```bash
#第二台機器註冊
act_runner register --instance https://gitea.momentry.ddns.net --token <TOKEN2>
```
**使用不同 labels區分**
- macos-runner-1: `macos-latest`
- macos-runner-2: `macos-14`
- linux-runner: `ubuntu-latest`
---
##安全性考量
### Token管理
- Token應妥善保存避免暴露
-定期更新 Token
- 使用環境變數配置
###網路安全
- Gitea使用 HTTPS已配置
- Runner使用 Token認證
-僅連接信任的 Gitea server
---
##叢考資源
- [Gitea Actions官方文檔](https://docs.gitea.com/usage/actions/overview)
- [act_runner GitHub](https://gitea.com/gitea/act_runner)
- [GitHub Actions兼容性](https://docs.gitea.com/usage/actions/comparison)
---
**最後更新2026-05-16**

106
docs/runner_usage.md Normal file
View File

@@ -0,0 +1,106 @@
# Gitea Runner使用指南快速版
## Runner已配置完成
**Runner資訊**
-版本v1.0.3
- 名稱accusys-Mac-mini-M4-2.local
- ID1
-地址https://gitea.momentry.ddns.net
---
## 啟動 Runner
### 方式A前景執行測試用
```bash
cd /Users/accusys/markbase
./scripts/start_runner.sh
```
或直接執行:
```bash
cd /Users/accusys/markbase
~/.local/bin/gitea-runner daemon
```
### 方式B背景服務macOS launchd
```bash
#配置為系統服務
./scripts/setup_launchd.sh
#管理命令
launchctl load ~/Library/LaunchAgents/com.gitea.runner.plist #啟動
launchctl unload ~/Library/LaunchAgents/com.gitea.runner.plist #停止
launchctl list | grep gitea #狀態
tail -f /tmp/gitea-runner.log #日誌
```
---
##驗證 Runner狀態
```bash
./scripts/verify_runner.sh
```
---
##支持的Labels
- `macos-latest:host` -本機Mac執行bare-metal
- `macos-arm64:host` -本機Mac執行bare-metal
- `ubuntu-latest:docker` - Docker容器執行
---
##觸發Workflow測試
### Push觸發
```bash
git add .
git commit -m "test workflow"
git push origin main
```
### 在Gitea查看結果
1.登入https://gitea.momentry.ddns.net
2.進入專案 → Actions →查看workflow執行狀態
---
##常見問題
**Q: Runner無法連接Gitea**
```bash
curl -I https://gitea.momentry.ddns.net
```
**Q: Workflow執行失敗**
```bash
tail -f /tmp/gitea-runner.log
tail -f /tmp/gitea-runner.err
```
**Q: macOS功能測試失敗**
-確認SwitchAudioSource已安裝`brew install switchaudio-source`
-確認使用`runs-on: macos-latest`bare-metal執行
---
##Runner配置檔案
**位置:** `/Users/accusys/markbase/.runner`
**重要:**
-不要手動刪除.runner檔案會導致Runner重新註冊
- Runner token與註冊token不同已自動生成
---
**最後更新2026-05-16**