接到一个需求: 对特定分支(release/* 分支,类似于 git tag)限制新代码输入,仅限只读和发布用途
然后,在GitHub的分支保护策略中找到了一个 Lock Branch 的配置,正好满足这个功能
于是打算通过脚本批量为所需的仓库添加这个限制
起初打算用原来使用过的 GitHub rest api 实现,尝试了一下,发现接口一直报错,再翻下文档发现这个api不支持设置通配符类型的分支
按照 GitHub 指引只能通过 Graphql API 方式处理这个需求
参考下面两个官方接口文档:
GitHub mutation(突变): createBranchProtectionRule
GitHub 接口输入对象: CreateBranchProtectionRuleInput
脚本核心:
- 获取 repository_id
- 设置带通配符类型(*)的分支保护策略
- 查询当前仓库的所有分支保护策略
完整 shell 脚本
#!/usr/bin/env bash
# GE_TOKEN="ghp_xxxxxxx"
GE_TOKEN="ghp_xxxxxxx"
github_graphql_base_url="https://api.github.com/graphql"
i=1
for file in $(ls ./repository-5/*); do
postfix=$(echo $file | awk -F'.' '{print "."$NF}')
if [[ $postfix = ".repos" ]]; then
echo -e "---- Current file is: $file"
org=$(echo $file | cut -d '/' -f 3 | awk -F '.' '{print $1}')
echo -e "---- Current org is: $org"
if [[ "$org" == "bitestream" || "$org" == "bitesign" ]]; then
# if [[ "$org" == "bitestream" ]]; then
while read -r line; do
if [[ -n $(echo $line | grep "^#") || -z $line ]]; then
continue
else
repo=$(echo $line)
echo -e "\e[32m$i\e[0m. current repository is: \e[0;35m$repo\e[0m"
branch='release/*'
echo -e "---- Going to update branch:$branch protections for \e[0;35m$org/$repo\e[0m 🚀🚀🚀"
if [[ "$org" != "bitearchived" ]]; then
# 1. Get github repository_id via GraphQL mutation
repository_id=$(curl -s -X POST -H "Authorization: bearer $GE_TOKEN" -H "Content-Type: application/json" -d '{
"query": "query { repository(owner: \"'"$org"'\", name: \"'"$repo"'\") { id } }"
}' $github_graphql_base_url | jq -r .data.repository.id)
# 2. create branch protection via GraphQL mutation
if [[ -n "$repository_id" ]]; then
curl -X POST \
-H "Authorization: bearer $GE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation { createBranchProtectionRule(input: { repositoryId: \"'"$repository_id"'\", pattern: \"release/*\", requiresApprovingReviews: false, requiresStatusChecks: false, requiresStrictStatusChecks: false, restrictsPushes: false, requiresCommitSignatures: true, lockBranch: true, allowsDeletions: true }) { clientMutationId } }",
"variables": { "clientMutationId": "MY_TEST_CLIENT_MUTATION_ID" }
}' $github_graphql_base_url
else
echo "---- error: repository_id is empty, exiting..."
exit 1
fi
# 3. Get branch protection via GraphQL mutation
final_branch_protection_list=$(curl -s -X POST \
-H "Authorization: bearer $GE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "query { repository(owner: \"'"$org"'\", name: \"'"$repo"'\") { branchProtectionRules(first: 100) { nodes { id, pattern, requiresApprovingReviews, requiresStatusChecks, requiresStrictStatusChecks, requiresCommitSignatures, restrictsPushes, lockBranch, isAdminEnforced, allowsDeletions } } } }"
}' $github_graphql_base_url | jq -r . | grep "pattern" | grep "release")
if [[ -n $final_branch_protection_list ]]; then
echo -e "---- Congratulations: repository \e[0;35m$org/$repo\e[0m has done! 👏👏👏"
else
echo -e "---- Unfortunate: repository \e[0;35m$org/$repo\e[0m change branch protection failed! ❌❌❌"
echo "$repo" >>../logs/pr-failed/$(date '+%Y-%m-%d').log
fi
fi
let i++
fi
done <$file
i=1
fi
fi
done
echo -e "------------ Congratulations all repositories migration have been done! 👏👏👏"
执行结果部分截图
添加后的 release/* 所有分支保护策略