mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-23 21:20:42 +08:00
模块化 PR 检查
This commit is contained in:
parent
6a57b4dcc9
commit
a31b145df9
@ -1,3 +1,3 @@
|
||||
language: c
|
||||
script:
|
||||
- make -s check
|
||||
- sh ./scripts/check.sh
|
||||
|
58
Makefile
58
Makefile
@ -1,58 +0,0 @@
|
||||
DIR_PATTERN := (news|talk|tech)
|
||||
NAME_PATTERN := [0-9]{8} [a-zA-Z0-9_.,() -]*\.md
|
||||
|
||||
RULES := rule-source-added \
|
||||
rule-translation-requested \
|
||||
rule-translation-completed \
|
||||
rule-translation-revised \
|
||||
rule-translation-published
|
||||
.PHONY: check match $(RULES)
|
||||
|
||||
CHANGE_FILE := /tmp/changes
|
||||
|
||||
check: $(CHANGE_FILE)
|
||||
echo 'PR #$(TRAVIS_PULL_REQUEST) Changes:'
|
||||
cat $(CHANGE_FILE)
|
||||
echo
|
||||
echo 'Check for rules...'
|
||||
make -k $(RULES) 2>/dev/null | grep '^Rule Matched: '
|
||||
|
||||
$(CHANGE_FILE):
|
||||
git --no-pager diff $(TRAVIS_BRANCH) origin/master --no-renames --name-status > $@
|
||||
|
||||
rule-source-added:
|
||||
echo 'Unmatched Files:'
|
||||
egrep -v '^A\s*"?sources/$(DIR_PATTERN)/$(NAME_PATTERN)"?' $(CHANGE_FILE) || true
|
||||
echo '[End of Unmatched Files]'
|
||||
[ $(shell egrep '^A\s*"?sources/$(DIR_PATTERN)/$(NAME_PATTERN)"?' $(CHANGE_FILE) | wc -l) -ge 1 ]
|
||||
[ $(shell egrep -v '^A\s*"?sources/$(DIR_PATTERN)/$(NAME_PATTERN)"?' $(CHANGE_FILE) | wc -l) = 0 ]
|
||||
echo 'Rule Matched: $(@)'
|
||||
|
||||
rule-translation-requested:
|
||||
[ $(shell egrep '^M\s*"?sources/$(DIR_PATTERN)/$(NAME_PATTERN)"?' $(CHANGE_FILE) | wc -l) = 1 ]
|
||||
[ $(shell cat $(CHANGE_FILE) | wc -l) = 1 ]
|
||||
echo 'Rule Matched: $(@)'
|
||||
|
||||
rule-translation-completed:
|
||||
[ $(shell egrep '^D\s*"?sources/$(DIR_PATTERN)/$(NAME_PATTERN)"?' $(CHANGE_FILE) | wc -l) = 1 ]
|
||||
[ $(shell egrep '^A\s*"?translated/$(DIR_PATTERN)/$(NAME_PATTERN)"?' $(CHANGE_FILE) | wc -l) = 1 ]
|
||||
[ $(shell cat $(CHANGE_FILE) | wc -l) = 2 ]
|
||||
echo 'Rule Matched: $(@)'
|
||||
|
||||
rule-translation-revised:
|
||||
[ $(shell egrep '^M\s*"?translated/$(DIR_PATTERN)/$(NAME_PATTERN)"?' $(CHANGE_FILE) | wc -l) = 1 ]
|
||||
[ $(shell cat $(CHANGE_FILE) | wc -l) = 1 ]
|
||||
echo 'Rule Matched: $(@)'
|
||||
|
||||
rule-translation-published:
|
||||
[ $(shell egrep '^D\s*"?translated/$(DIR_PATTERN)/$(NAME_PATTERN)"?' $(CHANGE_FILE) | wc -l) = 1 ]
|
||||
[ $(shell egrep '^A\s*"?published/$(NAME_PATTERN)' $(CHANGE_FILE) | wc -l) = 1 ]
|
||||
[ $(shell cat $(CHANGE_FILE) | wc -l) = 2 ]
|
||||
echo 'Rule Matched: $(@)'
|
||||
|
||||
badge:
|
||||
mkdir -p build/badge
|
||||
./lctt-scripts/show_status.sh -s published >build/badge/published.svg
|
||||
./lctt-scripts/show_status.sh -s translated >build/badge/translated.svg
|
||||
./lctt-scripts/show_status.sh -s translating >build/badge/translating.svg
|
||||
./lctt-scripts/show_status.sh -s sources >build/badge/sources.svg
|
10
scripts/check.sh
Normal file
10
scripts/check.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# PR 检查脚本
|
||||
set -e
|
||||
|
||||
CHECK_DIR="$(dirname "$0")/check"
|
||||
# sh "${CHECK_DIR}/check.sh" # 需要依赖,暂时禁用
|
||||
sh "${CHECK_DIR}/info.sh"
|
||||
sh "${CHECK_DIR}/collect.sh"
|
||||
sh "${CHECK_DIR}/analyze.sh"
|
||||
sh "${CHECK_DIR}/identify.sh"
|
43
scripts/check/analyze.sh
Normal file
43
scripts/check/analyze.sh
Normal file
@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
# PR 文件变更分析
|
||||
set -e
|
||||
|
||||
# 加载公用常量和函数
|
||||
# shellcheck source=common.inc.sh
|
||||
. "$(dirname "$0")/common.inc.sh"
|
||||
|
||||
################################################################################
|
||||
# 读入:
|
||||
# - /tmp/changes # 文件变更列表
|
||||
# 写出:
|
||||
# - /tmp/stats # 文件变更统计
|
||||
################################################################################
|
||||
|
||||
# 执行分析并将统计输出到标准输出
|
||||
do_analyze() {
|
||||
cat /dev/null > /tmp/stats
|
||||
OTHER_REGEX='^$'
|
||||
for TYPE in 'SRC' 'TSL' 'PUB'; do
|
||||
for STAT in 'A' 'M' 'D'; do
|
||||
# 统计每个类别的每个操作
|
||||
REGEX="$(get_operation_regex "$STAT" "$TYPE")"
|
||||
OTHER_REGEX="${OTHER_REGEX}|${REGEX}"
|
||||
eval "${TYPE}_${STAT}=\"\$(grep -Ec '$REGEX' /tmp/changes)\"" || true
|
||||
eval echo "${TYPE}_${STAT}=\$${TYPE}_${STAT}"
|
||||
done
|
||||
done
|
||||
|
||||
# 统计其他操作
|
||||
OTHER="$(grep -Evc "$OTHER_REGEX" /tmp/changes)" || true
|
||||
echo "OTHER=$OTHER"
|
||||
|
||||
# 统计变更总数
|
||||
TOTAL="$(wc -l < /tmp/changes )"
|
||||
echo "TOTAL=$TOTAL"
|
||||
}
|
||||
|
||||
|
||||
echo "[分析] 统计文件变更……"
|
||||
do_analyze > /tmp/stats
|
||||
echo "[分析] 已写入统计结果:"
|
||||
cat /tmp/stats
|
10
scripts/check/check.sh
Normal file
10
scripts/check/check.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# 检查脚本状态
|
||||
set -e
|
||||
|
||||
################################################################################
|
||||
# 暂时仅供开发使用
|
||||
################################################################################
|
||||
|
||||
shellcheck -e SC2034 -x mock/stats.sh "$(dirname "$0")"/*.sh \
|
||||
&& echo '[检查] ShellCheck 通过'
|
32
scripts/check/collect.sh
Normal file
32
scripts/check/collect.sh
Normal file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
# PR 文件变更收集
|
||||
set -e
|
||||
|
||||
################################################################################
|
||||
# 读入:(无)
|
||||
# 写出:
|
||||
# - /tmp/changes # 文件变更列表
|
||||
################################################################################
|
||||
|
||||
|
||||
echo "[收集] 计算 PR 分支与目标分支的分叉点……"
|
||||
|
||||
TARGET_BRANCH="${TRAVIS_BRANCH:-master}"
|
||||
echo "[收集] 目标分支设定为:${TARGET_BRANCH}"
|
||||
|
||||
MERGE_BASE="$(git merge-base "$TARGET_BRANCH" FETCH_HEAD)"
|
||||
echo "[收集] 找到分叉节点:${MERGE_BASE}"
|
||||
|
||||
{
|
||||
git log --oneline "${MERGE_BASE}..FETCH_HEAD" | grep -Eq '^绕过检查:' && {
|
||||
touch /tmp/bypass
|
||||
echo "[收集] 已标记为绕过检查项"
|
||||
}
|
||||
} || true
|
||||
|
||||
echo "[收集] 写出文件变更列表……"
|
||||
|
||||
git diff "$MERGE_BASE" FETCH_HEAD --no-renames --name-status > /tmp/changes
|
||||
echo "[收集] 已写出文件变更列表:"
|
||||
cat /tmp/changes
|
||||
{ [ -z "$(cat /tmp/changes)" ] && echo "(无变更)"; } || true
|
30
scripts/check/common.inc.sh
Normal file
30
scripts/check/common.inc.sh
Normal file
@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
|
||||
################################################################################
|
||||
# 公用常量和函数
|
||||
################################################################################
|
||||
|
||||
# 定义类别目录
|
||||
export SRC_DIR='sources' # 未翻译
|
||||
export TSL_DIR='translated' # 已翻译
|
||||
export PUB_DIR='published' # 已发布
|
||||
|
||||
# 定义匹配规则
|
||||
export CATE_PATTERN='(news|talk|tech)' # 类别
|
||||
export FILE_PATTERN='[0-9]{8} [a-zA-Z0-9_.,() -]*\.md' # 文件名
|
||||
|
||||
# 用法:get_operation_regex 状态 类型
|
||||
#
|
||||
# 状态为:
|
||||
# - A:添加
|
||||
# - M:修改
|
||||
# - D:删除
|
||||
# 类型为:
|
||||
# - SRC:未翻译
|
||||
# - TSL:已翻译
|
||||
# - PUB:已发布
|
||||
get_operation_regex() {
|
||||
STAT="$1"
|
||||
TYPE="$2"
|
||||
echo "^${STAT}\\s+\"?$(eval echo "\$${TYPE}_DIR")/"
|
||||
}
|
86
scripts/check/identify.sh
Normal file
86
scripts/check/identify.sh
Normal file
@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
# 匹配 PR 规则
|
||||
set -e
|
||||
|
||||
################################################################################
|
||||
# 读入:
|
||||
# - /tmp/stats
|
||||
# 写出:(无)
|
||||
################################################################################
|
||||
|
||||
# 加载公用常量和函数
|
||||
# shellcheck source=common.inc.sh
|
||||
. "$(dirname "$0")/common.inc.sh"
|
||||
|
||||
echo "[匹配] 加载统计结果……"
|
||||
# 加载统计结果
|
||||
# shellcheck source=mock/stats.sh
|
||||
. /tmp/stats
|
||||
|
||||
# 定义 PR 规则
|
||||
|
||||
# 绕过检查:绕过 PR 检查
|
||||
rule_bypass_check() {
|
||||
[ -f /tmp/bypass ] && echo "匹配规则:绕过检查"
|
||||
}
|
||||
|
||||
# 添加原文:添加至少一篇原文
|
||||
rule_source_added() {
|
||||
[ "$SRC_A" -ge 1 ] \
|
||||
&& [ "$TOTAL" -eq "$SRC_A" ] && echo "匹配规则:添加原文 ${SRC_A} 篇"
|
||||
}
|
||||
|
||||
# 申领翻译:只能申领一篇原文
|
||||
rule_translation_requested() {
|
||||
[ "$SRC_M" -eq 1 ] \
|
||||
&& [ "$TOTAL" -eq 1 ] && echo "匹配规则:申领翻译"
|
||||
}
|
||||
|
||||
# 提交译文:只能提交一篇译文
|
||||
rule_translation_completed() {
|
||||
[ "$SRC_D" -eq 1 ] && [ "$TSL_A" -eq 1 ] \
|
||||
&& [ "$TOTAL" -eq 2 ] && echo "匹配规则:提交译文"
|
||||
}
|
||||
|
||||
# 校对译文:只能校对一篇
|
||||
rule_translation_revised() {
|
||||
[ "$TSL_M" -eq 1 ] \
|
||||
&& [ "$TOTAL" -eq 1 ] && echo "匹配规则:校对译文"
|
||||
}
|
||||
|
||||
# 发布译文:发布多篇译文
|
||||
rule_translation_published() {
|
||||
[ "$TSL_D" -ge 1 ] && [ "$PUB_A" -ge 1 ] && [ "$TSL_D" -eq "$PUB_A" ] \
|
||||
&& [ "$TOTAL" -eq $(("$TSL_D" + "$PUB_A")) ] \
|
||||
&& echo "匹配规则:发布译文 ${PUB_A} 篇"
|
||||
}
|
||||
|
||||
# 定义常见错误
|
||||
|
||||
# 未知错误
|
||||
error_undefined() {
|
||||
echo "未知错误:无匹配规则,请尝试只对一篇文章进行操作"
|
||||
}
|
||||
|
||||
# 申领多篇
|
||||
error_translation_requested_multiple() {
|
||||
[ "$SRC_M" -gt 1 ] \
|
||||
&& echo "匹配错误:申领多篇,请一次仅申领一篇"
|
||||
}
|
||||
|
||||
# 执行检查并输出匹配项目
|
||||
do_check() {
|
||||
rule_bypass_check \
|
||||
|| rule_source_added \
|
||||
|| rule_translation_requested \
|
||||
|| rule_translation_completed \
|
||||
|| rule_translation_revised \
|
||||
|| rule_translation_published \
|
||||
|| {
|
||||
error_translation_requested_multiple \
|
||||
|| error_undefined
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
do_check
|
4
scripts/check/info.sh
Normal file
4
scripts/check/info.sh
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 打印 PR 信息
|
||||
echo ""
|
13
scripts/check/mock/stats.sh
Normal file
13
scripts/check/mock/stats.sh
Normal file
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
# 给 ShellCheck 用的 Mock 统计
|
||||
SRC_A=0
|
||||
SRC_M=0
|
||||
SRC_D=0
|
||||
TSL_A=0
|
||||
TSL_M=0
|
||||
TSL_D=0
|
||||
PUB_A=0
|
||||
PUB_M=0
|
||||
PUB_D=0
|
||||
OTHER=0
|
||||
TOTAL=0
|
Loading…
Reference in New Issue
Block a user