This commit is contained in:
@@ -17,19 +17,17 @@ jobs:
|
|||||||
if: ${{ gitea.ref != 'refs/heads/pre' && gitea.ref != 'refs/heads/dev' && gitea.ref != 'refs/heads/master-2.0' }}
|
if: ${{ gitea.ref != 'refs/heads/pre' && gitea.ref != 'refs/heads/dev' && gitea.ref != 'refs/heads/master-2.0' }}
|
||||||
runs-on: jdk11
|
runs-on: jdk11
|
||||||
steps:
|
steps:
|
||||||
# 浅克隆:CodeChecker 仅需 HEAD 与 HEAD~1,避免全量拉取
|
# 浅克隆当前 tip;对比基准用 push before(覆盖一次 push 的多 commit 累计 diff)
|
||||||
# 指定 --branch 确保非默认分支推送时也能正确检出 gitea.sha
|
# 不必全量历史:只需能 git show before / after 两边的文件内容
|
||||||
- name: 检出代码
|
- name: 检出代码
|
||||||
run: |
|
run: |
|
||||||
git config --global http.sslVerify false
|
git config --global http.sslVerify false
|
||||||
git clone --depth 2 --single-branch --branch "${{ gitea.ref_name }}" \
|
REPO_URL="https://${{ gitea.token }}@git.niujiekeji.com/${{ gitea.repository }}.git"
|
||||||
"https://${{ gitea.token }}@git.niujiekeji.com/${{ gitea.repository }}.git" .
|
BRANCH="${{ gitea.ref_name }}"
|
||||||
# 将 commit 绑定回本地分支,避免 detached HEAD 导致分支识别为「未知」
|
NEW_SHA="${{ gitea.sha }}"
|
||||||
git checkout -B "${{ gitea.ref_name }}" "${{ gitea.sha }}"
|
git clone --depth 1 --single-branch --branch "${BRANCH}" "${REPO_URL}" .
|
||||||
# git config --global http.sslVerify false
|
git checkout -B "${BRANCH}" "${NEW_SHA}"
|
||||||
# git clone --depth 2 --single-branch --branch "${{ gitea.ref_name }}" \
|
echo "${NEW_SHA}" > /tmp/code-check-new-sha.txt
|
||||||
# "https://${{ gitea.token }}@git.niujiekeji.com/${{ gitea.repository }}.git" .
|
|
||||||
# git checkout ${{ gitea.sha }}
|
|
||||||
|
|
||||||
- name: 检查配置文件
|
- name: 检查配置文件
|
||||||
run: |
|
run: |
|
||||||
@@ -67,17 +65,115 @@ jobs:
|
|||||||
echo "Java: $(java -version 2>&1 | head -1)"
|
echo "Java: $(java -version 2>&1 | head -1)"
|
||||||
|
|
||||||
- name: 执行 CodeChecker 变更检测
|
- name: 执行 CodeChecker 变更检测
|
||||||
|
env:
|
||||||
|
# push 前 tip;新分支首次 push 时为全 0。workflow_dispatch 可能为空,下方会回退。
|
||||||
|
PUSH_BEFORE: ${{ gitea.event.before }}
|
||||||
|
# push 事件携带的 commits 列表(JSON);用于准确统计 commit 数(不受浅克隆影响)
|
||||||
|
PUSH_COMMITS_JSON: ${{ toJson(gitea.event.commits) }}
|
||||||
run: |
|
run: |
|
||||||
|
NEW_SHA=$(cat /tmp/code-check-new-sha.txt)
|
||||||
|
OLD_SHA="${PUSH_BEFORE}"
|
||||||
|
# 新分支首次 push(before 全 0)→ 跳过
|
||||||
|
if [ -z "$OLD_SHA" ] || echo "$OLD_SHA" | grep -Eq '^0+$'; then
|
||||||
|
# 手动触发:无 before,回退为 HEAD~1(加深 1 层后取父提交)
|
||||||
|
if [ "${{ gitea.event_name }}" = "workflow_dispatch" ]; then
|
||||||
|
git fetch --deepen 1 || true
|
||||||
OLD_SHA=$(git rev-parse HEAD~1 2>/dev/null || echo "")
|
OLD_SHA=$(git rev-parse HEAD~1 2>/dev/null || echo "")
|
||||||
if [ -z "$OLD_SHA" ]; then
|
if [ -z "$OLD_SHA" ]; then
|
||||||
echo "首次提交,跳过变更检测"
|
echo "手动触发且无父提交,跳过检测"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
COMMIT_TIME=$(git log -1 --format=%cd --date=format:'%Y-%m-%d %H:%M:%S')
|
echo "workflow_dispatch:无 push before,回退使用 HEAD~1=${OLD_SHA}"
|
||||||
|
else
|
||||||
|
echo "新分支首次 push(before 为空/全 0),跳过检测"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$OLD_SHA" = "$NEW_SHA" ]; then
|
||||||
|
echo "before 与 after 相同,无需检测"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# 确保提交对象可读
|
||||||
|
ensure_commit() {
|
||||||
|
local sha="$1"
|
||||||
|
if git cat-file -e "${sha}^{commit}" 2>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "本地缺少 ${sha},尝试按 SHA 浅取…"
|
||||||
|
if git fetch --depth 1 origin "${sha}"; then
|
||||||
|
git cat-file -e "${sha}^{commit}" 2>/dev/null && return 0
|
||||||
|
fi
|
||||||
|
for d in 10 30 50 100; do
|
||||||
|
echo "deepen ${d}…"
|
||||||
|
git fetch --deepen "${d}" || true
|
||||||
|
if git cat-file -e "${sha}^{commit}" 2>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
# 加深当前 tip 的历史,直到 before 成为 after 的祖先(否则 rev-list 在浅克隆下会少算)
|
||||||
|
ensure_range() {
|
||||||
|
local old="$1"
|
||||||
|
local new="$2"
|
||||||
|
local i=0
|
||||||
|
while [ "$i" -lt 15 ]; do
|
||||||
|
if git merge-base --is-ancestor "${old}" "${new}" 2>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "区间历史不完整,deepen 20…(第 $((i + 1)) 次)"
|
||||||
|
git fetch --deepen 20 || true
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
# force-push 等非祖先关系:对象在即可做 git diff,但 rev-list 不可靠
|
||||||
|
if git cat-file -e "${old}^{commit}" 2>/dev/null \
|
||||||
|
&& git cat-file -e "${new}^{commit}" 2>/dev/null; then
|
||||||
|
echo "警告: ${old} 不是 ${new} 的祖先(可能 force-push),commit 计数将改用事件 payload"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
# 优先用 Gitea push 事件的 commits 数组长度(准确且不依赖 shallow)
|
||||||
|
count_from_payload() {
|
||||||
|
if [ -z "${PUSH_COMMITS_JSON:-}" ] || [ "${PUSH_COMMITS_JSON}" = "null" ] || [ "${PUSH_COMMITS_JSON}" = "[]" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
local n
|
||||||
|
n=$(printf '%s' "${PUSH_COMMITS_JSON}" | grep -oE '"id"[[:space:]]*:[[:space:]]*"[0-9a-fA-F]{7,40}"' | wc -l | tr -d ' ')
|
||||||
|
if [ -n "$n" ] && [ "$n" -gt 0 ] 2>/dev/null; then
|
||||||
|
echo "$n"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if ! ensure_commit "$OLD_SHA"; then
|
||||||
|
echo "错误: 无法获取 push 前 tip ${OLD_SHA},请检查 shallow/权限"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if ! ensure_commit "$NEW_SHA"; then
|
||||||
|
echo "错误: 无法解析当前 tip ${NEW_SHA}"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if ! ensure_range "$OLD_SHA" "$NEW_SHA"; then
|
||||||
|
echo "错误: 无法补齐 ${OLD_SHA}..${NEW_SHA} 历史"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
echo "对比区间: ${OLD_SHA} → ${NEW_SHA}"
|
||||||
|
COMMIT_COUNT=""
|
||||||
|
if COMMIT_COUNT=$(count_from_payload); then
|
||||||
|
echo "本次 push 累计 commit 数: ${COMMIT_COUNT}(来自事件 payload)"
|
||||||
|
elif git merge-base --is-ancestor "$OLD_SHA" "$NEW_SHA" 2>/dev/null; then
|
||||||
|
COMMIT_COUNT=$(git rev-list --count "${OLD_SHA}..${NEW_SHA}" 2>/dev/null || echo "?")
|
||||||
|
echo "本次 push 累计 commit 数: ${COMMIT_COUNT}(来自 git rev-list)"
|
||||||
|
else
|
||||||
|
echo "本次 push 累计 commit 数: ?(非祖先关系且无 payload)"
|
||||||
|
fi
|
||||||
|
COMMIT_TIME=$(git log -1 --format=%cd --date=format:'%Y-%m-%d %H:%M:%S' "${NEW_SHA}")
|
||||||
java -jar "/tmp/code-checker-${CODE_CHECKER_VERSION}.jar" \
|
java -jar "/tmp/code-checker-${CODE_CHECKER_VERSION}.jar" \
|
||||||
--config .gitea/config/code-check-config.yaml \
|
--config .gitea/config/code-check-config.yaml \
|
||||||
--repo-root . \
|
--repo-root . \
|
||||||
--old-sha "$OLD_SHA" \
|
--old-sha "$OLD_SHA" \
|
||||||
--new-sha "$(git rev-parse HEAD)" \
|
--new-sha "$NEW_SHA" \
|
||||||
|
--branch "${{ gitea.ref_name }}" \
|
||||||
--modifier "${{ gitea.actor }}" \
|
--modifier "${{ gitea.actor }}" \
|
||||||
--modify-time "$COMMIT_TIME"
|
--modify-time "$COMMIT_TIME"
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ public class CodeCheckMain implements Callable<Integer> {
|
|||||||
@Option(names = "--modify-time", required = true, description = "修改时间")
|
@Option(names = "--modify-time", required = true, description = "修改时间")
|
||||||
private String modifyTime;
|
private String modifyTime;
|
||||||
|
|
||||||
|
@Option(names = "--branch", description = "分支名(CI 显式传入,优先于 git rev-parse)")
|
||||||
|
private String branch;
|
||||||
|
|
||||||
/** 程序入口 */
|
/** 程序入口 */
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
int exitCode = new CommandLine(new CodeCheckMain()).execute(args);
|
int exitCode = new CommandLine(new CodeCheckMain()).execute(args);
|
||||||
@@ -68,7 +71,7 @@ public class CodeCheckMain implements Callable<Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GitChangeScanner gitScanner = new GitChangeScanner(repoRoot.toAbsolutePath());
|
GitChangeScanner gitScanner = new GitChangeScanner(repoRoot.toAbsolutePath());
|
||||||
String branch = gitScanner.getCurrentBranch();
|
String branchName = resolveBranch(gitScanner);
|
||||||
DtoNestIndex nestIndex = DtoNestIndex.build(repoRoot.toAbsolutePath(), appConfig);
|
DtoNestIndex nestIndex = DtoNestIndex.build(repoRoot.toAbsolutePath(), appConfig);
|
||||||
List<ClassChangeReport> classReports = List.of();
|
List<ClassChangeReport> classReports = List.of();
|
||||||
List<EndpointChangeReport> apiReports = List.of();
|
List<EndpointChangeReport> apiReports = List.of();
|
||||||
@@ -87,8 +90,8 @@ public class CodeCheckMain implements Callable<Integer> {
|
|||||||
|
|
||||||
OverlapNotificationFilter.FilterResult filtered = OverlapNotificationFilter.apply(
|
OverlapNotificationFilter.FilterResult filtered = OverlapNotificationFilter.apply(
|
||||||
classReports, apiReports, appConfig.getDtoOverlapMode(), nestIndex);
|
classReports, apiReports, appConfig.getDtoOverlapMode(), nestIndex);
|
||||||
int totalSent = sendClassNotifications(appConfig, filtered.classReports(), branch)
|
int totalSent = sendClassNotifications(appConfig, filtered.classReports(), branchName)
|
||||||
+ sendApiNotifications(appConfig, filtered.apiReports(), branch);
|
+ sendApiNotifications(appConfig, filtered.apiReports(), branchName);
|
||||||
|
|
||||||
if (totalSent == 0 && appConfig.isOnlyOnChange()) {
|
if (totalSent == 0 && appConfig.isOnlyOnChange()) {
|
||||||
System.out.println("无变更,静默退出");
|
System.out.println("无变更,静默退出");
|
||||||
@@ -96,6 +99,13 @@ public class CodeCheckMain implements Callable<Integer> {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resolveBranch(GitChangeScanner gitScanner) {
|
||||||
|
if (branch != null && !branch.isBlank()) {
|
||||||
|
return branch.trim();
|
||||||
|
}
|
||||||
|
return gitScanner.getCurrentBranch();
|
||||||
|
}
|
||||||
|
|
||||||
private List<ClassChangeReport> analyzeClassChanges(AppConfig appConfig, GitChangeScanner gitScanner,
|
private List<ClassChangeReport> analyzeClassChanges(AppConfig appConfig, GitChangeScanner gitScanner,
|
||||||
DtoNestIndex nestIndex) throws Exception {
|
DtoNestIndex nestIndex) throws Exception {
|
||||||
System.out.println("=== 类变更检测 ===");
|
System.out.println("=== 类变更检测 ===");
|
||||||
|
|||||||
Reference in New Issue
Block a user