├── .github ├── CODEOWNERS ├── dependabot.yml ├── release-drafter.yml └── workflows │ └── jenkins-security-scan.yml ├── .mvn ├── maven.config └── extensions.xml ├── .gitignore ├── .README ├── Screenshot_build_env.png ├── Screenshot_build_name.png └── Screenshot_build_step.png ├── src ├── main │ ├── resources │ │ ├── index.jelly │ │ └── org │ │ │ └── jenkinsci │ │ │ └── plugins │ │ │ ├── buildnameupdater │ │ │ └── BuildNameUpdater │ │ │ │ ├── help-buildName.jelly │ │ │ │ ├── help-macroTemplate.jelly │ │ │ │ ├── help.html │ │ │ │ ├── help-macroFirst.jelly │ │ │ │ └── config.jelly │ │ │ ├── pipeline │ │ │ ├── BuildNameStep │ │ │ │ ├── config.jelly │ │ │ │ └── help.html │ │ │ └── BuildDescriptionStep │ │ │ │ ├── config.jelly │ │ │ │ └── help.html │ │ │ └── buildnamesetter │ │ │ └── BuildNameSetter │ │ │ ├── help-template.jelly │ │ │ ├── help.html │ │ │ └── config.jelly │ └── java │ │ └── org │ │ └── jenkinsci │ │ └── plugins │ │ ├── pipeline │ │ ├── BuildNameStep.java │ │ └── BuildDescriptionStep.java │ │ ├── buildnamesetter │ │ ├── Executor.java │ │ └── BuildNameSetter.java │ │ ├── EnvironmentVarSetter.java │ │ └── buildnameupdater │ │ └── BuildNameUpdater.java └── test │ └── java │ └── org │ └── jenkinsci │ └── plugins │ └── buildnamesetter │ └── BuildNameSetterTest.java ├── Jenkinsfile ├── appveyor.yml ├── LICENSE ├── README.md └── pom.xml /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jenkinsci/build-name-setter-plugin-developers 2 | -------------------------------------------------------------------------------- /.mvn/maven.config: -------------------------------------------------------------------------------- 1 | -Pconsume-incrementals 2 | -Pmight-produce-incrementals 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | !.gitignore 3 | *.iml 4 | *.ipr 5 | *.iws 6 | .DS_Store 7 | .idea 8 | -------------------------------------------------------------------------------- /.README/Screenshot_build_env.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/build-name-setter-plugin/HEAD/.README/Screenshot_build_env.png -------------------------------------------------------------------------------- /.README/Screenshot_build_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/build-name-setter-plugin/HEAD/.README/Screenshot_build_name.png -------------------------------------------------------------------------------- /.README/Screenshot_build_step.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/build-name-setter-plugin/HEAD/.README/Screenshot_build_step.png -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 2 |
23 | * Once early on in the build, and another time later on.
24 | *
25 | * @author Kohsuke Kawaguchi
26 | */
27 | public class BuildNameSetter extends BuildWrapper implements MatrixAggregatable {
28 |
29 | private String template;
30 | private String descriptionTemplate;
31 | private Boolean runAtStart = true;
32 | private Boolean runAtEnd = true;
33 |
34 | @DataBoundConstructor
35 | public BuildNameSetter(String template, Boolean runAtStart, Boolean runAtEnd) {
36 | // attribute is named differently than parameter that must be backwards compatible
37 | this.template = template;
38 | this.runAtStart = toBooleanDefaultIfNull(runAtStart, true);
39 | this.runAtEnd = toBooleanDefaultIfNull(runAtEnd, true);
40 | }
41 |
42 | @DataBoundSetter
43 | public void setDescriptionTemplate(String descriptionTemplate) {
44 | this.descriptionTemplate = descriptionTemplate;
45 | }
46 |
47 | public String getDescriptionTemplate() {
48 | return descriptionTemplate;
49 | }
50 |
51 | @DataBoundSetter
52 | public void setTemplate(String template) {
53 | this.template = template;
54 | }
55 |
56 | public String getTemplate() {
57 | return template;
58 | }
59 |
60 | public Boolean getRunAtStart() {
61 | return runAtStart;
62 | }
63 |
64 | public Boolean getRunAtEnd() {
65 | return runAtEnd;
66 | }
67 |
68 | protected Object readResolve() {
69 | if (runAtStart == null) {
70 | runAtStart = true;
71 | }
72 | if (runAtEnd == null) {
73 | runAtEnd = true;
74 | }
75 | return this;
76 | }
77 |
78 | @Override
79 | public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) {
80 |
81 | Executor executor = new Executor(build, listener);
82 |
83 | if (runAtStart) {
84 | executor.setName(template);
85 | executor.setDescription(descriptionTemplate);
86 | }
87 |
88 | return new Environment() {
89 | @Override
90 | public boolean tearDown(AbstractBuild build, BuildListener listener) {
91 | if (runAtEnd) {
92 | executor.setName(template);
93 | executor.setDescription(descriptionTemplate);
94 | }
95 | return true;
96 | }
97 | };
98 | }
99 |
100 |
101 | // support for matrix project
102 | public MatrixAggregator createAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) {
103 |
104 | Executor executor = new Executor(build, listener);
105 |
106 | return new MatrixAggregator(build, launcher, listener) {
107 | @Override
108 | public boolean startBuild() throws InterruptedException, IOException {
109 | executor.setName(template);
110 | executor.setDescription(descriptionTemplate);
111 |
112 | return super.startBuild();
113 | }
114 |
115 | @Override
116 | public boolean endBuild() throws InterruptedException, IOException {
117 | executor.setName(template);
118 | executor.setDescription(descriptionTemplate);
119 |
120 | return super.endBuild();
121 | }
122 | };
123 | }
124 |
125 | @Extension
126 | public static class DescriptorImpl extends BuildWrapperDescriptor {
127 | @Override
128 | public boolean isApplicable(AbstractProject, ?> item) {
129 | return true;
130 | }
131 |
132 | @Override
133 | public String getDisplayName() {
134 | return "Set Build Name";
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/plugins/buildnameupdater/BuildNameUpdater.java:
--------------------------------------------------------------------------------
1 | package org.jenkinsci.plugins.buildnameupdater;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.nio.charset.StandardCharsets;
8 | import java.util.logging.Level;
9 | import java.util.logging.Logger;
10 |
11 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 | import hudson.Extension;
13 | import hudson.FilePath;
14 | import hudson.Launcher;
15 | import hudson.model.AbstractBuild;
16 | import hudson.model.AbstractProject;
17 | import hudson.model.BuildListener;
18 | import hudson.remoting.VirtualChannel;
19 | import hudson.tasks.BuildStepDescriptor;
20 | import hudson.tasks.Builder;
21 | import hudson.util.FormValidation;
22 | import jenkins.MasterToSlaveFileCallable;
23 | import org.apache.commons.lang3.StringUtils;
24 | import org.jenkinsci.plugins.buildnamesetter.Executor;
25 | import org.jenkinsci.plugins.tokenmacro.MacroEvaluationException;
26 | import org.jenkinsci.plugins.tokenmacro.TokenMacro;
27 | import org.kohsuke.stapler.DataBoundConstructor;
28 | import org.kohsuke.stapler.QueryParameter;
29 |
30 | /**
31 | * This plugin replace the build name with the first line from a file on a slave.
32 | *
33 | * @author Lev Mishin
34 | */
35 | public class BuildNameUpdater extends Builder {
36 |
37 | private final String buildName;
38 | private final String macroTemplate;
39 | private final boolean fromFile;
40 | private final boolean fromMacro;
41 | private final boolean macroFirst;
42 |
43 | private static final Logger LOGGER = Logger.getLogger(BuildNameUpdater.class.getName());
44 |
45 | // Fields in config.jelly must match the parameter names in the "DataBoundConstructor"
46 | @DataBoundConstructor
47 | public BuildNameUpdater(boolean fromFile, String buildName, boolean fromMacro, String macroTemplate, boolean macroFirst) {
48 | this.buildName = buildName;
49 | this.macroTemplate = macroTemplate;
50 | this.fromFile = fromFile;
51 | this.fromMacro = fromMacro;
52 | this.macroFirst = macroFirst;
53 | }
54 |
55 | @SuppressWarnings("unused")
56 | public boolean getFromFile() {
57 | return fromFile;
58 | }
59 |
60 | @SuppressWarnings("unused")
61 | public boolean getMacroFirst() {
62 | return macroFirst;
63 | }
64 |
65 | @SuppressWarnings("unused")
66 | public boolean getFromMacro() {
67 | return fromMacro;
68 | }
69 |
70 | @SuppressWarnings("unused")
71 | public String getBuildName() {
72 | return buildName;
73 | }
74 |
75 | @SuppressWarnings("unused")
76 | public String getMacroTemplate() {
77 | return macroTemplate;
78 | }
79 |
80 | @Override
81 | public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) {
82 | String buildNameToSet = "";
83 |
84 | if (fromFile) {
85 | buildNameToSet = readFromFile(build, listener, buildName);
86 | }
87 |
88 | if (fromMacro) {
89 | String evaluatedMacro = getFromMacro(build, listener, macroTemplate);
90 |
91 | listener.getLogger().println("Evaluated macro: '" + evaluatedMacro + "'");
92 |
93 | buildNameToSet = macroFirst ? evaluatedMacro + buildNameToSet : buildNameToSet + evaluatedMacro;
94 | }
95 |
96 | if (StringUtils.isNotBlank(buildNameToSet)) {
97 | Executor executor = new Executor(build, listener);
98 | executor.setName(buildNameToSet);
99 | }
100 |
101 | return true;
102 | }
103 |
104 | private String getFromMacro(AbstractBuild build, BuildListener listener, String macro) {
105 | String result = null;
106 | try {
107 | result = TokenMacro.expandAll(build, listener, macro);
108 | } catch (MacroEvaluationException e) {
109 | listener.getLogger().println("Failed to evaluate macro '" + macro + "'");
110 | LOGGER.log(Level.WARNING, "Failed to evaluate macro '" + macro + "': ", e);
111 | } catch (IOException e) {
112 | LOGGER.log(Level.WARNING, "Exception was thrown during macro evaluation: ", e);
113 | } catch (InterruptedException e) {
114 | LOGGER.log(Level.WARNING, "Macro evaluation was interrupted: ", e);
115 | listener.getLogger().println("Macro evaluating failed with:");
116 | }
117 | LOGGER.log(Level.INFO, "Macro evaluated: '" + result + "'");
118 | return result;
119 | }
120 |
121 | private String readFromFile(AbstractBuild build, BuildListener listener, String filePath) {
122 | String version = "";
123 |
124 | if (StringUtils.isBlank(filePath)) {
125 | listener.getLogger().println("File path is empty.");
126 | return "";
127 | }
128 |
129 | FilePath workspace = build.getWorkspace();
130 | if (workspace == null) {
131 | listener.getLogger().println("Workspace is empty.");
132 | return "";
133 | }
134 | FilePath fp = new FilePath(workspace, filePath);
135 |
136 | listener.getLogger().println("Getting version from file: " + fp);
137 |
138 | try {
139 | version = fp.act(new FileCallable());
140 | } catch (IOException e) {
141 | LOGGER.log(Level.WARNING, "Failed to read file: ", e);
142 | } catch (InterruptedException e) {
143 | LOGGER.log(Level.WARNING, "Getting name from file was interrupted: ", e);
144 | }
145 |
146 | listener.getLogger().println("Loaded version is " + version);
147 | return StringUtils.defaultString(version);
148 | }
149 |
150 | @Override
151 | public DescriptorImpl getDescriptor() {
152 | return (DescriptorImpl) super.getDescriptor();
153 | }
154 |
155 | private static class FileCallable extends MasterToSlaveFileCallable