{
271 |
272 | @Override
273 | public boolean isApplicable(Class extends AbstractProject> jobType) {
274 | return true;
275 | }
276 |
277 | @Override
278 | public String getDisplayName() {
279 | return "Change Assembly Version";
280 | }
281 | }
282 | }
283 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/plugins/changeassemblyversion/ChangeTools.java:
--------------------------------------------------------------------------------
1 | package org.jenkinsci.plugins.changeassemblyversion;
2 |
3 | import hudson.FilePath;
4 | import hudson.model.TaskListener;
5 | import java.io.IOException;
6 | import java.io.OutputStream;
7 | import java.nio.charset.Charset;
8 | import org.apache.commons.io.ByteOrderMark;
9 | import org.apache.commons.io.IOUtils;
10 | import org.apache.commons.io.input.BOMInputStream;
11 |
12 | public class ChangeTools {
13 |
14 | private final FilePath file;
15 | private final String regexPattern;
16 | private final String replacementPattern;
17 |
18 | ChangeTools(FilePath f, String regexPattern, String replacementPattern) {
19 | this.file = f;
20 | if (regexPattern != null && !regexPattern.equals("")) {
21 | this.regexPattern = regexPattern;
22 | } else {
23 | this.regexPattern = "Version[(]\"[\\d\\.]+\"[)]";
24 | }
25 |
26 | if (replacementPattern != null && !replacementPattern.equals("")) {
27 | this.replacementPattern = replacementPattern;
28 | } else {
29 | this.replacementPattern = "Version(\"%s\")";
30 | }
31 | }
32 |
33 | public void Replace(String replacement, TaskListener listener) throws IOException, InterruptedException {
34 | if (replacement != null && !replacement.isEmpty()) {
35 | BOMInputStream inputStream = new BOMInputStream(file.read());
36 | String content;
37 | ByteOrderMark bom;
38 | Charset fileEncoding = Charset.defaultCharset();
39 | try {
40 | bom = inputStream.getBOM();
41 | if (bom != null) {
42 | fileEncoding = Charset.forName(bom.getCharsetName());
43 | }
44 |
45 | content = IOUtils.toString(inputStream, fileEncoding);
46 | } finally {
47 | inputStream.close();
48 | }
49 | listener.getLogger()
50 | .println("Updating file : %s, Replacement : %s".formatted(file.getRemote(), replacement));
51 | content = content.replaceAll(regexPattern, replacementPattern.formatted(replacement));
52 | // listener.getLogger().println(String.format("Updating file : %s", file.getRemote()));
53 | OutputStream os = file.write();
54 | try {
55 | if (bom != null) {
56 | os.write(bom.getBytes());
57 | }
58 | os.write(content.getBytes(fileEncoding));
59 | } finally {
60 | os.close();
61 | }
62 | } else {
63 | listener.getLogger().println("Skipping replacement because value is empty.".formatted());
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/resources/index.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 | This plugin lets the user modify the AssemblyVersion and AssemblyFileVersion attributes, typically contained in the AssemblyInfo.cs file.
4 |
--------------------------------------------------------------------------------
/src/main/resources/org/jenkinsci/plugins/changeassemblyversion/ChangeAssemblyVersion/config.jelly:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/src/main/resources/org/jenkinsci/plugins/changeassemblyversion/ChangeAssemblyVersion/help-assemblyFile.html:
--------------------------------------------------------------------------------
1 |
2 | Set the file name to search.
3 | If the value is empty the default filename is : **/AssemblyInfo.cs.
4 | You can use an ant fileset pattern.
5 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/org/jenkinsci/plugins/changeassemblyversion/ChangeAssemblyVersion/help-regexPattern.html:
--------------------------------------------------------------------------------
1 |
2 | Regex Pattern in which version is stated.
3 | Specify this value if you want to use for versioning other than assembly files (e.g. visual studio extensions .vsix). For assembly (.dll) versioning you do not need to specify anything here.
4 |
5 |
--------------------------------------------------------------------------------
/src/main/resources/org/jenkinsci/plugins/changeassemblyversion/ChangeAssemblyVersion/help-replacementPattern.html:
--------------------------------------------------------------------------------
1 |
2 | Version value specified in regexPattern will be replaced by this. Use if you want versioning other than assembly files.
3 | e.g. "Version(\"%s\")" where %s will be new version number. For assembly (.dll) versioning keep this field blank.
4 |
5 |
--------------------------------------------------------------------------------
/src/main/resources/org/jenkinsci/plugins/changeassemblyversion/ChangeAssemblyVersion/help-task.html:
--------------------------------------------------------------------------------
1 |
2 | Set the new version number for replace.
3 | Can be a variable like ${BUILD_NUMBER} or plain text (1.0.0.0), or a mix of the two.
4 |
5 |
--------------------------------------------------------------------------------
/src/main/resources/org/jenkinsci/plugins/changeassemblyversion/ChangeAssemblyVersion/help.html:
--------------------------------------------------------------------------------
1 |
2 | This build step can be used to change the version in the AssemblyInfo.cs file from a .NET Project, it's going to find every
3 | AssemblyInfo.cs file in the workspace and change the version from [AssemblyVersion] and [AssemblyFileVersion] attributes.
4 | It's recommended to use this plugin with the auto-generated AssemblyInfo.cs from VisualStudio.
5 |
6 |
--------------------------------------------------------------------------------
/src/test/java/org/jenkinsci/plugins/changeassemblyversion/ReplacementsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2014 BELLINSALARIN.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.plugins.changeassemblyversion;
25 |
26 | import com.google.common.primitives.Bytes;
27 | import hudson.EnvVars;
28 | import hudson.Launcher;
29 | import hudson.model.AbstractBuild;
30 | import hudson.model.BuildListener;
31 | import hudson.model.FreeStyleBuild;
32 | import hudson.model.FreeStyleProject;
33 | import hudson.slaves.EnvironmentVariablesNodeProperty;
34 | import org.apache.commons.io.ByteOrderMark;
35 | import org.apache.commons.io.IOUtils;
36 | import org.apache.commons.io.input.BOMInputStream;
37 | import org.bouncycastle.util.Arrays;
38 | import org.junit.jupiter.api.Test;
39 | import org.jvnet.hudson.test.JenkinsRule;
40 | import org.jvnet.hudson.test.TestBuilder;
41 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
42 |
43 | import java.io.IOException;
44 | import java.io.InputStream;
45 | import java.io.OutputStream;
46 | import java.io.OutputStreamWriter;
47 | import java.nio.charset.StandardCharsets;
48 |
49 | import static org.junit.jupiter.api.Assertions.assertEquals;
50 | import static org.junit.jupiter.api.Assertions.assertTrue;
51 |
52 | /**
53 | * @author BELLINSALARIN
54 | */
55 | @WithJenkins
56 | class ReplacementsTest {
57 |
58 | @Test
59 | void testResolveEnvironmentVariables(JenkinsRule j) throws Exception {
60 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty();
61 | EnvVars envVars = prop.getEnvVars();
62 | envVars.put("PREFIX", "1.1.0");
63 | j.jenkins.getGlobalNodeProperties().add(prop);
64 | FreeStyleProject project = j.createFreeStyleProject();
65 | project.getBuildersList().add(new TestBuilder() {
66 | public boolean perform(AbstractBuild, ?> build, Launcher launcher, BuildListener listener)
67 | throws InterruptedException, IOException {
68 | build.getWorkspace()
69 | .child("AssemblyVersion.cs")
70 | .write(
71 | """
72 | using System.Reflection;
73 |
74 | [assembly: AssemblyTitle("")]
75 | [assembly: AssemblyDescription("")]
76 | [assembly: AssemblyCompany("")]
77 | [assembly: AssemblyProduct("")]
78 | [assembly: AssemblyCopyright("")]
79 | [assembly: AssemblyTrademark("")]
80 | [assembly: AssemblyCulture("")]
81 | [assembly: AssemblyVersion("13.1.1.976")]""",
82 | "UTF-8");
83 | return true;
84 | }
85 | });
86 | ChangeAssemblyVersion builder = new ChangeAssemblyVersion(
87 | "$PREFIX.${BUILD_NUMBER}",
88 | "AssemblyVersion.cs",
89 | "",
90 | "",
91 | "MyTitle",
92 | "MyDescription",
93 | "MyCompany",
94 | "MyProduct",
95 | "MyCopyright",
96 | "MyTrademark",
97 | "MyCulture");
98 | project.getBuildersList().add(builder);
99 | FreeStyleBuild build = project.scheduleBuild2(0).get();
100 |
101 | // String s = FileUtils.readFileToString(build.getLogFile());
102 | String content = build.getWorkspace().child("AssemblyVersion.cs").readToString();
103 | assertTrue(content.contains("AssemblyVersion(\"1.1.0."));
104 |
105 | // Check that we update additional assembly info
106 | assertTrue(content.contains("AssemblyTitle(\"MyTitle"));
107 | assertTrue(content.contains("AssemblyDescription(\"MyDescription"));
108 | assertTrue(content.contains("AssemblyCompany(\"MyCompany"));
109 | assertTrue(content.contains("AssemblyProduct(\"MyProduct"));
110 | assertTrue(content.contains("AssemblyCopyright(\"MyCopyright"));
111 | assertTrue(content.contains("AssemblyTrademark(\"MyTrademark"));
112 | assertTrue(content.contains("AssemblyCulture(\"MyCulture"));
113 |
114 | assertEquals("$PREFIX.${BUILD_NUMBER}", builder.getVersionPattern());
115 | }
116 |
117 | @Test
118 | void testResolveEnvironmentVariables_recursively_excludingSvn(JenkinsRule j)
119 | throws Exception {
120 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty();
121 | EnvVars envVars = prop.getEnvVars();
122 | envVars.put("PREFIX", "1.1.0");
123 | j.jenkins.getGlobalNodeProperties().add(prop);
124 | FreeStyleProject project = j.createFreeStyleProject();
125 | final String f1 = "myassembly/properties/AssemblyInfo.cs";
126 | final String f2 = ".svn/myassembly/properties/AssemblyInfo.cs";
127 | final String c = """
128 | using System.Reflection;
129 |
130 | [assembly: AssemblyVersion("13.1.1.976")]""";
131 | project.getBuildersList().add(new TestBuilder() {
132 | public boolean perform(AbstractBuild, ?> build, Launcher launcher, BuildListener listener)
133 | throws InterruptedException, IOException {
134 | build.getWorkspace().child(f1).write(c, "UTF-8");
135 | build.getWorkspace().child(f2).write(c, "UTF-8");
136 | return true;
137 | }
138 | });
139 | ChangeAssemblyVersion builder =
140 | new ChangeAssemblyVersion("$PREFIX.${BUILD_NUMBER}", "", "", "", "", "", "", "", "", "", "");
141 | project.getBuildersList().add(builder);
142 | FreeStyleBuild build = project.scheduleBuild2(0).get();
143 |
144 | // String s = FileUtils.readFileToString(build.getLogFile());
145 | String content = build.getWorkspace().child(f1).readToString();
146 | assertTrue(content.contains("AssemblyVersion(\"1.1.0."));
147 | content = build.getWorkspace().child(f2).readToString();
148 | assertTrue(content.contains("AssemblyVersion(\"13.1.1.976"));
149 | assertEquals("$PREFIX.${BUILD_NUMBER}", builder.getVersionPattern());
150 | }
151 |
152 | @Test
153 | void testBOMFileReplace(JenkinsRule j) throws Exception {
154 | FreeStyleProject project = j.createFreeStyleProject();
155 | final ByteOrderMark fileBom = ByteOrderMark.UTF_8;
156 | project.getBuildersList().add(new TestBuilder() {
157 | public boolean perform(AbstractBuild, ?> build, Launcher launcher, BuildListener listener)
158 | throws InterruptedException, IOException {
159 | OutputStream outputStream =
160 | build.getWorkspace().child("AssemblyVersion.cs").write();
161 | outputStream.write(fileBom.getBytes());
162 | OutputStreamWriter w = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
163 | try {
164 | w.write(
165 | """
166 | using System.Reflection;
167 |
168 | [assembly: AssemblyTitle("")]
169 | [assembly: AssemblyDescription("")]
170 | [assembly: AssemblyCompany("")]
171 | [assembly: AssemblyProduct("")]
172 | [assembly: AssemblyCopyright("")]
173 | [assembly: AssemblyTrademark("")]
174 | [assembly: AssemblyCulture("")]
175 | [assembly: AssemblyVersion("13.1.1.976")]""");
176 | } finally {
177 | w.close();
178 | outputStream.close();
179 | }
180 |
181 | return true;
182 | }
183 | });
184 | ChangeAssemblyVersion builder = new ChangeAssemblyVersion(
185 | "1.2.3",
186 | "AssemblyVersion.cs",
187 | "",
188 | "",
189 | "MyTitle",
190 | "MyDescription",
191 | "MyCompany",
192 | "MyProduct",
193 | "MyCopyright",
194 | "MyTrademark",
195 | "MyCulture");
196 | project.getBuildersList().add(builder);
197 | FreeStyleBuild build = project.scheduleBuild2(0).get();
198 |
199 | // String s = FileUtils.readFileToString(build.getLogFile());
200 | InputStream readStream =
201 | build.getWorkspace().child("AssemblyVersion.cs").read();
202 | BOMInputStream bomInputStream = BOMInputStream.builder().setInputStream(readStream).get();
203 | ByteOrderMark bomAfterChange = bomInputStream.getBOM();
204 | String content = org.apache.commons.io.IOUtils.toString(bomInputStream, StandardCharsets.UTF_8);
205 | bomInputStream.close();
206 | readStream.close();
207 |
208 | // the replaced file should have the same BOM as the origin.
209 | assertEquals(bomAfterChange.getCharsetName(), fileBom.getCharsetName());
210 | // the first bytes should be readable characters.
211 | assertTrue(content.matches("(?s)^using.*"));
212 | // Check that we update additional assembly info
213 | assertTrue(content.contains("AssemblyTitle(\"MyTitle"));
214 | assertTrue(content.contains("AssemblyDescription(\"MyDescription"));
215 | assertTrue(content.contains("AssemblyCompany(\"MyCompany"));
216 | assertTrue(content.contains("AssemblyProduct(\"MyProduct"));
217 | assertTrue(content.contains("AssemblyCopyright(\"MyCopyright"));
218 | assertTrue(content.contains("AssemblyTrademark(\"MyTrademark"));
219 | assertTrue(content.contains("AssemblyCulture(\"MyCulture"));
220 | }
221 |
222 | @Test
223 | void testBOMFileNotModified(JenkinsRule j) throws Exception {
224 | FreeStyleProject project = j.createFreeStyleProject();
225 | final byte[] originFileBinary =
226 | ("""
227 | using System.Reflection;
228 |
229 | [assembly: AssemblyTitle("")]
230 | [assembly: AssemblyDescription("")]
231 | [assembly: AssemblyCompany("")]
232 | [assembly: AssemblyProduct("")]
233 | [assembly: AssemblyCopyright("")]
234 | [assembly: AssemblyTrademark("")]
235 | [assembly: AssemblyCulture("")]
236 | [assembly: AssemblyVersion("13.1.1.976")]""")
237 | .getBytes();
238 | project.getBuildersList().add(new TestBuilder() {
239 | public boolean perform(AbstractBuild, ?> build, Launcher launcher, BuildListener listener)
240 | throws InterruptedException, IOException {
241 | try (OutputStream outputStream = build.getWorkspace().child("AssemblyVersion.cs").write()) {
242 | outputStream.write(originFileBinary);
243 | }
244 |
245 | return true;
246 | }
247 | });
248 |
249 | ChangeAssemblyVersion builder = new ChangeAssemblyVersion("");
250 | project.getBuildersList().add(builder);
251 | FreeStyleBuild build = project.scheduleBuild2(0).get();
252 |
253 | // String s = FileUtils.readFileToString(build.getLogFile());
254 | InputStream readStream =
255 | build.getWorkspace().child("AssemblyVersion.cs").read();
256 |
257 | byte[] binaryAfterChange = IOUtils.toByteArray(readStream);
258 | String content = new String(binaryAfterChange, StandardCharsets.UTF_8);
259 |
260 | // the replaced file should have the same BOM as the origin.
261 | assertTrue(Arrays.areEqual(originFileBinary, binaryAfterChange));
262 | }
263 |
264 | @Test
265 | void testBOMFileNotModified2(JenkinsRule j) throws Exception {
266 | FreeStyleProject project = j.createFreeStyleProject();
267 | ByteOrderMark bom = ByteOrderMark.UTF_8;
268 | byte[] bomBinary = bom.getBytes();
269 | final byte[] originFileContentBinary =
270 | ("""
271 | using System.Reflection;
272 |
273 | [assembly: AssemblyTitle("")]
274 | [assembly: AssemblyDescription("")]
275 | [assembly: AssemblyCompany("")]
276 | [assembly: AssemblyProduct("")]
277 | [assembly: AssemblyCopyright("")]
278 | [assembly: AssemblyTrademark("")]
279 | [assembly: AssemblyCulture("")]
280 | [assembly: AssemblyVersion("13.1.1.976")]""")
281 | .getBytes();
282 | final byte[] originFileBinary = Bytes.concat(bomBinary, originFileContentBinary);
283 | project.getBuildersList().add(new TestBuilder() {
284 | public boolean perform(AbstractBuild, ?> build, Launcher launcher, BuildListener listener)
285 | throws InterruptedException, IOException {
286 | try (OutputStream outputStream = build.getWorkspace().child("AssemblyVersion.cs").write()) {
287 | outputStream.write(originFileBinary);
288 | }
289 |
290 | return true;
291 | }
292 | });
293 |
294 | ChangeAssemblyVersion builder = new ChangeAssemblyVersion("");
295 | project.getBuildersList().add(builder);
296 | FreeStyleBuild build = project.scheduleBuild2(0).get();
297 |
298 | // String s = FileUtils.readFileToString(build.getLogFile());
299 | InputStream readStream =
300 | build.getWorkspace().child("AssemblyVersion.cs").read();
301 | byte[] binaryAfterChange = IOUtils.toByteArray(readStream);
302 | readStream.close();
303 |
304 | // the replaced file should have the same BOM as the origin.
305 | assertTrue(Arrays.areEqual(originFileBinary, binaryAfterChange));
306 | }
307 | }
308 |
--------------------------------------------------------------------------------