banshee86vr/snorlx
GitHub: banshee86vr/snorlx
一款自托管的 GitHub Actions CI/CD 仪表盘,提供跨仓库与组织的流水线可视化、成本追踪及代码质量评分。
Stars: 26 | Forks: 4
# Snorlx - GitHub Actions 的 CI/CD 仪表盘
[](https://github.com/banshee86vr/snorlx/actions/workflows/ci.yml) [](https://github.com/banshee86vr/snorlx/actions/workflows/security.yml)
一个全面的、自托管的仪表盘,提供针对分布在多个仓库和组织中的 GitHub Actions 流水线、性能指标和成本的集中可视化。

## 功能
- **集中可视化**:跨所有仓库的工作流运行的单一视图
- **仓库评分**:根据安全性、测试、CI/CD、文档、代码质量、维护和社区等维度,将仓库评为金/银/铜等级
- **实时更新**:通过 WebSocket 获取实时流水线状态
- **GitHub OAuth**:使用 GitHub 登录;无需设置 GitHub App
- **成本追踪**:针对单个工作流和单个仓库的成本分析
- **多仓库支持**:监控跨多个仓库和组织的各项流水线
- **美观的 UI**:现代、响应式的设计,支持深色/浅色模式
- **两种存储模式**:可使用内存模式快速启动,或使用 PostgreSQL 数据库实现持久化
## 架构

## 快速开始
### ⚡ TL;DR - 5 分钟内开始运行
**无数据库(内存模式):**
```
# 克隆并安装
git clone https://github.com/banshee86vr/snorlx.git && cd snorlx && pnpm install
# 配置(使用你的 GitHub 凭据编辑 .env)
cp env.example .env
# 在 .env 中设置 STORAGE_MODE=memory(默认)
# 同时启动 frontend 和 backend
pnpm run dev
```
**使用 PostgreSQL 数据库:**
```
# 克隆并安装
git clone https://github.com/banshee86vr/snorlx.git && cd snorlx && pnpm install
# 启动 PostgreSQL (Docker)
docker run --name snorlx-postgres \
-e POSTGRES_DB=snorlx \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-p 5432:5432 -d timescale/timescaledb:latest-pg16
# 配置(使用你的凭据和 DATABASE_URL 编辑 .env)
cp env.example .env
# 在 .env 中设置 STORAGE_MODE=database 和 DATABASE_URL
# 同时启动 frontend 和 backend
pnpm run dev
```
访问地址:http://localhost:5173
### 前置条件
- Go 1.26+
- Node.js 20+
- pnpm 或 npm
- 带有 TimescaleDB 的 PostgreSQL 14+(可选 - 仅用于数据库模式)
- GitHub OAuth App(请参阅[设置指南](#github-oauth-app-setup))
## 🚀 本地开发(无需 Docker)
### 选项 1:内存模式(无数据库)
**非常适合测试和开发!** 几分钟即可启动,无需配置数据库。
1. **克隆并安装依赖**
```
git clone https://github.com/banshee86vr/snorlx.git
cd snorlx
pnpm install
```
2. **配置环境变量**
```
# 复制示例环境文件
cp env.example .env
```
编辑 `.env` 并填入你的凭证:
```
# 开发模式(跳过 GitHub OAuth 验证)
DEV_MODE=true
# Storage Mode - 使用 memory 以便快速开始(无需数据库)
STORAGE_MODE=memory
# GitHub OAuth(创建地址:https://github.com/settings/developers)
GITHUB_CLIENT_ID=your_oauth_client_id
GITHUB_CLIENT_SECRET=your_oauth_client_secret
# Session Security(生成命令:openssl rand -base64 32)
SESSION_SECRET=your_random_32_character_secret_string
# URLs
PORT=8080
FRONTEND_URL=http://localhost:5173
```
3. **启动应用**
```
# 从项目根目录 - 同时启动 frontend 和 backend
pnpm run dev
```
应用将会启动:
- Frontend: http://localhost:5173
- Backend API: http://localhost:8080
**或者分别启动:**
```
# 仅 backend
pnpm run dev:backend
# 仅 frontend(在另一个终端)
pnpm run dev:frontend
```
### 选项 2:数据库模式(持久化存储)
适用于在生产环境中进行持久化数据存储。
#### 步骤 1:安装依赖
```
git clone https://github.com/banshee86vr/snorlx.git
cd snorlx
pnpm install
```
#### 步骤 2:配置 PostgreSQL + TimescaleDB
**使用 Docker(推荐)**
```
docker run --name snorlx-postgres \
-e POSTGRES_DB=snorlx \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-p 5432:5432 \
-d timescale/timescaledb:latest-pg16
```
**使用本地 PostgreSQL(macOS 配合 Homebrew)**
```
# 安装 TimescaleDB
brew install postgresql@16 timescaledb
# 启动 PostgreSQL
brew services start postgresql@16
# 创建数据库
psql postgres -c "CREATE DATABASE snorlx;"
```
#### 步骤 3:配置环境变量
```
cp env.example .env
```
编辑 `.env`:
```
# 开发模式
DEV_MODE=true
# Storage Mode - 使用 database 实现持久化
STORAGE_MODE=database
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/snorlx?sslmode=disable
# GitHub 配置
GITHUB_CLIENT_ID=your_oauth_client_id
GITHUB_CLIENT_SECRET=your_oauth_client_secret
# Session Security
SESSION_SECRET=your_random_32_character_secret_string
# URLs
PORT=8080
FRONTEND_URL=http://localhost:5173
```
#### 步骤 4:启动应用
```
# 从项目根目录 - 同时启动 frontend 和 backend
# Migrations 在 backend 启动时自动运行
pnpm run dev
```
访问地址:http://localhost:5173
## 🐳 Docker Compose 设置
适用于将所有服务容器化的生产环境部署。
1. **配置环境变量**
```
cp env.example .env
# 使用你的生产环境设置编辑 .env
# 确保为 Docker 设置 STORAGE_MODE=database
```
2. **启动所有服务**
```
docker compose up -d
```
仪表盘将通过 http://localhost:5174 (frontend) 和 http://localhost:3001 (backend API) 提供。
3. **查看日志**
```
docker compose logs -f
```
4. **停止服务**
```
docker compose down
```
## 仓库评分
系统会基于七个类别的检查,为仓库提供一个总体百分比和等级(金 / 银 / 铜)进行评分:
| 类别 | 权重 | 示例 |
| ---------- | ---- | -------------------------------------- |
| 安全性 | 25% | 分支保护、Dependabot、代码扫描 |
| 测试 | 20% | 测试配置、覆盖率、CI 测试任务 |
| CI/CD | 15% | 工作流、部署、状态检查 |
| 文档 | 15% | README、CONTRIBUTING、Issue 模板 |
| 代码质量 | 10% | 代码检查工具、代码所有者 |
| 维护 | 10% | 近期活跃度、描述 |
| 社区 | 5% | 社区健康文件 |
同步一个仓库,并在其详情页使用 **刷新等级** 来计算或更新其分数。仪表盘摘要将显示所有仓库的平均分。
## GitHub OAuth App 设置
本项目使用 GitHub OAuth App 进行用户身份验证(比 GitHub App 更简单)。
### 步骤 1:创建 OAuth App
1. 前往 [GitHub Developer Settings](https://github.com/settings/developers)
2. 点击 **OAuth Apps** → **New OAuth App**
3. 填写详细信息:
- **Application name**:`Snorlx Dashboard`(或你偏好的名称)
- **Homepage URL**:`http://localhost:5173`(或你的生产环境 URL)
- **Authorization callback URL**:`http://localhost:8080/api/auth/callback`
4. 点击 **Register application**
### 步骤 2:获取凭证
1. 复制 **Client ID**
2. 点击 **Generate a new client secret** 并复制它
### 步骤 3:配置环境变量
将其添加到你的 `.env` 文件中:
```
GITHUB_CLIENT_ID=your_client_id_here
GITHUB_CLIENT_SECRET=your_client_secret_here
```
### OAuth 作用域
应用会请求以下 OAuth 作用域:
- `read:user` - 读取用户个人资料信息
- `user:email` - 访问用户邮箱地址
- `repo` - 访问仓库(用于获取工作流数据)
- `read:org` - 读取组织成员身份
### 可选:Webhooks
要通过 webhook 获取实时更新,请在你的仓库/组织设置中配置 webhook:
1. 前往 Repository → Settings → Webhooks → Add webhook
2. **Payload URL**:`https://your-domain.com/api/webhooks/github`
3. **Content type**:`application/json`
4. **Secret**:生成一个安全的密钥,并作为 `GITHUB_WEBHOOK_SECRET` 添加到 `.env` 中
5. 选择事件:`Workflow runs`、`Workflow jobs`、`Deployments`
## 配置说明
### 环境变量
#### 存储配置
| 变量 | 必填 | 默认值 | 描述 |
| ------------------- | ---------------------- | -------- | -------------------------------------------- |
| `STORAGE_MODE` | 否 | `memory` | `memory` 或 `database` |
| `DATABASE_URL` | 仅在 `database` 模式下 | - | PostgreSQL 连接字符串 |
| `POSTGRES_PASSWORD` | 仅在 `database` 模式下 | - | PostgreSQL 密码(由 Docker Compose 使用) |
#### 服务器配置
| 变量 | 描述 | 默认值 |
| ---------------- | -------------------------------------- | ----------------------- |
| `PORT` | 服务器端口 | `8080` |
| `LOG_LEVEL` | 日志级别(debug, info, warn, error) | `info` |
| `SESSION_SECRET` | 会话加密密钥 | 必填 |
| `FRONTEND_URL` | 用于 CORS 的前端 URL | `http://localhost:5173` |
| `VITE_API_URL` | 前端使用的后端 API URL | `http://localhost:8080` |
#### GitHub OAuth 配置
| 变量 | 描述 | 必填 |
| ---------------------- | -------------------------- | ---------------------- |
| `GITHUB_CLIENT_ID` | GitHub OAuth App Client ID | 是 |
| `GITHUB_CLIENT_SECRET` | GitHub OAuth App Client Secret | 是 |
| `GITHUB_WEBHOOK_SECRET` | Webhook 签名密钥 | 否(仅用于 webhook) |
| `DEV_MODE` | 跳过 GitHub OAuth 验证 | 否 |
#### 同步配置
| 变量 | 必填 | 默认值 | 描述 |
| ------------ | ---- | ----------- | ----------------------------------- |
| `SYNC_LIMIT` | 否 | `0`(全部) | 限制同步的仓库数量 |
| `SYNC_REPOS` | 否 | - | 以逗号分隔的指定要同步的仓库列表 |
## API 端点
### 健康检查
- `GET /health` - 健康检查端点
### 身份验证
- `GET /api/auth/login` - 发起 GitHub OAuth
- `GET /api/auth/callback` - OAuth 回调
- `POST /api/auth/logout` - 退出登录
- `GET /api/auth/status` - 检查认证状态
### 组织
- `GET /api/organizations` - 列出所有组织
- `GET /api/organizations/:id` - 获取组织详情
### 仓库
- `GET /api/repositories` - 列出所有仓库
- `GET /api/repositories/:id` - 获取仓库详情
- `GET /api/repositories/scores` - 列出最新的仓库评分(所有仓库)
- `GET /api/repositories/:id/score` - 获取某个仓库的最新评分
- `POST /api/repositories/sync` - 触发仓库同步
### 工作流
- `GET /api/workflows` - 列出所有工作流
- `GET /api/workflows/:id` - 获取工作流详情
- `PATCH /api/workflows/:id` - 更新工作流
- `GET /api/workflows/:id/runs` - 获取工作流运行记录
### 运行记录
- `GET /api/runs` - 列出所有运行记录(支持过滤)
- `GET /api/runs/:id` - 获取运行详情
- `GET /api/runs/:id/jobs` - 获取运行的任务
- `GET /api/runs/:id/logs` - 获取运行的日志
- `GET /api/runs/:id/annotations` - 获取运行的注解
- `GET /api/runs/:id/workflow-definition` - 获取工作流的 YAML 定义
- `POST /api/runs/:id/rerun` - 重新运行工作流
- `POST /api/runs/:id/cancel` - 取消正在运行的工作流
### 任务
- `GET /api/jobs/:id/logs` - 获取任务日志
### 仪表盘
- `GET /api/dashboard/summary` - 获取仪表盘摘要
- `GET /api/dashboard/trends` - 获取趋势数据
### 实时更新
- `GET /ws` - 用于实时更新的 WebSocket 端点
### Webhooks
- `POST /api/webhooks/github` - GitHub webhook 接收器
## 项目结构
```
├── .github/workflows/ # CI and Security GitHub Actions
├── frontend/ # React frontend
│ ├── src/
│ │ ├── components/ # UI components (layout, protected routes)
│ │ ├── context/ # React contexts (auth, theme, socket, sync, sidebar)
│ │ ├── lib/ # Utility functions
│ │ ├── pages/ # Page components
│ │ ├── services/ # API client
│ │ ├── styles/ # Global styles
│ │ ├── test/ # Test setup
│ │ └── types/ # TypeScript types
│ └── ...
├── backend/ # Go backend
│ ├── cmd/server/ # Main entry point
│ ├── internal/
│ │ ├── config/ # Configuration
│ │ ├── database/ # Database migrations and setup
│ │ ├── github/ # GitHub client
│ │ ├── handlers/ # HTTP handlers
│ │ ├── models/ # Data models
│ │ ├── scorer/ # Repository scoring (gold/silver/bronze)
│ │ ├── storage/ # Storage layer (memory/database)
│ │ └── websocket/ # WebSocket hub for real-time updates
│ └── ...
├── helm/ # Kubernetes Helm charts
└── docker-compose.yml # Docker configuration
```
## 故障排除
### 常见问题
**后端无法启动:需要 GitHub OAuth 凭证**
- 在你的 `.env` 文件中设置 `DEV_MODE=true` 以便进行本地开发(将跳过 OAuth)
- 或者从一个 [GitHub OAuth App](#github-oauth-app-setup) 提供 `GITHUB_CLIENT_ID` 和 `GITHUB_CLIENT_SECRET`
**数据库连接错误**
- 确认 PostgreSQL 正在运行:`psql -U postgres -d snorlx`
- 检查 `.env` 中的 `DATABASE_URL` 是否与你的数据库凭证匹配
- 确保已安装 TimescaleDB 扩展
**端口已被占用 (EADDRINUSE)**
- 后端 (8080) 或 前端 (5173) 端口已被占用
- 查找进程:`lsof -i :8080` 或 `lsof -i :5173`
- 终止进程:`kill -9 `
- 或者在 `.env` 中更改端口
**内存模式数据丢失**
- 这是正常的!内存模式在重启之间不会持久化数据
- 使用 `STORAGE_MODE=database` 进行持久化存储
**“Too many requests” 错误**
- 触发了速率限制。请稍后重试
- 在生产环境中,这可以防止滥用
## CI/CD
本项目包含两个 GitHub Actions 工作流:
### CI (`ci.yml`)
在向 `main` 分支推送代码和提交 Pull Request 时运行:
- **后端**:Go vet、带有竞态检测和覆盖率的测试、二进制构建
- **前端**:Lint、带有覆盖率的测试、生产环境构建
### 安全 (`security.yml`)
在向 `main` 分支推送代码、提交 Pull Request 以及每周(UTC 时间周一 08:00)运行:
- **CodeQL 分析**:针对 Go 和 JavaScript/TypeScript 的静态分析
- **Trivy 扫描**:文件系统漏洞扫描,以及对后端和前端的 Docker 镜像扫描
- **依赖审查**:在 PR 上标记新引入的易受攻击的依赖项
- **Go 安全**:针对 Go 特定漏洞执行 govulncheck 和sec
- **npm Audit**:检查 Node 包中已知的漏洞
## 12-Factor App 合规性
本应用遵循 [12-Factor 方法论](https://12factor.net/):
1. **代码库**:在 Git 中跟踪的单一仓库
2. **依赖项**:在 `go.mod` 和 `package.json` 中明确声明
3. **配置**:使用环境变量进行所有配置
4. **后端服务**:通过 URL 将数据库视为附加资源
5. **构建、发布、运行**:带有语义化版本控制的 Docker 镜像
6. **进程**:无状态;会话存储在 storage 中
7. **端口绑定**:自包含的 HTTP 服务器
8. **并发**:通过副本进行水平扩展
9. **易处理**:在收到 SIGTERM 信号时优雅关闭
10. **开发/生产环境一致性**:Docker Compose 映射生产环境
11. **日志**:JSON 格式输出到 stdout,由平台收集
12. **管理进程**:迁移作为启动过程的一部分运行
## 许可证
MIT License - 详情请参阅 [LICENSE](LICENSE)。
标签:EVTX分析, GitHub Actions, MITM代理, 成本分析, 日志审计, 测试用例, 监控面板, 自动笔记, 请求拦截