这份文档用于把当前仓库已经验证过的机制,迁移到另一个 GitHub 仓库中。
目标效果:
执行前先确认以下条件已经满足:
gitgh(GitHub CLI)gh auth status 显示已登录且 token 有 repo、workflow 权限origin建议先执行:
gh auth status
git remote -v
在目标仓库中新增以下文件:
.github/pull_request_template.md
.github/workflows/pr-slack-notify.yml
scripts/create_pr.sh
如果目标仓库没有 scripts/ 目录,可以直接新建。
scripts/create_pr.sh用途:
gh pr create 创建 PR建议内容如下:
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
scripts/create_pr.sh --title "PR title" [--body-file path] [--base main] [--draft]
Description:
Push the current branch to origin and create a GitHub pull request with gh.
Notes:
- This script expects your changes to already be committed.
- If you run it on main, it will stop to avoid opening a PR from the default branch.
- Required tools: git, gh
EOF
}
require_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "Missing required command: $1" >&2
exit 1
fi
}
TITLE=""
BODY_FILE=""
BASE_BRANCH="main"
DRAFT_FLAG=""
while [[ $# -gt 0 ]]; do
case "$1" in
--title)
TITLE="${2:-}"
shift 2
;;
--body-file)
BODY_FILE="${2:-}"
shift 2
;;
--base)
BASE_BRANCH="${2:-}"
shift 2
;;
--draft)
DRAFT_FLAG="--draft"
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown argument: $1" >&2
usage >&2
exit 1
;;
esac
done
if [[ -z "$TITLE" ]]; then
echo "--title is required." >&2
usage >&2
exit 1
fi
if [[ -n "$BODY_FILE" && ! -f "$BODY_FILE" ]]; then
echo "Body file not found: $BODY_FILE" >&2
exit 1
fi
require_cmd git
require_cmd gh
CURRENT_BRANCH="$(git branch --show-current)"
if [[ -z "$CURRENT_BRANCH" ]]; then
echo "Could not determine current branch." >&2
exit 1
fi
if [[ "$CURRENT_BRANCH" == "$BASE_BRANCH" ]]; then
echo "Current branch is $BASE_BRANCH. Please create a feature branch before opening a PR." >&2
exit 1
fi
if [[ -n "$(git status --porcelain)" ]]; then
echo "Working tree is not clean. Please commit or stash changes before creating a PR." >&2
exit 1
fi
echo "Pushing branch $CURRENT_BRANCH to origin..."
git push -u origin "$CURRENT_BRANCH"
PR_ARGS=(
pr create
--base "$BASE_BRANCH"
--head "$CURRENT_BRANCH"
--title "$TITLE"
)
if [[ -n "$BODY_FILE" ]]; then
PR_ARGS+=(--body-file "$BODY_FILE")
else
PR_ARGS+=(--fill)
fi
if [[ -n "$DRAFT_FLAG" ]]; then
PR_ARGS+=("$DRAFT_FLAG")
fi
echo "Creating pull request..."
gh "${PR_ARGS[@]}"
添加后执行:
chmod +x scripts/create_pr.sh
.github/pull_request_template.md这个文件不是必须,但建议统一 PR 结构。
建议内容:
## Summary
-
## Validation
-
## Notes
-
.github/workflows/pr-slack-notify.yml这个工作流负责在 PR 生命周期关键节点把通知发到 Slack。
为什么用
pull_request_target而不是pull_request? GitHub 出于安全考虑,pull_request事件来自 fork 时不会注入 secrets,导致SLACK_WEBHOOK_URL为空、通知跳过。pull_request_target在目标仓库的上下文中运行,可以访问 secrets。这个 workflow 只发通知、不 checkout 或执行 PR 中的代码,所以安全上没有问题。
建议内容如下:
name: PR Slack Notify
on:
pull_request_target:
types:
- opened
- reopened
- ready_for_review
- synchronize
- closed
jobs:
notify:
runs-on: ubuntu-latest
env:
SLACK_WEBHOOK_URL: $
steps:
- name: Skip when webhook is not configured
if: $
run: |
echo "SLACK_WEBHOOK_URL is not configured; skipping notification."
- name: Build message payload
if: $
id: payload
env:
REPO: $
ACTION: $
PR_NUMBER: $
PR_TITLE: $
PR_URL: $
PR_AUTHOR: $
BASE_REF: $
HEAD_REF: $
MERGED: $
run: |
node - <<'NODE' >> "$GITHUB_OUTPUT"
const action = process.env.ACTION;
const merged = process.env.MERGED === "true";
let status = "updated";
if (action === "opened") status = "opened";
if (action === "reopened") status = "reopened";
if (action === "ready_for_review") status = "ready for review";
if (action === "closed") status = merged ? "merged" : "closed";
const text = [
`GitHub PR ${status}: #${process.env.PR_NUMBER} ${process.env.PR_TITLE}`,
`Repo: ${process.env.REPO}`,
`Author: ${process.env.PR_AUTHOR}`,
`Branch: ${process.env.HEAD_REF} -> ${process.env.BASE_REF}`,
`URL: ${process.env.PR_URL}`,
].join("\n");
process.stdout.write(`payload=${JSON.stringify({ text })}\n`);
NODE
- name: Send Slack notification
if: $
env:
PAYLOAD: $
run: |
curl -sS -X POST \
-H 'Content-Type: application/json' \
--data "$PAYLOAD" \
"$SLACK_WEBHOOK_URL"
不要把 Slack Webhook URL 写进仓库文件。
应该配置到目标仓库的 GitHub Secret:
SLACK_WEBHOOK_URL配置路径:
GitHub 仓库 -> Settings -> Secrets and variables -> Actions -> New repository secret
建议在目标仓库按下面顺序执行:
codex/pr-automation-slack-notify示例命令:
git checkout -b codex/pr-automation-slack-notify
git add .github scripts
git commit -m "Add PR automation and Slack notification workflow"
scripts/create_pr.sh --title "Add PR automation and Slack notification workflow" --body-file .github/pull_request_template.md
gh auth status
预期结果:
repo 与 workflow 权限gh run list --limit 10
预期结果:
PR Slack Notifypull_requestsuccess预期至少会在以下时机收到通知:
gh auth status 显示 token invalid处理方式:
gh auth login
如果之前登录错了账号,也可以先:
gh auth logout -h github.com -u <username>
gh auth login
优先检查:
if 中不兼容地引用了 secretsnode 脚本块是否完整建议优先使用本手册里的工作流内容,不要自行改写触发和判断逻辑。
优先检查:
SLACK_WEBHOOK_URL 是否配置在正确仓库main处理方式:
例如:
git checkout -b codex/your-feature-name
处理方式:
脚本这样设计是为了避免把半成品直接推上去创建 PR。
如果你想继续增强这套机制,可以考虑:
如果你只想快速复用,最少做这几步:
scripts/create_pr.sh.github/workflows/pr-slack-notify.ymlSLACK_WEBHOOK_URLchmod +x scripts/create_pr.sh做到这一步,这套机制就算迁移完成了。