因为我的数据库更新是通过 Liquibase 执行的,所以每次发版的时候都会新增 liquibase 记录,如果没有一个自动检查的 pipeline, 很容易在发版的时候因为有重复的 changeset id 这一小失误导致pipeline 被中断
于是,我通过在 Github workflow 中添加一个每次有新提交时就扫描所有文件内是否有重复 changeset id 出现的 workflow 来规避这个失误
workflow 文件: .github/workflows/check-duplications.yml
name: Check Changeset Duplications
on:
push:
paths:
- '**.sql'
jobs:
changeset-checking:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Checking duplications
run: bash liquibase/scripts/check_changeset_duplications.sh
shell 脚本: check_changeset_duplications.sh
#!/bin/bash
extract_ids() {
local file=$1
local changeset_ids=()
local file_lines=()
while IFS= read -r line; do
id=$(echo $line | perl -lne 'print $1 if m{^\d+:--\s*changeset (.*?)(?= runOnChange| endDelimiter|;|$)}')
line_number=$(echo $line | perl -lne 'print $1 if m{^(\d+)}')
if [[ -n "$id" && -n "$line_number" ]]; then
if echo "$id" | grep -q " "; then
id=$(echo $id | tr ' ' '_')
fi
changeset_ids+=("$id")
file_lines+=("$file:$line_number")
fi
done < <(perl -lne 'print "$.:$_" if /--\s*changeset .*?(?= runOnChange| endDelimiter|;|$)/' $file)
echo "${changeset_ids[*]}|${file_lines[*]}"
}
check_duplicates() {
IFS=' ' read -r -a changeset_ids <<<"$1"
IFS=' ' read -r -a file_lines <<<"$2"
local duplicates=()
local checked_ids=()
for index in ${!changeset_ids[@]}; do
id=${changeset_ids[$index]}
if [[ " ${checked_ids[@]} " =~ " ${id} " ]]; then
continue
fi
checked_ids+=("$id")
count=$(printf '%s\n' "${changeset_ids[@]}" | grep -c "$id")
if [ $count -gt 1 ]; then
first_occurrence_found=false
for second_index in ${!changeset_ids[@]}; do
if [ "${changeset_ids[$second_index]}" = "$id" ]; then
if [ "$first_occurrence_found" = true ]; then
# echo "Duplicate changeset ID: $id found at ${file_lines[$second_index]}"
echo -e "Duplicate changeset ID: \e[0;35m$id\e[0m found at file:file_line (\e[0;35m${file_lines[$second_index]}\e[0m) ❌❌❌"
else
first_occurrence_found=true
fi
fi
done
fi
done
}
total_duplicates=0
for file in $(find . -mindepth 1 -type d -name 'Testing' -prune -o -type f -name "*.sql" -print); do
echo -e "------------------------------------------Begin: $file------------------------------------------"
echo -e "---- Checking file $file..."
result=$(extract_ids $file)
changeset_ids=(${result%|*})
file_lines=(${result#*|})
echo -e "-------- Total ${#changeset_ids[*]} changeset id in $file "
echo -e "-------- Total ${#file_lines[*]} file lines in $file "
tmpfile=$(mktemp)
check_duplicates "${changeset_ids[*]}" "${file_lines[*]}" >"$tmpfile"
total_duplicates_in_file=$(wc -l <"$tmpfile")
total_duplicates=$((total_duplicates + total_duplicates_in_file))
if [ $(wc -c <"$tmpfile") -gt 0 ]; then
cat "$tmpfile"
fi
rm "$tmpfile"
echo -e "------------------------------------------End: $file------------------------------------------\n"
done
echo -e "------------------------------------------All done------------------------------------------\n"
if [ $total_duplicates -gt 0 ]; then
echo "---- Total $total_duplicates duplicates be found."
exit 1
else
echo "-------- Congratuations:"
echo "---- No duplicate changeset IDs found. All changeset IDs in the files are unique."
echo "---- Good to go."
fi
检查效果:
1. 有重复项时,打印:重复的changeset id, 所在文件名,所在文件中的行号
2. 没有重复项时,打印:Good to go.