跨境上传 130 MB 镜像 40 分钟没传完。改为服务器从 origin(git.xuyue.cc)拉代码、 构建镜像、重启,等编译服务就绪;提交还没到 origin 时等待重试。 部署任务加 20 分钟超时,SSH 认证失败立即报错。去掉 deploy/deploy.sh。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
103 lines
3.6 KiB
YAML
103 lines
3.6 KiB
YAML
# 每次推送和 PR 都跑测试;推送到 main 且测试通过后,SSH 到服务器执行 deploy/update.sh(服务器从 origin 拉代码、构建、重启)。
|
||
# 部署需要的 Secrets 见 deploy/README.md 的"自动部署"一节。
|
||
# 只在 github.com 上运行;仓库同时推到 git.xuyue.cc,那边的 Gitea Actions 也会读这个目录,用 if 跳过。
|
||
name: CI/CD
|
||
|
||
on:
|
||
push:
|
||
branches: [main]
|
||
pull_request:
|
||
# 在 Actions 页面手动重新部署(比如改了服务器上的 .env 之后)
|
||
workflow_dispatch:
|
||
|
||
jobs:
|
||
test:
|
||
if: github.server_url == 'https://github.com'
|
||
runs-on: ubuntu-24.04
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- uses: oven-sh/setup-bun@v2
|
||
with:
|
||
bun-version: 1.4.3
|
||
|
||
- uses: actions/setup-dotnet@v4
|
||
with:
|
||
dotnet-version: 10.0.x
|
||
|
||
# 测试里学生程序在 bubblewrap 沙箱中运行;Ubuntu 24.04 默认禁止非特权用户命名空间,要先放开
|
||
- name: 准备沙箱
|
||
run: |
|
||
sudo apt-get update -q
|
||
sudo apt-get install -y -q bubblewrap
|
||
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
||
|
||
- run: bun install --frozen-lockfile
|
||
|
||
- name: 编译 C# 运行时
|
||
run: bun run build:runtime
|
||
|
||
- name: 服务端测试(编译并运行示例、沙箱、编译检查)
|
||
working-directory: server
|
||
run: bun test
|
||
|
||
- name: 网页端测试和类型检查
|
||
working-directory: web
|
||
run: |
|
||
bun test src
|
||
bunx vue-tsc --noEmit
|
||
|
||
deploy:
|
||
needs: test
|
||
if: github.server_url == 'https://github.com' && github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
||
runs-on: ubuntu-24.04
|
||
# 服务器构建约几分钟;卡住时及时失败,不要一直占着
|
||
timeout-minutes: 20
|
||
# 连续推送时排队部署,不会两次部署同时进行
|
||
concurrency:
|
||
group: deploy
|
||
cancel-in-progress: false
|
||
environment: production
|
||
steps:
|
||
# Secrets 还没配置时跳过部署(只跑测试),不算失败
|
||
- name: 检查部署配置
|
||
id: check
|
||
env:
|
||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||
run: |
|
||
if [ -n "$DEPLOY_HOST" ]; then
|
||
echo "configured=true" >> "$GITHUB_OUTPUT"
|
||
else
|
||
echo "::notice::没有配置 DEPLOY_HOST 等 Secrets,跳过部署(配置方法见 deploy/README.md)"
|
||
fi
|
||
|
||
- name: 配置 SSH
|
||
if: steps.check.outputs.configured == 'true'
|
||
env:
|
||
SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||
run: |
|
||
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
||
printf '%s\n' "$SSH_KEY" > ~/.ssh/deploy_key
|
||
chmod 600 ~/.ssh/deploy_key
|
||
cat > ~/.ssh/config <<EOF
|
||
Host deploy-target
|
||
HostName $DEPLOY_HOST
|
||
User $DEPLOY_USER
|
||
Port ${DEPLOY_PORT:-22}
|
||
IdentityFile ~/.ssh/deploy_key
|
||
IdentitiesOnly yes
|
||
# 不预先登记服务器公钥,第一次连接时自动接受
|
||
StrictHostKeyChecking accept-new
|
||
# 认证失败立即报错,不等输入密码
|
||
BatchMode yes
|
||
ConnectTimeout 30
|
||
ServerAliveInterval 30
|
||
EOF
|
||
|
||
- name: 部署(在服务器上拉代码、构建、重启)
|
||
if: steps.check.outputs.configured == 'true'
|
||
run: ssh deploy-target "cd ${{ vars.DEPLOY_DIR || 'IOT_SIM' }} && deploy/update.sh ${{ github.sha }}"
|