package org.jfrog.bamboo.bintray; import com.google.common.collect.Lists; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.jfrog.bamboo.admin.ServerConfig; import org.jfrog.bamboo.bintray.client.BintrayClient; import org.jfrog.bamboo.util.ActionLog; import org.jfrog.bamboo.util.BuildInfoLog; import org.jfrog.build.api.release.BintrayUploadInfoOverride; import org.jfrog.build.client.ArtifactoryVersion; import org.jfrog.build.client.bintrayResponse.BintrayResponse; import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; import java.util.List; import java.util.Map; /** * Push to Bintray Runnable to pass in to a Thread that will preform this task on Bamboo * * @author Aviad Shikloshi */ public class PushToBintrayRunnable implements Runnable { private static final String MINIMAL_SUPPORTED_VERSION = "3.6"; private Logger log = Logger.getLogger(PushToBintrayRunnable.class); private BintrayClient bintrayClient; private ServerConfig serverConfig; private PushToBintrayAction action; private ActionLog bintrayLog; private String buildName; private String buildNumber; public PushToBintrayRunnable(PushToBintrayAction pushToBintrayAction, ServerConfig serverConfig, BintrayClient bintrayClient) { this.action = pushToBintrayAction; this.serverConfig = serverConfig; this.bintrayClient = bintrayClient; this.bintrayLog = PushToBintrayAction.context.getActionLog(); this.buildName = PushToBintrayAction.context.getBuildKey(); this.buildNumber = Integer.toString(PushToBintrayAction.context.getBuildNumber()); } /** * Run method to perform Push to Bintray action * This method sets the isSuccessfullyDone in the action object to use later in the action view */ @Override public void run() { ArtifactoryBuildInfoClient artifactoryClient = null; try { bintrayLog.logMessage("Starting Push to Bintray action."); PushToBintrayAction.context.getLock().lock(); PushToBintrayAction.context.setDone(false); artifactoryClient = getArtifactoryBuildInfoClient(); if (!isValidArtifactoryVersion(artifactoryClient)) { bintrayLog.logError("Push to Bintray supported from Artifactory version " + MINIMAL_SUPPORTED_VERSION); PushToBintrayAction.context.setDone(true); return; } performPushToBintray(artifactoryClient); if (action.isMavenSync()) { bintrayLog.logMessage("Starting MavenSync."); mavenCentralSync(); } } catch (Exception e) { bintrayLog.logError("Error while trying to Push build to Bintray.", e); log.error("Error while trying to Push build to Bintray.", e); } finally { if (artifactoryClient != null) { artifactoryClient.close(); } PushToBintrayAction.context.setDone(true); PushToBintrayAction.context.getLock().unlock(); } } /** * Create the relevant objects from input and send it to build info artifactoryClient that will preform the actual push * Set the result of the action to true if successful to use in the action view. */ private void performPushToBintray(ArtifactoryBuildInfoClient artifactoryClient) { String subject = action.getSubject(), repoName = action.getRepository(), packageName = action.getPackageName(), versionName = action.getVersion(), vcsUrl = action.getVcsUrl(), signMethod = action.getSignMethod(), passphrase = action.getGpgPassphrase(); List<String> licenses = createLicensesListFromString(action.getLicenses()); BintrayUploadInfoOverride uploadInfoOverride = new BintrayUploadInfoOverride(subject, repoName, packageName, versionName, licenses, vcsUrl); BintrayResponse response; try { response = artifactoryClient.pushToBintray(buildName, buildNumber, signMethod, passphrase, uploadInfoOverride); bintrayLog.logMessage(response.toString()); log.info("Push to Bintray finished: " + response.toString()); } catch (Exception e) { throw new RuntimeException("Push to Bintray failed with Exception.", e); } if (!response.isSuccessful()) { throw new RuntimeException("Push to Bintray failed with Exception"); } } /** * Trigger's Bintray MavenCentralSync API */ private void mavenCentralSync() { if (!Boolean.valueOf(action.isOverrideDescriptorFile())) { prepareMavenCentralSync(); } try { bintrayLog.logMessage("Syncing version to Maven Central."); String response = bintrayClient.mavenCentralSync(action.getSubject(), action.getRepository(), action.getPackageName(), action.getVersion()); bintrayLog.logMessage(response); } catch (Exception e) { bintrayLog.logError("Error while trying to sync with Maven Central", e); log.error("Error while trying to sync with Maven Central", e); } } // When using descriptor file with MavenCentralSync we don't have any of the details Bintray is expecting for (package name, // version, subject etc. So we must read it from the bintray-info.json file frmo Artifactory. private void prepareMavenCentralSync() { // fetch the location of the file from Artifactory Map<String, Object> response = bintrayClient.getBintrayJsonFileLocation(serverConfig, buildName, buildNumber); // parse Artifactory response and get the download URI String fileUrl = MavenSyncHelper.getBintrayDescriptorFileUrl(response); // download the file to memory Map<String, Object> bintrayJsonMap = bintrayClient.downloadBintrayInfoDescriptor(serverConfig, fileUrl); // populate the properties we now have to the action context - subject, repo name, package name and version. MavenSyncHelper.updateBintrayActionContext(action, bintrayJsonMap); } private boolean isValidArtifactoryVersion(ArtifactoryBuildInfoClient client) { boolean validVersion = false; try { ArtifactoryVersion version = client.verifyCompatibleArtifactoryVersion(); validVersion = version.isAtLeast(new ArtifactoryVersion(MINIMAL_SUPPORTED_VERSION)); } catch (Exception e) { bintrayLog.logError("Error while checking Artifactory version", e); log.error("Error while checking Artifactory version", e); } return validVersion; } private ArtifactoryBuildInfoClient getArtifactoryBuildInfoClient() { String username = serverConfig.getUsername(); String password = serverConfig.getPassword(); String artifactoryUrl = serverConfig.getUrl(); return new ArtifactoryBuildInfoClient(artifactoryUrl, username, password, new BuildInfoLog(log)); } private List<String> createLicensesListFromString(String licenses) { String[] licensesArray = StringUtils.split(licenses, ","); for (int i = 0; i < licensesArray.length; i++) { licensesArray[i] = licensesArray[i].trim(); } return Lists.newArrayList(licensesArray); } }