package org.jfrog.hudson.release; import hudson.model.TaskListener; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.commons.io.IOUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.jfrog.build.api.builder.PromotionBuilder; import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; import java.io.IOException; import java.io.InputStream; /** * Created by romang on 6/21/16. */ public class PromotionUtils { /** * Two stage promotion, dry run and actual promotion to verify correctness. * * @param promotionBuilder * @param client * @param listener * @param buildName * @param buildNumber * @throws IOException */ public static boolean promoteAndCheckResponse(PromotionBuilder promotionBuilder, ArtifactoryBuildInfoClient client, TaskListener listener, String buildName, String buildNumber) throws IOException { // do a dry run first promotionBuilder.dryRun(true); listener.getLogger().println("Performing dry run promotion (no changes are made during dry run) ..."); HttpResponse dryResponse = client.stageBuild(buildName, buildNumber, promotionBuilder.build()); if (checkSuccess(dryResponse, true, promotionBuilder.isFailFast(), true, listener)) { listener.getLogger().println("Dry run finished successfully.\nPerforming promotion ..."); HttpResponse wetResponse = client.stageBuild(buildName, buildNumber, promotionBuilder.dryRun(false).build()); if (checkSuccess(wetResponse, false, promotionBuilder.isFailFast(), true, listener)) { listener.getLogger().println("Promotion completed successfully!"); return true; } } return false; } /** * Checks the status of promotion response and return true on success * * @param response * @param dryRun * @param parseMessages * @param listener * @return */ public static boolean checkSuccess(HttpResponse response, boolean dryRun, boolean failFast, boolean parseMessages, TaskListener listener) { StatusLine status = response.getStatusLine(); try { String content = entityToString(response); if (assertResponseStatus(dryRun, failFast, listener, status, content)) { if (parseMessages) { JSONObject json = JSONObject.fromObject(content); JSONArray messages = json.getJSONArray("messages"); for (Object messageObj : messages) { JSONObject messageJson = (JSONObject) messageObj; String level = messageJson.getString("level"); String message = messageJson.getString("message"); // TODO: we don't want to fail if no items were moved/copied. find a way to support it if ((level.equals("WARNING") || level.equals("ERROR")) && !message.startsWith("No items were") && failFast) { listener.error("Received " + level + ": " + message); return false; } } } listener.getLogger().println(content); return true; } } catch (IOException e) { e.printStackTrace(listener.error("Failed parsing promotion response:")); } return false; } private static String entityToString(HttpResponse response) throws IOException { HttpEntity entity = response.getEntity(); InputStream is = entity.getContent(); return IOUtils.toString(is, "UTF-8"); } private static boolean assertResponseStatus(boolean dryRun, boolean failFast, TaskListener listener, StatusLine status, String content) { if (status.getStatusCode() != 200 && failFast) { if (dryRun) { listener.error( "Promotion failed during dry run (no change in Artifactory was done): " + status + "\n" + content); } else { listener.error( "Promotion failed. View Artifactory logs for more details: " + status + "\n" + content); } return false; } return true; } }