Skip to content

Commit 899f6b7

Browse files
committed
BI-406 - Use a separate rest API for build retention
1 parent 33792e0 commit 899f6b7

File tree

9 files changed

+142
-73
lines changed

9 files changed

+142
-73
lines changed

build-info-api/src/main/java/org/jfrog/build/api/BuildRetention.java

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.jfrog.build.api;
22

3+
import com.fasterxml.jackson.annotation.JsonIgnore;
34
import com.google.common.collect.Lists;
45
import com.thoughtworks.xstream.annotations.XStreamAlias;
56

@@ -64,4 +65,9 @@ public void setBuildNumbersNotToBeDiscarded(List<String> buildNumbersNotToBeDisc
6465
public List<String> getBuildNumbersNotToBeDiscarded() {
6566
return buildNumbersNotToBeDiscarded;
6667
}
68+
69+
@JsonIgnore
70+
public boolean isEmpty() {
71+
return count == -1 && minimumBuildDate == null;
72+
}
6773
}

build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryHttpClient.java

+6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public class ArtifactoryHttpClient {
4747
new ArtifactoryVersion("2.2.3");
4848
public static final ArtifactoryVersion NON_NUMERIC_BUILD_NUMBERS_TOLERANT_ARTIFACTORY_VERSION =
4949
new ArtifactoryVersion("2.2.4");
50+
public static final ArtifactoryVersion STANDALONE_BUILD_RETENTION_SUPPORTED_ARTIFACTORY_VERSION =
51+
new ArtifactoryVersion("5.2.1");
5052
public static final ArtifactoryVersion MINIMAL_ARTIFACTORY_VERSION = new ArtifactoryVersion("2.2.3");
5153
public static final String VERSION_INFO_URL = "/api/system/version";
5254
private static final int DEFAULT_CONNECTION_TIMEOUT_SECS = 300; // 5 Minutes in seconds
@@ -118,6 +120,10 @@ public void setConnectionRetries(int connectionRetries){
118120
this.connectionRetries = connectionRetries;
119121
}
120122

123+
public int getConnectionRetries() {
124+
return connectionRetries;
125+
}
126+
121127
/**
122128
* Release all connection and cleanup resources.
123129
*/

build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/extractor/GradleBuildInfoExtractor.java

-19
Original file line numberDiff line numberDiff line change
@@ -185,25 +185,6 @@ public Build extract(Project rootProject) {
185185
governance.setBlackDuckProperties(blackDuckProperties);
186186
bib.governance(governance);
187187

188-
BuildRetention buildRetention = new BuildRetention(clientConf.info.isDeleteBuildArtifacts());
189-
Integer count = clientConf.info.getBuildRetentionCount();
190-
if (count != null) {
191-
buildRetention.setCount(count);
192-
}
193-
String buildRetentionMinimumDays = clientConf.info.getBuildRetentionMinimumDate();
194-
if (StringUtils.isNotBlank(buildRetentionMinimumDays)) {
195-
int minimumDays = Integer.parseInt(buildRetentionMinimumDays);
196-
if (minimumDays > -1) {
197-
Calendar calendar = Calendar.getInstance();
198-
calendar.add(Calendar.DAY_OF_YEAR, -minimumDays);
199-
buildRetention.setMinimumBuildDate(calendar.getTime());
200-
}
201-
}
202-
String[] notToDelete = clientConf.info.getBuildNumbersNotToDelete();
203-
for (String notToDel : notToDelete) {
204-
buildRetention.addBuildNotToBeDiscarded(notToDel);
205-
}
206-
bib.buildRetention(buildRetention);
207188
if (clientConf.info.isReleaseEnabled()) {
208189
String stagingRepository = clientConf.publisher.getRepoKey();
209190
String comment = clientConf.info.getReleaseComment();

build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/task/BuildInfoBaseTask.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.jfrog.build.extractor.clientConfiguration.IncludeExcludePatterns;
2626
import org.jfrog.build.extractor.clientConfiguration.PatternMatcher;
2727
import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient;
28+
import org.jfrog.build.extractor.retention.Utils;
2829
import org.jfrog.gradle.plugin.artifactory.ArtifactoryPluginUtil;
2930
import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention;
3031
import org.jfrog.gradle.plugin.artifactory.dsl.PropertiesConfig;
@@ -438,7 +439,7 @@ private void prepareAndDeploy() throws IOException {
438439
client.sendModuleInfo(build);
439440
} else {
440441
log.debug("Publishing build info to artifactory at: '{}'", contextUrl);
441-
client.sendBuildInfo(build);
442+
Utils.sendBuildAndBuildRetention(client, build, accRoot);
442443
}
443444
}
444445
if (isGenerateBuildInfoToFile(accRoot)) {

build-info-extractor-ivy/src/main/java/org/jfrog/build/extractor/listener/ArtifactoryBuildListener.java

+3-21
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
import org.apache.tools.ant.taskdefs.Ant;
1414
import org.jfrog.build.api.*;
1515
import org.jfrog.build.api.builder.BuildInfoBuilder;
16-
import org.jfrog.build.client.*;
16+
import org.jfrog.build.client.DeployDetails;
1717
import org.jfrog.build.context.BuildContext;
1818
import org.jfrog.build.extractor.BuildInfoExtractorUtils;
1919
import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration;
2020
import org.jfrog.build.extractor.clientConfiguration.IncludeExcludePatterns;
2121
import org.jfrog.build.extractor.clientConfiguration.PatternMatcher;
2222
import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient;
23+
import org.jfrog.build.extractor.retention.Utils;
2324
import org.jfrog.build.extractor.trigger.ArtifactoryBuildInfoTrigger;
2425
import org.jfrog.build.util.IvyBuildInfoLog;
2526

@@ -335,25 +336,6 @@ private void doDeploy(BuildEvent event) {
335336
governance.setBlackDuckProperties(blackDuckProperties);
336337
builder.governance(governance);
337338

338-
BuildRetention buildRetention = new BuildRetention(clientConf.info.isDeleteBuildArtifacts());
339-
if (clientConf.info.getBuildRetentionCount() != null) {
340-
buildRetention.setCount(clientConf.info.getBuildRetentionCount());
341-
}
342-
String buildRetentionMinimumDays = clientConf.info.getBuildRetentionMinimumDate();
343-
if (StringUtils.isNotBlank(buildRetentionMinimumDays)) {
344-
int minimumDays = Integer.parseInt(buildRetentionMinimumDays);
345-
if (minimumDays > -1) {
346-
Calendar calendar = Calendar.getInstance();
347-
calendar.add(Calendar.DAY_OF_YEAR, -minimumDays);
348-
buildRetention.setMinimumBuildDate(calendar.getTime());
349-
}
350-
}
351-
String[] notToDelete = clientConf.info.getBuildNumbersNotToDelete();
352-
for (String notToDel : notToDelete) {
353-
buildRetention.addBuildNotToBeDiscarded(notToDel);
354-
}
355-
builder.buildRetention(buildRetention);
356-
357339
String issueTrackerName = clientConf.info.issues.getIssueTrackerName();
358340
if (StringUtils.isNotBlank(issueTrackerName)) {
359341
Issues issues = new Issues();
@@ -398,7 +380,7 @@ private void doDeploy(BuildEvent event) {
398380
deployArtifacts(project, client, deployDetails, patterns);
399381
}
400382
if (clientConf.publisher.isPublishBuildInfo()) {
401-
client.sendBuildInfo(build);
383+
Utils.sendBuildAndBuildRetention(client, build, clientConf);
402384
}
403385
isDidDeploy = true;
404386
} catch (IOException e) {

build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/BuildDeploymentHelper.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.jfrog.build.extractor.clientConfiguration.IncludeExcludePatterns;
3434
import org.jfrog.build.extractor.clientConfiguration.PatternMatcher;
3535
import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient;
36+
import org.jfrog.build.extractor.retention.Utils;
3637

3738
import java.io.File;
3839
import java.io.IOException;
@@ -116,10 +117,10 @@ public void deploy( Build build,
116117
client.sendBuildInfo( buildInfoMerged );
117118
}
118119
else {
119-
client.sendBuildInfo( build );
120+
Utils.sendBuildAndBuildRetention(client, build, clientConf);
120121
}
121122
} catch ( Exception e ) {
122-
throw new RuntimeException("Error occurred while publishing Build Info to Artifactory.", e);
123+
throw new RuntimeException(e);
123124
}
124125
}
125126
} finally {

build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/BuildInfoModelPropertyResolver.java

-19
Original file line numberDiff line numberDiff line change
@@ -91,26 +91,7 @@ public BuildInfoMavenBuilder resolveProperties(ExecutionEvent event, Artifactory
9191
Governance governance = new Governance();
9292
governance.setBlackDuckProperties(blackDuckProperties);
9393
builder.governance(governance);
94-
95-
BuildRetention buildRetention = new BuildRetention(clientConf.info.isDeleteBuildArtifacts());
96-
if (clientConf.info.getBuildRetentionCount() != null) {
97-
buildRetention.setCount(clientConf.info.getBuildRetentionCount());
98-
}
99-
String buildRetentionMinimumDays = clientConf.info.getBuildRetentionMinimumDate();
100-
if (StringUtils.isNotBlank(buildRetentionMinimumDays)) {
101-
int minimumDays = Integer.parseInt(buildRetentionMinimumDays);
102-
if (minimumDays > -1) {
103-
Calendar calendar = Calendar.getInstance();
104-
calendar.add(Calendar.DAY_OF_YEAR, -minimumDays);
105-
buildRetention.setMinimumBuildDate(calendar.getTime());
106-
}
107-
}
108-
String[] notToDelete = clientConf.info.getBuildNumbersNotToDelete();
109-
for (String notToDel : notToDelete) {
110-
buildRetention.addBuildNotToBeDiscarded(notToDel);
111-
}
11294
attachStagingIfNeeded(clientConf, builder);
113-
builder.buildRetention(buildRetention);
11495
builder.artifactoryPrincipal(clientConf.publisher.getName());
11596

11697
builder.artifactoryPluginVersion(clientConf.info.getArtifactoryPluginVersion());

build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBuildInfoClient.java

+46-11
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.apache.http.protocol.HTTP;
4141
import org.apache.http.util.EntityUtils;
4242
import org.jfrog.build.api.Build;
43+
import org.jfrog.build.api.BuildRetention;
4344
import org.jfrog.build.api.release.BintrayUploadInfoOverride;
4445
import org.jfrog.build.api.release.Promotion;
4546
import org.jfrog.build.api.util.FileChecksumCalculator;
@@ -73,8 +74,11 @@ public class ArtifactoryBuildInfoClient extends ArtifactoryBaseClient {
7374
private static final String VIRTUAL_REPOS_REST_URL = "/api/repositories?type=virtual";
7475
private static final String PUSH_TO_BINTRAY_REST_URL = "/api/build/pushToBintray/";
7576
private static final String BUILD_REST_URL = "/api/build";
77+
private static final String BUILD_RETENTION_REST_URL = BUILD_REST_URL + "/retention/";
7678
private static final int CHECKSUM_DEPLOY_MIN_FILE_SIZE = 10240; // Try checksum deploy of files greater than 10KB
7779
public static final String BUILD_BROWSE_URL = "/webapp/builds";
80+
public static final String APPLICATION_VND_ORG_JFROG_ARTIFACTORY_JSON = "application/vnd.org.jfrog.artifactory+json";
81+
public static final String APPLICATION_JSON = "application/json";
7882

7983
/**
8084
* Version of Artifactory we work with.
@@ -180,7 +184,25 @@ private List<String> getRepositoriesList(String restUrl) throws IOException {
180184
public void sendBuildInfo(String buildInfoJson) throws IOException {
181185
String url = artifactoryUrl + BUILD_REST_URL;
182186
HttpPut httpPut = new HttpPut(url);
183-
sendDescriptor(httpPut, buildInfoJson);
187+
try {
188+
sendDescriptor(httpPut, buildInfoJson, APPLICATION_VND_ORG_JFROG_ARTIFACTORY_JSON);
189+
} catch (IOException e) {
190+
throw new IOException("Failed to send build descriptor. " + e.getMessage(), e);
191+
}
192+
}
193+
194+
public void sendBuildRetetion(BuildRetention buildRetantion, String buildName) throws IOException {
195+
String buildRetantionJson = toJsonString(buildRetantion);
196+
String url = artifactoryUrl + BUILD_RETENTION_REST_URL + buildName;
197+
HttpPost httpPost = new HttpPost(url);
198+
try {
199+
log.info("Executing build retention");
200+
log.debug(buildRetantionJson);
201+
sendRequest(httpPost, buildRetantionJson, APPLICATION_JSON, true);
202+
} catch (IOException e) {
203+
log.error("Failed to execute build retention.", e);
204+
throw new IOException("Failed to execute build retention: " + e.getMessage(), e);
205+
}
184206
}
185207

186208
/**
@@ -209,23 +231,36 @@ public void sendModuleInfo(Build build) throws IOException {
209231
encodeUrl(build.getNumber());
210232
HttpPost httpPost = new HttpPost(url);
211233
String modulesAsJsonString = toJsonString(build.getModules());
212-
sendDescriptor(httpPost, modulesAsJsonString);
234+
sendDescriptor(httpPost, modulesAsJsonString, APPLICATION_VND_ORG_JFROG_ARTIFACTORY_JSON);
213235
} catch (Exception e) {
214236
log.error("Could not build the build-info modules object.", e);
215-
throw new IOException("Could not publish build-info modules: " + e.getMessage());
237+
throw new IOException("Could not publish build-info modules: " + e.getMessage(), e);
216238
}
217239
}
218240

219-
private void sendDescriptor(HttpEntityEnclosingRequestBase request, String content) throws IOException {
241+
private void sendDescriptor(HttpEntityEnclosingRequestBase request, String content, String contentType) throws IOException {
242+
log.info("Deploying build descriptor to: " + request.getURI().toString());
243+
sendRequest(request, content, contentType, true);
244+
}
245+
246+
private void sendRequest(HttpEntityEnclosingRequestBase request, String content, String contentType, boolean retry) throws IOException {
220247
StringEntity stringEntity = new StringEntity(content, "UTF-8");
221-
stringEntity.setContentType("application/vnd.org.jfrog.artifactory+json");
248+
stringEntity.setContentType(contentType);
222249
request.setEntity(stringEntity);
223-
log.info("Deploying build descriptor to: " + request.getURI().toString());
224-
HttpResponse response = httpClient.getHttpClient().execute(request);
225-
StatusLine statusLine = response.getStatusLine();
226-
if (statusLine.getStatusCode() != HttpStatus.SC_NO_CONTENT) {
227-
HttpEntity responseEntity = response.getEntity();
228-
throw new IOException("Failed to send build descriptor. Status code: " + statusLine.getStatusCode() + getMessageFromEntity(responseEntity));
250+
int connectionRetries = httpClient.getConnectionRetries();
251+
try {
252+
if (!retry) {
253+
httpClient.setConnectionRetries(0);
254+
}
255+
HttpResponse response = httpClient.getHttpClient().execute(request);
256+
StatusLine statusLine = response.getStatusLine();
257+
if (statusLine.getStatusCode() != HttpStatus.SC_NO_CONTENT) {
258+
HttpEntity responseEntity = response.getEntity();
259+
throw new IOException(statusLine.getStatusCode() + getMessageFromEntity(responseEntity));
260+
}
261+
} finally {
262+
// We are using the same client for multiple operations therefore we need to restore the connectionRetries configuration.
263+
httpClient.setConnectionRetries(connectionRetries);
229264
}
230265
}
231266

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.jfrog.build.extractor.retention;
2+
3+
import org.apache.commons.lang.StringUtils;
4+
import org.jfrog.build.api.Build;
5+
import org.jfrog.build.api.BuildRetention;
6+
import org.jfrog.build.client.ArtifactoryHttpClient;
7+
import org.jfrog.build.client.ArtifactoryVersion;
8+
import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration;
9+
import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient;
10+
import org.jfrog.build.util.VersionException;
11+
12+
import java.io.IOException;
13+
import java.util.Calendar;
14+
15+
import static org.jfrog.build.client.ArtifactoryHttpClient.encodeUrl;
16+
17+
/**
18+
* Created by tamirh on 13/04/2017.
19+
*/
20+
public class Utils {
21+
22+
private static BuildRetention getBuildRetention(ArtifactoryClientConfiguration clientConf) {
23+
BuildRetention buildRetention = new BuildRetention(clientConf.info.isDeleteBuildArtifacts());
24+
if (clientConf.info.getBuildRetentionCount() != null) {
25+
buildRetention.setCount(clientConf.info.getBuildRetentionCount());
26+
}
27+
String buildRetentionMinimumDays = clientConf.info.getBuildRetentionMinimumDate();
28+
if (StringUtils.isNotBlank(buildRetentionMinimumDays)) {
29+
int minimumDays = Integer.parseInt(buildRetentionMinimumDays);
30+
if (minimumDays > -1) {
31+
Calendar calendar = Calendar.getInstance();
32+
calendar.add(Calendar.DAY_OF_YEAR, -minimumDays);
33+
buildRetention.setMinimumBuildDate(calendar.getTime());
34+
}
35+
}
36+
String[] notToDelete = clientConf.info.getBuildNumbersNotToDelete();
37+
for (String notToDel : notToDelete) {
38+
buildRetention.addBuildNotToBeDiscarded(notToDel);
39+
}
40+
41+
return buildRetention;
42+
}
43+
44+
private static void addRetentionIfNeeded(Build build, BuildRetention retention, ArtifactoryVersion version) {
45+
if (!version.isAtLeast(ArtifactoryHttpClient.STANDALONE_BUILD_RETENTION_SUPPORTED_ARTIFACTORY_VERSION)) {
46+
build.setBuildRetention(retention);
47+
}
48+
}
49+
50+
private static void sendRetentionIfNeeded(ArtifactoryBuildInfoClient client, BuildRetention retention, String buildName, ArtifactoryVersion version) throws IOException {
51+
if (version.isAtLeast(ArtifactoryHttpClient.STANDALONE_BUILD_RETENTION_SUPPORTED_ARTIFACTORY_VERSION)) {
52+
client.sendBuildRetetion(retention, encodeUrl(buildName));
53+
}
54+
}
55+
56+
public static void sendBuildAndBuildRetention(ArtifactoryBuildInfoClient client, Build build, ArtifactoryClientConfiguration clientConf) throws IOException {
57+
BuildRetention retention = getBuildRetention(clientConf);
58+
sendBuildAndBuildRetention(client, build, retention);
59+
}
60+
61+
public static void sendBuildAndBuildRetention(ArtifactoryBuildInfoClient client, Build build, BuildRetention retention) throws IOException {
62+
if (retention.isEmpty()) {
63+
client.sendBuildInfo(build);
64+
return;
65+
}
66+
ArtifactoryVersion version;
67+
try {
68+
version = client.verifyCompatibleArtifactoryVersion();
69+
} catch (VersionException e) {
70+
throw new RuntimeException(e);
71+
}
72+
addRetentionIfNeeded(build, retention, version);
73+
client.sendBuildInfo(build);
74+
sendRetentionIfNeeded(client, retention, build.getName(), version);
75+
}
76+
}

0 commit comments

Comments
 (0)