Litefuse Prompt 的 GitHub 集成
把 Litefuse 的 prompt 与 GitHub 集成有两种方式:
- GitHub Repository Dispatch - 在 prompt 变更时触发 CI/CD 工作流。无需额外的基础设施。
- 把 Litefuse Prompt 同步到仓库 - 把 prompt 存到仓库中的特定文件。需要部署一个 webhook 服务,监听 prompt 版本变更并把它们提交到仓库。
触发 GitHub Actions
通过 repository_dispatch 事件,在 Litefuse prompt 变更时触发 GitHub Actions 工作流。
1. 创建 GitHub Workflow
.github/workflows/litefuse-ci.yml:
name: Litefuse Prompt CI
on:
repository_dispatch:
types: [litefuse-prompt-update]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: |
echo "Testing prompt: ${{ github.event.client_payload.prompt.name }} v${{ github.event.client_payload.prompt.version }}"
# Add your test commands
# npm test
# python -m pytest
deploy:
needs: test
runs-on: ubuntu-latest
if: contains(github.event.client_payload.prompt.labels, 'production')
steps:
- uses: actions/checkout@v4
- name: Deploy to production
run: |
echo "Deploying ${{ github.event.client_payload.prompt.name }} v${{ github.event.client_payload.prompt.version }}"
# Your deployment commands访问 webhook 数据: 使用 github.event.client_payload.* 访问 prompt 数据:
# Example: Access webhook data in your workflow
- name: Process prompt data
run: |
echo "Action: ${{ github.event.client_payload.action }}"
echo "Prompt: ${{ github.event.client_payload.prompt.name }}"
echo "Version: ${{ github.event.client_payload.prompt.version }}"
echo "Labels: ${{ github.event.client_payload.prompt.labels }}"
- name: Deploy only production prompts
if: contains(github.event.client_payload.prompt.labels, 'production')
run: echo "Deploying production prompt"2. 创建用于 Actions 的 GitHub Token
步骤:
- GitHub Settings > Developer settings > Personal access tokens
- Generate new token (classic 或 fine-grained)
- 选择 scope(参见下表)
| Token 类型 | 所需权限 |
|---|---|
| Personal Access Token (classic) | repo scope(公开仓库)或 public_repo scope(私有仓库) |
| Fine-grained PAT 或 GitHub App | actions 的 read 和 write 权限 |
3. 在 Litefuse 中配置 GitHub Action
- 在你的 Litefuse 项目中进入 Prompts > Automations。
- 点击 Create Automation。
- 选择 GitHub Repository Dispatch。
- 配置自动化:
- Dispatch URL:
https://api.github.com/repos/{owner}/{repo}/dispatches(把{owner}和{repo}替换成你的值) - Event Type:
litefuse-prompt-update(必须与你的 GitHub workflow 中的 type 一致) - GitHub Token:填入你的 GitHub Personal Access Token,会被安全存储。
- Dispatch URL:
4. 测试 GitHub Actions 集成
- 在 Litefuse 中更新一个带有
production标签的 prompt - 检查 GitHub Actions 标签页中触发的 workflow
- 确认 test 和 deploy 两个 job 都成功运行
把 Litefuse Prompt 同步到仓库
通过 Prompt Version Webhook,自动把 Litefuse 中的 prompt 变更同步到 GitHub。这样你可以对 prompt 做版本管理,也能在 prompt 变更时触发 CI/CD 工作流。
同步工作流概览
每当你在 Litefuse 中保存新的 prompt 版本,它就会被自动提交到你的 GitHub 仓库。基于这套方案,你也可以在 prompt 变更时触发 CI/CD 工作流。
同步前的准备
- Litefuse 项目: 已完成 prompt 配置,并具备 Project Owner 权限
- GitHub 仓库: 用于存放 prompt 的公开或私有仓库
- GitHub PAT: 具备最小所需权限的 Personal Access Token(详见 Step 2)
- Python 3.9+(下面示例使用,可以是任意语言) 加上 FastAPI、Uvicorn、httpx、Pydantic
- 公开 HTTPS 端点用于你的 webhook 服务(Render、Fly.io、Heroku 等)
Step 1:在 Litefuse 中配置 Prompt Webhook
- 在你的 Litefuse 项目中进入 Prompts > Webhooks
- 点击 Create Webhook
- (可选)筛选事件:选择想接收 webhook 的 prompt 版本事件(默认:
created、updated、deleted) - 设置 endpoint URL:
https://<your-domain>/webhook/prompt - 保存并复制 Signing Secret
注意: 你的端点必须返回 2xx 状态码。Litefuse 会以指数退避的方式重试失败的 webhook。
示例 Webhook Payload
示例 webhook payload:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2024-07-10T10:30:00Z",
"type": "prompt-version",
"action": "created",
"prompt": {
"id": "prompt_abc123",
"name": "movie-critic",
"version": 3,
"projectId": "xyz789",
"labels": ["production", "latest"],
"prompt": "As a {{criticLevel}} movie critic, rate {{movie}} out of 10.",
"type": "text",
"config": { "...": "..." },
"commitMessage": "Improved critic persona",
"tags": ["entertainment"],
"createdAt": "2024-07-10T10:30:00Z",
"updatedAt": "2024-07-10T10:30:00Z"
}
}Step 2:准备好用于同步的 GitHub 仓库与 Token
创建一个 .env 文件,写入你的 GitHub 凭据:
GITHUB_TOKEN=<your_github_pat_here>
GITHUB_REPO_OWNER=<github_username_or_org>
GITHUB_REPO_NAME=<repo_name>
# (Optional) GITHUB_FILE_PATH=litefuse_prompt.json
# (Optional) GITHUB_BRANCH=main
# (Optional) REQUIRED_LABEL=production把占位符替换成你实际的值。默认情况下,服务会把 prompt 提交到 main 分支的 litefuse_prompt.json。如果设置了 REQUIRED_LABEL,那么只有带这个标签的 prompt 会被同步到 GitHub。
用于同步的 GitHub PAT 权限
要让 webhook 工作,你的 GitHub Personal Access Token 需要具备最小权限:
| 权限类型 | 所需权限 |
|---|---|
| 所需权限 | Contents:读写,Metadata:只读 |
| 旧版 Token Scope | 公开仓库:public_repo scope;私有仓库:repo scope |
Step 3:实现 FastAPI Webhook 服务
创建 main.py,写入下面的 FastAPI 服务:
from typing import Any, Dict
from uuid import UUID
import json
import base64
import httpx
from pydantic import BaseModel, Field
from pydantic_settings import BaseSettings, SettingsConfigDict
from fastapi import FastAPI, HTTPException, Body
class GitHubSettings(BaseSettings):
"""GitHub repository configuration."""
GITHUB_TOKEN: str
GITHUB_REPO_OWNER: str
GITHUB_REPO_NAME: str
GITHUB_FILE_PATH: str = "litefuse_prompt.json"
GITHUB_BRANCH: str = "main"
REQUIRED_LABEL: str = "" # Optional: only sync prompts with this label
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=True
)
config = GitHubSettings()
class LitefuseEvent(BaseModel):
"""Litefuse webhook event structure."""
id: UUID = Field(description="Event identifier")
timestamp: str = Field(description="Event timestamp")
type: str = Field(description="Event type")
action: str = Field(description="Performed action")
prompt: Dict[str, Any] = Field(description="Prompt content")
async def sync(event: LitefuseEvent) -> Dict[str, Any]:
"""Synchronize prompt data to GitHub repository."""
# Check if prompt has required label (if specified)
if config.REQUIRED_LABEL:
prompt_labels = event.prompt.get("labels", [])
if config.REQUIRED_LABEL not in prompt_labels:
return {"skipped": f"Prompt does not have required label '{config.REQUIRED_LABEL}'"}
api_endpoint = f"https://api.github.com/repos/{config.GITHUB_REPO_OWNER}/{config.GITHUB_REPO_NAME}/contents/{config.GITHUB_FILE_PATH}"
request_headers = {
"Authorization": f"Bearer {config.GITHUB_TOKEN}",
"Accept": "application/vnd.github.v3+json"
}
content_json = json.dumps(event.prompt, indent=2)
encoded_content = base64.b64encode(content_json.encode("utf-8")).decode("utf-8")
name = event.prompt.get("name", "unnamed")
version = event.prompt.get("version", "unknown")
message = f"{event.action}: {name} v{version}"
payload = {
"message": message,
"content": encoded_content,
"branch": config.GITHUB_BRANCH
}
async with httpx.AsyncClient() as http_client:
try:
existing = await http_client.get(api_endpoint, headers=request_headers, params={"ref": config.GITHUB_BRANCH})
if existing.status_code == 200:
payload["sha"] = existing.json().get("sha")
except Exception:
pass
try:
response = await http_client.put(api_endpoint, headers=request_headers, json=payload)
response.raise_for_status()
return response.json()
except Exception as e:
raise HTTPException(status_code=500, detail=f"Repository sync failed: {str(e)}")
app = FastAPI(title="Litefuse GitHub Sync", version="1.0")
@app.post("/webhook/prompt", status_code=201)
async def receive_webhook(event: LitefuseEvent = Body(...)):
"""Process Litefuse webhook and sync to GitHub."""
result = await sync(event)
return {
"status": "synced",
"commit_info": result.get("commit", {}),
"file_info": result.get("content", {})
}
@app.get("/status")
async def health_status():
"""Service health check."""
return {"healthy": True}服务会校验 webhook payload,必要时获取已有文件的 SHA,并以带描述性的 commit 信息把 prompt 变更提交到 GitHub。
依赖
安装依赖:
pip install fastapi uvicorn pydantic-settings httpx本地运行
本地运行:
uvicorn main:app --reload --port 8000在 http://localhost:8000/health 测试健康检查端点。可以使用 ngrok 等工具把本地端口暴露出去用于 webhook 测试。
Step 4:部署并连接服务
-
部署: 使用 Render、Fly.io、Heroku 或类似平台。设置好环境变量并确保启用了 HTTPS。
-
更新 Webhook: 在 Litefuse 中编辑你的 webhook,把 URL 设为
https://your-domain.com/webhook/prompt。 -
测试: 在 Litefuse 中更新一个 prompt,确认你的 GitHub 仓库中出现了新的 commit。
安全考量
- 校验签名: 使用 signing secret 和
x-litefuse-signatureheader 验证请求 - 限制 PAT 权限: 使用 fine-grained token,限定到具体仓库
- 处理重试: 该实现是幂等的 —— 重复事件不会产生冲突的 commit