Gradle 通过 buildFinished 钩子捕获构建失败并执行清理或通知,配合 taskGraph.whenReady 和 afterTask 实现前置检查与任务级响应;清理应谨慎限定路径,通知需防异常掩盖原错误。

Gradle 本身不提供“构建失败事件”的标准监听接口,但可以通过 buildFinished 和 taskGraph.whenReady 等生命周期钩子,结合构建结果状态判断是否失败,从而触发清理或通知逻辑。关键在于:**在构建生命周期末尾捕获失败状态,并执行自定义动作**。
使用 buildFinished 钩子捕获最终构建结果
buildFinished 是最可靠的方式,它在构建完全结束(无论成功或失败)后触发,且能拿到 BuildResult 对象,其中包含明确的 failure 属性。
- 在
build.gradle(或build.gradle.kts)的根脚本中注册:
gradle.buildFinished { buildResult ->
if (buildResult.failure != null) {
println "⚠️ 构建失败:${buildResult.failure}"
// 执行清理:例如删除 build/ 或临时目录
delete "$buildDir"
// 或发送通知:调用脚本、发邮件、写日志、调用 Webhook
exec {
commandLine 'curl', '-X', 'POST', '-H', 'Content-Type: application/json',
'-d', "{\"status\":\"FAILED\",\"reason\":\"${buildResult.failure.message}\"}",
'https://your-webhook.example.com/notify'
}
}
}
Kotlin(build.gradle.kts):
gradle.buildFinished { buildResult ->
if (buildResult.failure != null) {
logger.warn("构建失败:${buildResult.failure}")
delete(layout.buildDirectory.asFile.get())
// 示例:调用本地通知脚本
exec {
commandLine("sh", "-c", "echo 'Build failed: ${buildResult.failure}' | notify-send 'Gradle'")
}
}
}
配合 taskGraph.whenReady 提前预判高风险任务失败
taskGraph.whenReady 在任务图确定后、执行前触发,适合做前置检查;但它不能直接捕获运行时异常。若想“提前响应”某些已知易失败任务(如集成测试),可结合 afterTask 监听具体任务状态:
- 监听特定任务(如
test)的执行结果:
gradle.taskGraph.afterTask { task, state ->
if (task.name == 'test' && !state.success) {
logger.warn("测试任务失败,准备清理测试数据...")
// 清理嵌入式数据库、临时文件等
project.delete(fileTree("$buildDir/test-output").matching { include("**/*.tmp") })
}
}
注意:afterTask 是按任务粒度触发,适用于局部清理;而 buildFinished 是全局兜底,二者可互补使用。
立即学习“Java免费学习笔记(深入)”;
清理操作建议与注意事项
自动清理需谨慎,避免误删关键产物(如 jar、发布包)。推荐策略:
- 默认只清理中间产物(
build/下的classes、tmp、generated等),保留distributions、libs等发布目录 - 用
deleteDSL 显式指定路径,避免clean任务被意外跳过或覆盖 - 清理前记录日志,便于排查误删问题;生产环境建议加开关控制(如通过
-PautoCleanup=true启用)
通知机制的轻量实现方式
无需引入复杂依赖,利用 Gradle 内置能力即可:
-
终端通知:用
logger.error或系统命令(notify-send/osascript)弹窗 -
日志归档:将
buildResult.failure.stackTrace写入$buildDir/logs/last-failure.log -
HTTP 通知:用
exec调用curl或wget推送 JSON 到企业微信、钉钉、Slack Webhook(注意处理网络超时) -
邮件通知:搭配
mail命令或 JavaMail API(需额外依赖),适合 CI 环境
不复杂但容易忽略的是:确保通知逻辑本身不抛异常,否则可能掩盖原始构建错误。建议用 try/catch 包裹通知代码,并仅记录内部错误。


















