问题:
Jenkins 测试报告路径中包含
job/AndroidSmokePipline/35/execution/node/3/ws/...
等动态部分,导致链接每次构建都不同。
✅ 解决方案总结
我们使用 Jenkins 的内置功能:
- ✅
archiveArtifacts artifacts: 'SuuntoTest/log/<latest_dir>'
:只归档最新的测试日志目录 - ✅
${BUILD_URL}artifact/SuuntoTest/log/<latest_dir>
:构造标准的、可分享的日志访问链接 - ✅ PowerShell 获取最新日志目录名(非写死)
- ✅ Python 脚本读取环境变量构造日志 URL,用于钉钉或邮件通知
这样可以确保:
- ✅ 每次构建生成唯一的 artifact 日志目录
- ✅ 链接始终有效,且不依赖 node 或 job 名称变化
- ✅ 可以直接在浏览器中打开查看测试报告
📄 详细操作文档
✅ 第一步:确保你的测试脚本将日志输出到 SuuntoTest/log/
目录下
例如,在你的测试框架中设置日志目录为:
log_dir = os.path.join("SuuntoTest", "log", "<timestamped_dir>")
每次运行都会生成一个时间戳命名的新目录,如:
SuuntoTest\log\2025-06-23-19-48-33_android_10CF4809DD002B4\
✅ 第二步:修改 Jenkinsfile 归档“最新”日志目录
在 Jenkins Pipeline 中添加如下逻辑,只归档最新的日志目录。
修改后的 Jenkinsfile 示例片段如下:
stage('Archive Artifacts') {
steps {
script {
def latestLogDir = powershell(returnStdout: true, script: '''
$workspaceDir = "$env:WORKSPACE\\SuuntoTest"
$logPath = "$workspaceDir\\log"
if (-Not (Test-Path -Path $logPath)) {
Write-Output ""
exit 1
}
# 获取 log 下最新创建的子目录
$latestDir = Get-ChildItem -Path $logPath -Directory | Sort-Object -Property Name -Descending | Select-Object -First 1
if ($latestDir) {
Write-Output $latestDir.Name
} else {
Write-Output ""
}
''').trim()
if (!latestLogDir) {
echo "没有找到日志目录,跳过归档"
return
}
def artifactPath = "SuuntoTest\\\\log\\\\${latestLogDir}\\\\**"
archiveArtifacts artifacts: artifactPath, allowEmptyArchive: false
}
}
}
✅ 第三步:Python 脚本中获取 Jenkins 构建地址并构造 artifact 日志路径
在 [notification_sender.py](file://C:\ProgramData\Jenkins.jenkins\workspace\AndroidSmoke\SuuntoTest\jenkins\notification_sender.py) 中构造日志链接如下:
import os
def get_jenkins_log_url():
build_url = os.getenv("JENKINS_BUILD_URL", "未知")
latest_log_dir = os.getenv("LATEST_LOG_DIR", "")
if build_url == "未知" or not latest_log_dir:
return "未知"
return f"{build_url.rstrip('/')}/artifact/SuuntoTest/log/{latest_log_dir}/"
✅ 第四步:在 Jenkinsfile 中传递 LATEST_LOG_DIR
给 Python 脚本
stage('Send Notification') {
steps {
script {
dir("${env.WORKSPACE_DIR}") {
bat """
set PYTHONIOENCODING=utf-8
set LATEST_LOG_DIR=${latestLogDir}
.venv\\Scripts\\python jenkins\\notification_sender.py
"""
}
}
}
}
这样 Python 脚本就能获取到本次构建的最新日志目录名,并构造出固定格式的 artifact 访问链接。
✅ 第五步:最终日志访问方式
最终你可以通过以下方式访问日志:
${BUILD_URL}artifact/SuuntoTest/log/2025-06-23-19-48-33_android_10CF4809DD002B4/
其中:
${BUILD_URL}
是 Jenkins 自动提供的当前构建地址/artifact/
是 Jenkins 提供的标准 artifact 访问前缀SuuntoTest/log/2025-06-23-19-48-33_android_10CF4809DD002B4/
是本次构建生成的唯一日志目录
✅ 总结:完整流程图
步骤 | 行为 |
---|---|
1️⃣ | 测试脚本生成带时间戳的日志目录 |
2️⃣ | Jenkins Pipeline 使用 PowerShell 获取最新目录名 |
3️⃣ | Jenkins 归档该目录内容为 artifact |
4️⃣ | Jenkinsfile 将目录名传入 Python 脚本 |
5️⃣ | Python 构造完整的 artifact 日志链接 |
6️⃣ | 发送通知时附带这个链接,用户可点击访问 |
✅ 最终效果示例
内容 | 示例值 |
---|---|
Jenkins 构建链接 | http://localhost:8080/job/AndroidSmokePipline/35/ |
artifact 日志链接 | http://localhost:8080/job/AndroidSmokePipline/35/artifact/SuuntoTest/log/2025-06-23-19-48-33_android_10CF4809DD002B4/ |
Python 构造链接 | os.getenv("JENKINS_BUILD_URL") + '/artifact/SuuntoTest/log/' + os.getenv("LATEST_LOG_DIR") |