今天介绍一个插件 build-name-setter-plugin 美化 构建 name 和 description 的 默认的 样式 只显示 成 #1, #2, #3 这样的。 我们可以通过 jenkin上的变量 等值 设置到 构建名称上,
例如把参数设置上去,触发人设置上去,能一眼看出来这次构建是干什么的,用了哪些参数等等。
例如现这样,设置了这个job 在哪个 节点上执行的,构建类型,新片平台,分支名,触发人 等信息。
1 2 #13034[another-docker-05][TriggerDailyBuild][sm8550][sm8550_s_master][mage]
用法 自由风格中的使用 1 2 3 4 5 6 构建环境 下面 勾选 Set Build Name and Description 那个就行。 然后填上 Build Name处填写 ${GERRIT_CHANGE_SUBJECT}" Build Description 处填写 Executed @ ${NODE_NAME}
这个支持的 参数 挺多的, 例如 环境变量的, job参数的,这是比较常见的。
${BUILD_NUMBER}
${BUILD_STATUS}
${ENV,var="VARIABLENAME"} 展开一个 环境变量的,job参数的
还支持一些特殊的 变量的
${BUILD_LOG_EXCERPT} 从构建日志 解析一段 excerpt 文本的
${BUILD_LOG} 显示构建日志 结尾的一段文本的,也是利用正则匹配的, 没用过
${GROOVY,script = "code"} 执行一段groovy代码的
${PROPFILE,file="FILENAME",property="PROPERTYNAME"} 从文件中 读取一段文本的
${FILE,path="PATH"} 从文件中 读取一段文本的
${XML,file="FILE",xpath="XPATH"} 从xml文件读取 一个 xpath 下的文本的
${TOKEN:offset:length} 还支持 类似 bash 里面的 按长度 切片 一个字符串的
${TOKEN#pattern} 类似 bash 中的
${TOKEN%pattern} 类似 bash 中的
这些用法 都来自 token-macro 插件 https://github.com/jenkinsci/token-macro-plugin
流水线中的用法 1 2 3 4 5 buildName "${GERRIT_CHANGE_SUBJECT}" buildDescription "Executed @ ${NODE_NAME}"
问题延伸 之前一直在使用 BuildUserVars 和 BuildNameDescriptionSetter 这2个插件,
通过 BuildUserVars 能够获取到是哪个人触发了构建.这个插件会设置个类似的环境变量 BUILD_USER.
然后 通过 BuildNameDescriptionSetter 插件 把这个环境变量 BUILD_USER 设置到 构建的 name 上.
方便一眼看出来构建历史中哪个构建是哪个人触发的/或者哪个构建是定时器触发的等等.
jenkins插件学习之BuildUserVars和BuildNameDescriptionSetter插件执行顺序 BuildNameDescriptionSetter 插件有个 " Set build name before build starts "
和 " Set build name after build ends " 选项
发现 只有在 " Set build name after build ends " 的时候 才能获取到 BUILD_USER 这个变量. 为什么这样的???
通过研究发现 是 因为 BuildUserVars 在 BuildNameDescriptionSetter 之后执行了.
执行顺序 类似 下面这样
①先 BuildNameDescriptionSetter的 " Set build name before build starts "
②然后是 BuildUserVars 插件设置用户相关的环境变量
③最后 BuildNameDescriptionSetter的 " Set build name after build ends "
在job的配置界面 “Build Environment” 地方也可以看到 BuildNameDescriptionSetter 插件 在 BuildUserVars 插件上面的.
为什么这么个排序呢? 通过搜索发现 插件 Extension 的排序是 有个 ordinal 值提供排序的. 值越大 越靠前.
默认这2个插件的这个值都是0. 都是0的话 就会按照 插件的 displayName 排序了.
修改的话 可以 把 BuildUserVars 插件的 ordinal 值 设置 大于0.
第二种修改方法 就是 修改 displayName,让排序 换一下位置.
修改 ordinal 值 设置 大于0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Extension(ordinal = 1) public static class DescriptorImpl extends BuildWrapperDescriptor { @Override public boolean isApplicable (AbstractProject<?, ?> item) { return true ; } @Override public String getDisplayName () { return EXTENSION_DISPLAY_NAME; } } private static final String EXTENSION_DISPLAY_NAME = "Set jenkins user build variables" ;
调试 跟踪 分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /** * Returns all the registered {@link BuildWrapper} descriptors. */ // for compatibility we can't use BuildWrapperDescriptor public static DescriptorExtensionList<BuildWrapper,Descriptor<BuildWrapper>> all() { // use getDescriptorList and not getExtensionList to pick up legacy instances return Jenkins.getInstance().<BuildWrapper,Descriptor<BuildWrapper>>getDescriptorList(BuildWrapper.class); } public DescriptorExtensionList<T,D> getDescriptorList(Class<T> type) { //type = BuildWrapper.class hudson.tasks.BuildWrapper return descriptorLists.computeIfAbsent(type, key -> DescriptorExtensionList.createDescriptorList(this, key)); //descriptorLists 中有key对应的值直接就获取到了. 如果没用通过 DescriptorExtensionList.createDescriptorList(this, key) 新建了. }
descriptorLists
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 descriptorLists 这个里面初始了很多的DescriptorExtensionList, 而我们要找的是 {Class@10416} "class hudson.tasks.BuildWrapper" -> {DescriptorExtensionList@13112} size = 2 这个对应的. descriptorLists = {ConcurrentHashMap@13015} size = 14 {Class@10349} "class hudson.views.ListViewColumn" -> {DescriptorExtensionList@13102} size = 8 {Class@8034} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@13103} size = 22 {Class@10272} "class hudson.model.JobProperty" -> {DescriptorExtensionList@13104} size = 3 {Class@10289} "class hudson.scm.SCM" -> {DescriptorExtensionList@13105} size = 1 {Class@8453} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@13106} size = 8 {Class@10312} "class hudson.tasks.Publisher" -> {Publisher$DescriptorExtensionListImpl@13107} size = 6 {Class@10253} "class hudson.model.ParameterDefinition" -> {DescriptorExtensionList@13108} size = 7 {Class@8698} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@13109} size = 6 {Class@10370} "class jenkins.scm.SCMCheckoutStrategy" -> {DescriptorExtensionList@13110} size = 1 {Class@7731} "class hudson.triggers.Trigger" -> {DescriptorExtensionList@13111} size = 4 {Class@10416} "class hudson.tasks.BuildWrapper" -> {DescriptorExtensionList@13112} size = 2 {Class@8443} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@13113} size = 3 {Class@10323} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@13114} size = 1 {Class@10317} "class hudson.tasks.Builder" -> {DescriptorExtensionList@13115} size = 6
1 2 3 4 5 6 7 8 9 10 11 12 13 public static DescriptorExtensionList<T,D> createDescriptorList(Jenkins jenkins, Class<T> describableType) { if (describableType == (Class) Publisher.class) { return (DescriptorExtensionList) new Publisher.DescriptorExtensionListImpl(jenkins); } return new DescriptorExtensionList<>(jenkins, describableType); } @Deprecated 这个方法已经不用了. 传入的参数是hudson 实例而已. 我们看到里面也是强制的把 hudson 转换为 jenkins 实例了.public class Hudson extends Jenkins public static DescriptorExtensionList<T,D> createDescriptorList(Hudson hudson, Class<T> describableType) { return (DescriptorExtensionList)createDescriptorList((Jenkins)hudson,describableType); }
通过在 return descriptorLists.computeIfAbsent(type, key -> DescriptorExtensionList.createDescriptorList(this, key)); 加上断点 调试发现 如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 懒加载啊! 首先重启 debug. 也就是重启了jenkins. descriptorLists = {ConcurrentHashMap@10542} size = 0 第1次 实例化这个 class hudson.node_monitors.NodeMonitor descriptorLists = {ConcurrentHashMap@10541} size = 1 第2次. 准备实例化这个 class jenkins.model.GlobalConfiguration {Class@8698} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@10741} size = 6 到这个时候 jenkins 已经启动起来了. 后续 点击了job的话还会继续实例化 下面的. descriptorLists = {ConcurrentHashMap@10541} size = 2 第3次 class hudson.model.PageDecorator {Class@8034} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11557} size = 22 {Class@8698} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@10741} size = 6 descriptorLists = {ConcurrentHashMap@10541} size = 3 {Class@8034} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11557} size = 22 {Class@8698} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@10741} size = 6 {Class@8454} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11911} size = 8 descriptorLists = {ConcurrentHashMap@10541} size = 3 第4次 class jenkins.model.GlobalConfiguration {Class@8034} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11557} size = 22 {Class@8698} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@10741} size = 6 {Class@8454} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11911} size = 8 到这时 是 点击 job 后 又加载的几个实例. descriptorLists = {ConcurrentHashMap@10541} size = 4 第5次 interface hudson.model.TopLevelItem {Class@8034} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11557} size = 22 {Class@8698} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@10741} size = 6 {Class@8440} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12854} size = 3 {Class@8454} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11911} size = 8 懒加载啊! descriptorLists = {ConcurrentHashMap@10542} size = 5 第6次 class jenkins.model.BuildDiscarder {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 又增加了一个.class jenkins.model.BuildDiscarder!!! descriptorLists = {ConcurrentHashMap@10542} size = 6 {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@10324} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@12637} size = 1 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 又增加了一个.class hudson.model.ParameterDefinition!!! 参数阶段 descriptorLists = {ConcurrentHashMap@10542} size = 7 {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@10324} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@12637} size = 1 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@10251} "class hudson.model.ParameterDefinition" -> {DescriptorExtensionList@12672} size = 7 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 又增加了一个.class hudson.scm.SCM!! descriptorLists = {ConcurrentHashMap@10542} size = 8 {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@10324} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@12637} size = 1 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@10251} "class hudson.model.ParameterDefinition" -> {DescriptorExtensionList@12672} size = 7 {Class@10290} "class hudson.scm.SCM" -> {DescriptorExtensionList@12696} size = 1 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 又增加了一个.class jenkins.scm.SCMCheckoutStrategy!!!! 这个基本上就是 job 配置 页面 从上到下 各个阶段的配置了. 代码检出阶段. descriptorLists = {ConcurrentHashMap@10542} size = 9 {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@10324} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@12637} size = 1 {Class@10371} "class jenkins.scm.SCMCheckoutStrategy" -> {DescriptorExtensionList@12722} size = 1 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@10251} "class hudson.model.ParameterDefinition" -> {DescriptorExtensionList@12672} size = 7 {Class@10290} "class hudson.scm.SCM" -> {DescriptorExtensionList@12696} size = 1 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 又增加了一个class hudson.triggers.Trigger!!!这个基本上就是 job 配置 页面 从上到下 各个阶段的配置了. 触发阶段了. descriptorLists = {ConcurrentHashMap@10542} size = 10 {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@10324} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@12637} size = 1 {Class@10371} "class jenkins.scm.SCMCheckoutStrategy" -> {DescriptorExtensionList@12722} size = 1 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@10251} "class hudson.model.ParameterDefinition" -> {DescriptorExtensionList@12672} size = 7 {Class@7733} "class hudson.triggers.Trigger" -> {DescriptorExtensionList@12770} size = 4 {Class@10290} "class hudson.scm.SCM" -> {DescriptorExtensionList@12696} size = 1 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 又增加了一个class hudson.tasks.BuildWrapper, !!!! BuildWrapper 阶段了.构建环境设置.那一块了. descriptorLists = {ConcurrentHashMap@10542} size = 11 {Class@10417} "class hudson.tasks.BuildWrapper" -> {DescriptorExtensionList@12804} size = 2 {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@10324} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@12637} size = 1 {Class@10371} "class jenkins.scm.SCMCheckoutStrategy" -> {DescriptorExtensionList@12722} size = 1 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@10251} "class hudson.model.ParameterDefinition" -> {DescriptorExtensionList@12672} size = 7 {Class@7733} "class hudson.triggers.Trigger" -> {DescriptorExtensionList@12770} size = 4 {Class@10290} "class hudson.scm.SCM" -> {DescriptorExtensionList@12696} size = 1 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 又增加了一个 class hudson.tasks.Builder !!! 构建阶段 descriptorLists = {ConcurrentHashMap@10542} size = 12 {Class@10417} "class hudson.tasks.BuildWrapper" -> {DescriptorExtensionList@12804} size = 2 {Class@10324} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@12637} size = 1 {Class@10318} "class hudson.tasks.Builder" -> {DescriptorExtensionList@12845} size = 6 {Class@7733} "class hudson.triggers.Trigger" -> {DescriptorExtensionList@12770} size = 4 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@10371} "class jenkins.scm.SCMCheckoutStrategy" -> {DescriptorExtensionList@12722} size = 1 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@10251} "class hudson.model.ParameterDefinition" -> {DescriptorExtensionList@12672} size = 7 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@10290} "class hudson.scm.SCM" -> {DescriptorExtensionList@12696} size = 1 又增加了一个class hudson.tasks.Publisher descriptorLists = {ConcurrentHashMap@10542} size = 13 {Class@10417} "class hudson.tasks.BuildWrapper" -> {DescriptorExtensionList@12804} size = 2 {Class@10324} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@12637} size = 1 {Class@10318} "class hudson.tasks.Builder" -> {DescriptorExtensionList@12845} size = 6 {Class@7733} "class hudson.triggers.Trigger" -> {DescriptorExtensionList@12770} size = 4 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 {Class@10313} "class hudson.tasks.Publisher" -> {Publisher$DescriptorExtensionListImpl@13032} size = 6 {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@10371} "class jenkins.scm.SCMCheckoutStrategy" -> {DescriptorExtensionList@12722} size = 1 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@10251} "class hudson.model.ParameterDefinition" -> {DescriptorExtensionList@12672} size = 7 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@10290} "class hudson.scm.SCM" -> {DescriptorExtensionList@12696} size = 1 descriptorLists = {ConcurrentHashMap@10542} size = 14 {Class@10417} "class hudson.tasks.BuildWrapper" -> {DescriptorExtensionList@12804} size = 2 {Class@10324} "class jenkins.model.BuildDiscarder" -> {DescriptorExtensionList@12637} size = 1 {Class@10318} "class hudson.tasks.Builder" -> {DescriptorExtensionList@12845} size = 6 {Class@7733} "class hudson.triggers.Trigger" -> {DescriptorExtensionList@12770} size = 4 {Class@8035} "class jenkins.model.GlobalConfiguration" -> {DescriptorExtensionList@11528} size = 22 {Class@10313} "class hudson.tasks.Publisher" -> {Publisher$DescriptorExtensionListImpl@13032} size = 6 {Class@10273} "class hudson.model.JobProperty" -> {DescriptorExtensionList@12571} size = 3 {Class@8699} "class hudson.node_monitors.NodeMonitor" -> {DescriptorExtensionList@11527} size = 6 {Class@10371} "class jenkins.scm.SCMCheckoutStrategy" -> {DescriptorExtensionList@12722} size = 1 {Class@8455} "class hudson.model.PageDecorator" -> {DescriptorExtensionList@11546} size = 8 {Class@10251} "class hudson.model.ParameterDefinition" -> {DescriptorExtensionList@12672} size = 7 {Class@8441} "interface hudson.model.TopLevelItem" -> {DescriptorExtensionList@12401} size = 3 {Class@10350} "class hudson.views.ListViewColumn" -> {DescriptorExtensionList@13278} size = 8 {Class@10290} "class hudson.scm.SCM" -> {DescriptorExtensionList@12696} size = 1
在 Project 类中的 submit()方法中会调用到 BuildWrappers.getFor(this) 方法. submit()方法 方法就是点了job配置里面的save按钮触发的.
1 2 3 4 5 6 7 8 9 10 11 12 public abstract class Project <P extends Project <P,B>,B extends Build <P,B>> extends AbstractProject <P,B> implements SCMTriggerItem , Saveable, ProjectWithMaven, BuildableItemWithBuildWrappers { @Override protected void submit ( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException { super .submit(req,rsp); JSONObject json = req.getSubmittedForm(); getBuildWrappersList().rebuild(req,json, BuildWrappers.getFor(this )); getBuildersList().rebuildHetero(req,json, Builder.all(), "builder" ); getPublishersList().rebuildHetero(req, json, Publisher.all(), "publisher" ); }
BuildWrappers 中的 getFor 方法, 这里会遍历 所有的 BuildWrapperDescriptor 子类的 。 BuildWrapper.all() 获取所有的 Descriptor 类型。然后还会 判断 isApplicable 返回值是否true,是TRUE表示启动这个类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class BuildWrappers { public static List<Descriptor<BuildWrapper>> getFor (AbstractProject<?, ?> project) { List<Descriptor<BuildWrapper>> result = new ArrayList <>(); Descriptor pd = Jenkins.getInstance().getDescriptor((Class)project.getClass()); for (Descriptor<BuildWrapper> w : BuildWrapper.all()) { if (pd instanceof AbstractProjectDescriptor && !((AbstractProjectDescriptor)pd).isApplicable(w)) continue ; if (w instanceof BuildWrapperDescriptor) { BuildWrapperDescriptor bwd = (BuildWrapperDescriptor) w; if (bwd.isApplicable(project)) result.add(bwd); } else { result.add(w); } } return result; } }
通过 调用 BuildWrappers 中的 getFor()方法. 调用到 for (Descriptor w : BuildWrapper.all()) { 时候会 执行到 public @Nonnull Iterator iterator() { 里面
1 2 3 4 5 6 7 8 9 @Override public @Nonnull Iterator<T> iterator () { return new AdaptedIterator <ExtensionComponent<T>,T>(Iterators.readOnly(ensureLoaded().iterator())) { protected T adapt (ExtensionComponent<T> item) { return item.getInstance(); } }; }
然后iterator() 方法里面会调用 ensureLoaded() 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 private List<ExtensionComponent<T>> ensureLoaded () { if (extensions!=null ) return extensions; if (jenkins.getInitLevel().compareTo(InitMilestone.PLUGINS_PREPARED)<0 ) return legacyInstances; synchronized (getLoadLock()) { if (extensions==null ) { List<ExtensionComponent<T>> r = load(); r.addAll(legacyInstances); extensions = sort(r); } return extensions; } } ``` 最后 ensureLoaded() 里面会对 List 进行 排序. ```java protected List<ExtensionComponent<T>> sort (List<ExtensionComponent<T>> r) { r = new ArrayList <>(r); Collections.sort(r); return r; }
排序的时候会调用到 ExtensionComponent 里面的 compareTo(ExtensionComponent that) 方法.
DescriptorExtensionList 中有存放的 ExtensionComponent 的一个集合. 然后 ExtensionComponent 中会有个 compareTo 比较顺序的方法.
然后比较出来的顺序就是 BuildWrapper 类型插件 的执行的先后顺序.
如果设置了 ordinal 值. 值越大 越先执行的(也就是job设置界面里面越靠上)没有设置ordinal就比较 displayname. 按照字符串比较的.
如果比较displayname失败会比较getClass().getName(),也是按照字符串比较。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 this = {DescriptorExtensionList@12209 } size = 2 0 = {BuildNameSetter$DescriptorImpl@12212 } 1 = {BuildUser$DescriptorImpl@12213 } public int compareTo (ExtensionComponent<T> that) { double a = this .ordinal(); double b = that.ordinal(); if (a>b) return -1 ; if (a<b) return 1 ; if (this .instance instanceof Descriptor && that.instance instanceof Descriptor) { try { return Util.fixNull(((Descriptor)this .instance).getDisplayName()).compareTo(Util.fixNull(((Descriptor)that.instance).getDisplayName())); } catch (RuntimeException | LinkageError x) { LOG.log(Level.WARNING, null , x); } } return this .instance.getClass().getName().compareTo(that.instance.getClass().getName()); }
修改 这里我采用了修改build-user-vars-plugin插件的display的方法,本来就觉得他设置的displayname看着不爽。
1 2 3 private static final String EXTENSION_DISPLAY_NAME = "Set jenkins user build variables"; private static final String EXTENSION_DISPLAY_NAME = "Set Build User Variables";
其他参考 可以参考 https://github.com/mamh-java/build-user-vars-plugin