ci(部署): 手动触发可放行破坏性迁移,push 触发永远不放行
Some checks failed
Deploy / deploy (push) Has been cancelled

deploy.sh 现在会在起栈前跑迁移,但 CI 没法传 OJ2_ALLOW_DESTRUCTIVE,
于是任何破坏性迁移都会让自动部署一直红着,且没有出口。

给 workflow_dispatch 加一个 allow_destructive 布尔 input,经 env: 传到
ssh 命令里。push 触发拿不到 inputs,值恒为空 —— 也就是说**自动部署永远
不会执行 DROP TABLE 之类的迁移**,只会停在闸门上把工作流判红。这是有意的:
那种改动得有人先确认备份,不该由一次 git push 顺带完成。

日常的加索引 / 加列属于非破坏性,CI 部署会照常自动执行,无需干预。

留了一条注释标明必须用 `inputs.` 而不是 `github.event.inputs.`:后者会把
布尔字符串化,没勾选时拿到字符串 "false",那是非空字符串、在 `&&` 里为真,
等于每次手动部署都无条件放行。

验证:本机 YAML 解析通过,确认 inputs 定义挂在 workflow_dispatch 下。
表达式三种情况的语义(勾选 → '1'、未勾选 → ''、push 事件 inputs 为空 → '')
是 GitHub 表达式的既定行为,要真的 push 到 github 才跑得起来。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 08:38:47 -06:00
parent 5f04f3283f
commit 64cb7b62ef

View File

@@ -21,7 +21,15 @@ on:
push: push:
branches: branches:
- main - main
# 手动触发时可以放行破坏性迁移。push 触发拿不到这个 input值恒为空 ——
# 也就是说**自动部署永远不会执行 DROP TABLE 之类的迁移**,只会停在闸门上把
# 工作流判红。这是有意的:那种改动得有人先确认备份。
workflow_dispatch: workflow_dispatch:
inputs:
allow_destructive:
description: "放行破坏性迁移DROP TABLE / DROP COLUMN / ALTER TYPE …)。勾之前先确认已备份数据库。"
type: boolean
default: false
permissions: permissions:
contents: read contents: read
@@ -100,9 +108,20 @@ jobs:
--exclude 'docker/.env*' \ --exclude 'docker/.env*' \
./ "root@${{ secrets.HOST }}:$REMOTE_DIR/" ./ "root@${{ secrets.HOST }}:$REMOTE_DIR/"
# deploy.sh 自检不过 / 容器没起来 / 冒烟发现题目数是 0都会非零退出 # deploy.sh 自检不过 / 迁移被拦 / 容器没起来 / 冒烟发现题目数是 0都会非零退出
# 这一步跟着红,日志里能看到具体是哪一条。 # 这一步跟着红,日志里能看到具体是哪一条。
#
# 迁移在 deploy.sh 里排在起栈之前:非破坏性的(加索引、加列)自动执行;
# 破坏性的会被拦下并退出 4除非手动触发时勾了 allow_destructive。
# 走 env: 传而不是把 ${{ }} 直接拼进命令串 —— 值虽然是 GitHub 约束过的布尔,
# 但拼字符串进 shell 的写法不该在这个仓库里留下先例。
#
# ⚠️ 必须用 `inputs.`**不能换成 `github.event.inputs.`**。后者把布尔
# 字符串化,没勾选时拿到的是字符串 "false" —— 那是个非空字符串,在
# `&&` 里为真,等于每次手动部署都无条件放行破坏性迁移。
- name: 起栈 - name: 起栈
env:
ALLOW_DESTRUCTIVE: ${{ inputs.allow_destructive && '1' || '' }}
run: | run: |
ssh -i ~/.ssh/id_deploy -p "$REMOTE_PORT" "root@${{ secrets.HOST }}" \ ssh -i ~/.ssh/id_deploy -p "$REMOTE_PORT" "root@${{ secrets.HOST }}" \
"cd $REMOTE_DIR && docker/deploy.sh --prebuilt" "cd $REMOTE_DIR && OJ2_ALLOW_DESTRUCTIVE='$ALLOW_DESTRUCTIVE' docker/deploy.sh --prebuilt"