guanghulab/.github/workflows/.archive/training-bootstrap.yml
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

223 lines
11 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ═══════════════════════════════════════════════════════════
# 🛠️ GPU 训练机 Bootstrap · training-bootstrap.yml
# ═══════════════════════════════════════════════════════════
# 签发: 铸渊 · ICE-GL-ZY001
# 版权: 国作登字-2026-A-00037559 · TCS-0002∞
#
# 把 server/training-agent/ 下的脚本 SCP 到 GPU 训练机
# (zy-gpu-train · 119.45.160.137),写入 .env触发 setup.sh。
# 全程心跳→训练实时仪表盘。
#
# 必需 Secrets:
# ZY_GPU_HOST 119.45.160.137
# ZY_GPU_USER ubuntu
# ZY_GPU_KEY SSH 私钥
# ZY_COS_SECRET_ID 腾讯云 SecretId
# ZY_COS_SECRET_KEY 腾讯云 SecretKey
# ZY_DISPATCH_TOKEN 仓库 dispatch PAT (servers→github 心跳所需)
# ⚠️ 需要冰朔在 Settings > Secrets 新建一个 PAT,
# 权限: repo (classic) 或 contents+actions (fine-grained)
# 作用域: 仅本仓库
# ═══════════════════════════════════════════════════════════
name: 🛠️ 训练机 Bootstrap
# ⚠️ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 2026-05-03 D72训练机自动同步已停用。母模型训练转交 Notion 侧
# 霜砚 + 服务器直接协作。SSH/SCP 操作必须 confirm_override=true。
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
on:
workflow_dispatch:
inputs:
confirm_override:
description: '⚠️ 我已确认霜砚同意 + 服务器无运行中训练,重新启用 bootstrap'
type: boolean
default: false
action:
description: '动作'
required: true
default: 'probe'
type: choice
options:
- probe # 仅探活 SSHsafe
- status # 查询状态safe
- bootstrap # 上传脚本 + 跑 setup.sh
- sync-scripts # 仅上传脚本(不跑 setup
- start # 启动训练tmux
- stop # 停训练
permissions:
contents: read
concurrency:
group: training-bootstrap
cancel-in-progress: false
jobs:
guard:
name: '🛑 同步停用守卫'
runs-on: ubuntu-latest
outputs:
proceed: ${{ steps.check.outputs.proceed }}
steps:
- name: 检查覆盖确认
id: check
run: |
ACTION="${{ github.event.inputs.action }}"
# probe / status 两个只读动作允许通过 (不修改服务器状态)
if [[ "$ACTION" == "probe" || "$ACTION" == "status" ]]; then
echo " 只读动作 ($ACTION),允许执行"
echo "proceed=true" >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ "${{ github.event.inputs.confirm_override }}" == "true" ]]; then
echo "✅ 收到覆盖确认 + 写动作 ($ACTION),继续"
echo "proceed=true" >> "$GITHUB_OUTPUT"
else
echo "🛑 写动作 ($ACTION) 需要勾选 confirm_override本次中止"
echo "proceed=false" >> "$GITHUB_OUTPUT"
{
echo "## 🛑 训练机 Bootstrap 已停用"
echo ""
echo "动作 \`$ACTION\` 会修改服务器状态,已被 D72 决策保护。"
echo "如需执行,请勾选 \`confirm_override\` 后再触发。"
echo ""
echo "只读动作 \`probe\` / \`status\` 不需要勾选。"
} >> "$GITHUB_STEP_SUMMARY"
fi
bootstrap:
name: '🚀 ${{ github.event.inputs.action }}'
needs: guard
if: needs.guard.outputs.proceed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: 📥 Checkout
uses: actions/checkout@v4
- name: 🔑 配置 SSH
run: |
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "${{ secrets.ZY_GPU_KEY }}" > ~/.ssh/zy_gpu_key
chmod 600 ~/.ssh/zy_gpu_key
ssh-keyscan -H "${{ secrets.ZY_GPU_HOST }}" >> ~/.ssh/known_hosts 2>/dev/null
- name: 🛰️ 探活
run: |
ssh -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no -o ConnectTimeout=15 \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"echo '✅ SSH OK · $(hostname) · uptime:' && uptime && echo '--- nvidia ---' && (nvidia-smi --query-gpu=name,driver_version,memory.total --format=csv,noheader || echo '驱动尚未就绪')"
- name: 📡 上报 Bootstrap 开始
if: github.event.inputs.action == 'bootstrap' || github.event.inputs.action == 'start'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -sS -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GH_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/${{ github.repository }}/dispatches" \
-d '{
"event_type": "training-progress",
"client_payload": {
"phase": "bootstrapping",
"phase_label": "铸渊触发 ${{ github.event.inputs.action }}",
"level": "info",
"message": "training-bootstrap.yml run #${{ github.run_number }} 触发动作=${{ github.event.inputs.action }}",
"health": { "status": "ok", "message": "bootstrap workflow 启动" }
}
}' || true
- name: 📤 上传脚本到服务器
if: github.event.inputs.action == 'bootstrap' || github.event.inputs.action == 'sync-scripts' || github.event.inputs.action == 'start' || github.event.inputs.action == 'stop'
run: |
ssh -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
'sudo mkdir -p /opt/guanghu/training/configs && sudo chown -R ${{ secrets.ZY_GPU_USER }}:${{ secrets.ZY_GPU_USER }} /opt/guanghu/training'
scp -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no \
server/training-agent/progress-reporter.sh \
server/training-agent/setup.sh \
server/training-agent/start-training.sh \
server/training-agent/watch-training-output.sh \
server/training-agent/download-model.py \
server/training-agent/preprocess-corpus.py \
server/training-agent/train.py \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}:/opt/guanghu/training/"
scp -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no \
server/training-agent/configs/ds_zero3_offload.json \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}:/opt/guanghu/training/configs/"
- name: 🔐 写入 .env (服务器侧)
if: github.event.inputs.action == 'bootstrap' || github.event.inputs.action == 'sync-scripts'
env:
ZY_COS_SECRET_ID: ${{ secrets.ZY_COS_SECRET_ID }}
ZY_COS_SECRET_KEY: ${{ secrets.ZY_COS_SECRET_KEY }}
ZY_DISPATCH_TOKEN: ${{ secrets.ZY_DISPATCH_TOKEN }}
REPO_OWNER: ${{ github.repository_owner }}
REPO_NAME: ${{ github.event.repository.name }}
run: |
# 通过 stdin 写,避免在命令行/参数列表中暴露 secrets
ssh -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"umask 077 && cat > /opt/guanghu/training/.env && chmod 600 /opt/guanghu/training/.env" <<EOF
ZY_COS_SECRET_ID=${ZY_COS_SECRET_ID}
ZY_COS_SECRET_KEY=${ZY_COS_SECRET_KEY}
ZY_COS_BUCKET=sy-finetune-corpus-1317346199
ZY_COS_REGION=ap-guangzhou
GH_REPO_OWNER=${REPO_OWNER}
GH_REPO_NAME=${REPO_NAME}
GH_DISPATCH_TOKEN=${ZY_DISPATCH_TOKEN}
ZY_TRAIN_ROOT=/opt/guanghu/training
ZY_TRAIN_DATA=/data/guanghu
EOF
ssh -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"chmod +x /opt/guanghu/training/*.sh"
- name: 🛠️ 执行 setup.sh
if: github.event.inputs.action == 'bootstrap'
run: |
ssh -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"sudo -E bash /opt/guanghu/training/setup.sh 2>&1 | tee /tmp/zy-bootstrap.log; tail -c 4000 /tmp/zy-bootstrap.log"
- name: ▶️ 启动训练 (tmux)
if: github.event.inputs.action == 'start'
run: |
ssh -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"bash /opt/guanghu/training/start-training.sh --tmux"
- name: ⏹️ 停止训练
if: github.event.inputs.action == 'stop'
run: |
ssh -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"bash /opt/guanghu/training/start-training.sh --stop"
- name: 📊 查询状态
if: github.event.inputs.action == 'status'
run: |
ssh -i ~/.ssh/zy_gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"echo '=== 阶段 ===' && cat /opt/guanghu/training/.phase 2>/dev/null || echo idle; \
echo '=== tmux ===' && (tmux ls 2>/dev/null || echo no-tmux); \
echo '=== nvidia-smi ===' && nvidia-smi --query-gpu=index,name,utilization.gpu,memory.used,memory.total,temperature.gpu --format=csv 2>/dev/null || echo no-gpu; \
echo '=== disk ===' && df -h /data/guanghu 2>/dev/null || df -h /; \
echo '=== last log lines ===' && tail -n 40 /opt/guanghu/training/training.log 2>/dev/null || echo no-log"
- name: 📝 摘要
if: always()
run: |
{
echo "## 训练机操作: \`${{ github.event.inputs.action }}\`"
echo ""
echo "- 服务器: \`${{ secrets.ZY_GPU_HOST }}\`"
echo "- 时间: $(date -u '+%Y-%m-%dT%H:%M:%SZ')"
echo "- Run #: ${{ github.run_number }}"
} >> "$GITHUB_STEP_SUMMARY"