Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
jenkins
提交
91834d9f
J
jenkins
项目概览
xxadev
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
91834d9f
编写于
8月 04, 2020
作者:
W
Wadeck Follonier
提交者:
GitHub
8月 04, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[JENKINS-63232] Build Time Trend Page fails to Display Build Time History (#4893)
上级
7886eccf
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
243 addition
and
2 deletion
+243
-2
core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.js
...in/resources/hudson/model/Job/buildTimeTrend_resources.js
+8
-2
test/src/test/java/jenkins/widgets/BuildTimeTrendTest.java
test/src/test/java/jenkins/widgets/BuildTimeTrendTest.java
+226
-0
test/src/test/resources/jenkins/widgets/BuildTimeTrendTest/NonAbstractJob/sidepanel.jelly
...widgets/BuildTimeTrendTest/NonAbstractJob/sidepanel.jelly
+5
-0
test/src/test/resources/jenkins/widgets/BuildTimeTrendTest/localDataNonAbstractJob/jobs/job0/builds/1/build.xml
...Test/localDataNonAbstractJob/jobs/job0/builds/1/build.xml
+2
-0
test/src/test/resources/jenkins/widgets/BuildTimeTrendTest/localDataNonAbstractJob/jobs/job0/config.xml
...imeTrendTest/localDataNonAbstractJob/jobs/job0/config.xml
+2
-0
未找到文件。
core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.js
浏览文件 @
91834d9f
...
...
@@ -19,8 +19,14 @@ function buildTimeTrend_displayBuilds(data) {
tr
.
insert
(
new
Element
(
'
td
'
,
{
data
:
e
.
duration
}).
update
(
e
.
durationString
.
escapeHTML
()));
if
(
isMasterSlaveEnabled
)
{
tr
.
insert
(
new
Element
(
'
td
'
).
update
(
e
.
builtOn
?
new
Element
(
'
a
'
,
{
href
:
rootURL
+
'
/computer/
'
+
e
.
builtOn
,
'
class
'
:
'
model-link inside
'
}).
update
(
e
.
builtOnStr
.
escapeHTML
())
:
e
.
builtOnStr
.
escapeHTML
()));
var
buildInfo
=
null
;
var
buildInfoStr
=
(
e
.
builtOnStr
||
''
).
escapeHTML
();
if
(
e
.
builtOn
)
{
buildInfo
=
new
Element
(
'
a
'
,
{
href
:
rootURL
+
'
/computer/
'
+
e
.
builtOn
,
'
class
'
:
'
model-link inside
'
}).
update
(
buildInfoStr
);
}
else
{
buildInfo
=
buildInfoStr
;
}
tr
.
insert
(
new
Element
(
'
td
'
).
update
(
buildInfo
));
}
p
.
insert
(
tr
);
Behaviour
.
applySubtree
(
tr
);
...
...
test/src/test/java/jenkins/widgets/BuildTimeTrendTest.java
0 → 100644
浏览文件 @
91834d9f
/*
* The MIT License
*
* Copyright (c) 2020, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.widgets
;
import
com.gargoylesoftware.htmlunit.html.DomNode
;
import
com.gargoylesoftware.htmlunit.html.DomNodeList
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
import
com.gargoylesoftware.htmlunit.html.HtmlTable
;
import
edu.umd.cs.findbugs.annotations.NonNull
;
import
hudson.XmlFile
;
import
hudson.model.FreeStyleProject
;
import
hudson.model.ItemGroup
;
import
hudson.model.Job
;
import
hudson.model.Result
;
import
hudson.model.Run
;
import
hudson.model.RunMap
;
import
hudson.model.TopLevelItem
;
import
hudson.model.TopLevelItemDescriptor
;
import
hudson.slaves.DumbSlave
;
import
jenkins.model.Jenkins
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.Issue
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.TestExtension
;
import
org.jvnet.hudson.test.recipes.LocalData
;
import
java.io.File
;
import
java.io.IOException
;
import
java.util.Optional
;
import
java.util.SortedMap
;
import
static
org
.
hamcrest
.
CoreMatchers
.
instanceOf
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
public
class
BuildTimeTrendTest
{
@Rule
public
JenkinsRule
j
=
new
JenkinsRule
();
@Test
public
void
withAbstractJob_OnMaster
()
throws
Exception
{
FreeStyleProject
p
=
j
.
createFreeStyleProject
();
j
.
assertBuildStatusSuccess
(
p
.
scheduleBuild2
(
0
));
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
withThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
page
=
wc
.
getPage
(
p
,
"buildTimeTrend"
);
HtmlTable
table
=
page
.
getDocumentElement
().
querySelector
(
"table[data-is-master-slave-enabled=false]"
);
assertNotNull
(
table
);
}
@Test
public
void
withAbstractJob_OnNode
()
throws
Exception
{
DumbSlave
agent
=
j
.
createSlave
();
FreeStyleProject
p
=
j
.
createFreeStyleProject
();
p
.
setAssignedNode
(
agent
);
j
.
assertBuildStatusSuccess
(
p
.
scheduleBuild2
(
0
));
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
withThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
page
=
wc
.
getPage
(
p
,
"buildTimeTrend"
);
DomNodeList
<
DomNode
>
anchors
=
page
.
getDocumentElement
().
querySelectorAll
(
"table[data-is-master-slave-enabled=true] td a"
);
Optional
<
DomNode
>
anchor
=
anchors
.
stream
()
.
filter
(
a
->
a
.
getTextContent
().
equals
(
agent
.
getNodeName
()))
.
findFirst
();
assertTrue
(
anchor
.
isPresent
());
}
@Test
public
void
withAbstractJob_OnBoth
()
throws
Exception
{
DumbSlave
agent
=
j
.
createSlave
();
FreeStyleProject
p
=
j
.
createFreeStyleProject
();
p
.
setAssignedNode
(
j
.
jenkins
);
j
.
assertBuildStatusSuccess
(
p
.
scheduleBuild2
(
0
));
p
.
setAssignedNode
(
agent
);
j
.
assertBuildStatusSuccess
(
p
.
scheduleBuild2
(
0
));
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
withThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
page
=
wc
.
getPage
(
p
,
"buildTimeTrend"
);
DomNodeList
<
DomNode
>
anchors
=
page
.
getDocumentElement
().
querySelectorAll
(
"table[data-is-master-slave-enabled=true] td a"
);
Optional
<
DomNode
>
anchor
=
anchors
.
stream
()
.
filter
(
a
->
a
.
getTextContent
().
equals
(
agent
.
getNodeName
()))
.
findFirst
();
// for the build on agent
assertTrue
(
anchor
.
isPresent
());
String
masterName
=
hudson
.
model
.
Messages
.
Hudson_Computer_DisplayName
();
DomNodeList
<
DomNode
>
tds
=
page
.
getDocumentElement
().
querySelectorAll
(
"table[data-is-master-slave-enabled=true] td"
);
Optional
<
DomNode
>
td
=
tds
.
stream
()
.
filter
(
t
->
t
.
getTextContent
().
equals
(
masterName
))
.
findFirst
();
// for the build on master
assertTrue
(
td
.
isPresent
());
}
@Test
@LocalData
(
"localDataNonAbstractJob"
)
public
void
withNonAbstractJob_withoutAgents
()
throws
Exception
{
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
TopLevelItem
p
=
j
.
jenkins
.
getItem
(
"job0"
);
assertThat
(
p
,
instanceOf
(
NonAbstractJob
.
class
));
wc
.
withThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
page
=
wc
.
getPage
(
p
,
"buildTimeTrend"
);
DomNodeList
<
DomNode
>
tds
=
page
.
getDocumentElement
().
querySelectorAll
(
"table[data-is-master-slave-enabled=false] td"
);
Optional
<
DomNode
>
td
=
tds
.
stream
()
.
filter
(
t
->
t
.
getTextContent
().
equals
(
"#1"
))
.
findFirst
();
// for the stored build
assertTrue
(
td
.
isPresent
());
}
@Test
@LocalData
(
"localDataNonAbstractJob"
)
@Issue
(
"JENKINS-63232"
)
public
void
withNonAbstractJob_withAgents
()
throws
Exception
{
// just to trigger data-is-master-slave-enabled = true
j
.
createSlave
();
// Before the correction, if there was an agent and the build was not inheriting from AbstractBuild, we got
// Uncaught TypeError: Cannot read property 'escapeHTML' of undefined
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
TopLevelItem
p
=
j
.
jenkins
.
getItem
(
"job0"
);
assertThat
(
p
,
instanceOf
(
NonAbstractJob
.
class
));
wc
.
withThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
page
=
wc
.
getPage
(
p
,
"buildTimeTrend"
);
DomNodeList
<
DomNode
>
tds
=
page
.
getDocumentElement
().
querySelectorAll
(
"table[data-is-master-slave-enabled=true] td"
);
Optional
<
DomNode
>
td
=
tds
.
stream
()
.
filter
(
t
->
t
.
getTextContent
().
equals
(
"#1"
))
.
findFirst
();
// for the stored build
assertTrue
(
td
.
isPresent
());
// with the correction, the last cell is just empty instead of throwing the TypeError
}
public
static
class
NonAbstractBuild
extends
Run
<
NonAbstractJob
,
NonAbstractBuild
>
{
protected
NonAbstractBuild
(
@NonNull
NonAbstractJob
job
)
throws
IOException
{
super
(
job
);
this
.
result
=
Result
.
SUCCESS
;
this
.
onEndBuilding
();
}
}
public
static
class
NonAbstractJob
extends
Job
<
NonAbstractJob
,
NonAbstractBuild
>
implements
TopLevelItem
{
public
NonAbstractJob
(
ItemGroup
parent
,
String
name
)
{
super
(
parent
,
name
);
}
@Override
public
boolean
isBuildable
()
{
return
true
;
}
private
RunMap
<
NonAbstractBuild
>
runMap
;
@Override
protected
SortedMap
<
Integer
,
NonAbstractBuild
>
_getRuns
()
{
if
(
runMap
==
null
){
runMap
=
new
RunMap
<>(
this
.
getBuildDir
(),
this
::
createBuildFromDir
);
}
return
runMap
;
}
private
NonAbstractBuild
createBuildFromDir
(
File
dir
)
throws
IOException
{
NonAbstractBuild
build
=
new
NonAbstractBuild
(
NonAbstractJob
.
this
);
XmlFile
xmlFile
=
new
XmlFile
(
Run
.
XSTREAM2
,
new
File
(
dir
,
"build.xml"
));
xmlFile
.
unmarshal
(
build
);
return
build
;
}
@Override
protected
void
removeRun
(
NonAbstractBuild
run
)
{
}
@Override
public
DescriptorImpl
getDescriptor
()
{
return
(
NonAbstractJob
.
DescriptorImpl
)
Jenkins
.
get
().
getDescriptorOrDie
(
getClass
());
}
@TestExtension
public
static
class
DescriptorImpl
extends
TopLevelItemDescriptor
{
@Override
public
TopLevelItem
newInstance
(
ItemGroup
parent
,
String
name
)
{
return
new
NonAbstractJob
(
parent
,
name
);
}
}
}
}
test/src/test/resources/jenkins/widgets/BuildTimeTrendTest/NonAbstractJob/sidepanel.jelly
0 → 100644
浏览文件 @
91834d9f
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout">
<l:side-panel>
</l:side-panel>
</j:jelly>
test/src/test/resources/jenkins/widgets/BuildTimeTrendTest/localDataNonAbstractJob/jobs/job0/builds/1/build.xml
0 → 100644
浏览文件 @
91834d9f
<?xml version='1.1' encoding='UTF-8'?>
<jenkins.widgets.BuildTimeTrendTest_-NonAbstractBuild
/>
test/src/test/resources/jenkins/widgets/BuildTimeTrendTest/localDataNonAbstractJob/jobs/job0/config.xml
0 → 100644
浏览文件 @
91834d9f
<?xml version='1.1' encoding='UTF-8'?>
<jenkins.widgets.BuildTimeTrendTest_-NonAbstractJob
/>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录