/**
* Copyright 2014 ArcBees Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.arcbees.staging;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.HttpStatus;
import org.apache.tomcat.maven.common.deployer.TomcatManager;
import org.apache.tomcat.maven.common.deployer.TomcatManagerException;
import org.apache.tomcat.maven.common.deployer.TomcatManagerResponse;
import org.jetbrains.annotations.NotNull;
import com.arcbees.vcs.VcsApi;
import com.arcbees.vcs.VcsApiFactories;
import com.arcbees.vcs.VcsConstants;
import com.arcbees.vcs.VcsPropertiesHelper;
import com.arcbees.vcs.model.PullRequest;
import com.arcbees.vcs.model.PullRequestTarget;
import com.arcbees.vcs.model.PullRequests;
import com.arcbees.vcs.util.JsonCustomDataStorage;
import com.google.common.base.Strings;
import jetbrains.buildServer.buildTriggers.BuildTriggerDescriptor;
import jetbrains.buildServer.buildTriggers.BuildTriggerException;
import jetbrains.buildServer.buildTriggers.PolledBuildTrigger;
import jetbrains.buildServer.buildTriggers.PolledTriggerContext;
public class TomcatStagingTrigger extends PolledBuildTrigger {
private static final Logger LOGGER = Logger.getLogger(TomcatStagingTrigger.class.getName());
private final VcsApiFactories vcsApiFactories;
private final TomcatManagerFactory tomcatManagerFactory;
private final Constants constants;
private final VcsConstants vcsConstants;
public TomcatStagingTrigger(VcsApiFactories vcsApiFactories,
TomcatManagerFactory tomcatManagerFactory,
Constants constants,
VcsConstants vcsConstants) {
this.vcsApiFactories = vcsApiFactories;
this.tomcatManagerFactory = tomcatManagerFactory;
this.constants = constants;
this.vcsConstants = vcsConstants;
}
@Override
public void triggerBuild(@NotNull PolledTriggerContext context) throws BuildTriggerException {
BuildTriggerDescriptor triggerDescriptor = context.getTriggerDescriptor();
Map<String, String> properties = triggerDescriptor.getProperties();
StagingPropertiesHelper stagingPropertiesHelper = new StagingPropertiesHelper(properties, constants);
String mergeBranch = stagingPropertiesHelper.getMergeBranch();
if (!Strings.isNullOrEmpty(mergeBranch)) {
try {
checkBranchesToUndeploy(context, properties, stagingPropertiesHelper, mergeBranch);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
}
private void checkBranchesToUndeploy(PolledTriggerContext context, Map<String, String> properties,
StagingPropertiesHelper stagingPropertiesHelper, String mergeBranch)
throws IOException {
VcsPropertiesHelper vcsPropertiesHelper = new VcsPropertiesHelper(properties, vcsConstants);
String repositoryOwner = vcsPropertiesHelper.getRepositoryOwner();
String repositoryName = vcsPropertiesHelper.getRepositoryName();
JsonCustomDataStorage<TomcatStagingDeploy> dataStorage =
JsonCustomDataStorage.create(context.getCustomDataStorage(), TomcatStagingDeploy.class);
TomcatManager tomcatManager = createTomcatManager(stagingPropertiesHelper);
PullRequests<? extends PullRequest> pullRequests = getMergedPullRequests(vcsPropertiesHelper);
for (PullRequest pullRequest : pullRequests.getPullRequests()) {
if (isTargetMergeBranch(mergeBranch, pullRequest)) {
String pullRequestKey = getPullRequestKey(repositoryOwner, repositoryName, pullRequest);
TomcatStagingDeploy stagingDeploy = getTomcatStagingDeploy(dataStorage, pullRequest, pullRequestKey);
if (stagingDeploy.isDeployed() && !stagingDeploy.isUndeployed()) {
undeploy(tomcatManager, stagingDeploy);
dataStorage.putValue(pullRequestKey, stagingDeploy);
}
}
}
}
private PullRequests getMergedPullRequests(VcsPropertiesHelper vcsPropertiesHelper) throws IOException {
VcsApi vcsApi = vcsApiFactories.create(vcsPropertiesHelper);
return vcsApi.getMergedPullRequests();
}
private TomcatStagingDeploy getTomcatStagingDeploy(JsonCustomDataStorage<TomcatStagingDeploy> dataStorage,
PullRequest pullRequest,
String pullRequestKey) {
TomcatStagingDeploy stagingDeploy = dataStorage.getValue(pullRequestKey);
if (stagingDeploy == null) {
stagingDeploy = new TomcatStagingDeploy(pullRequest, false);
}
return stagingDeploy;
}
private TomcatManager createTomcatManager(StagingPropertiesHelper propertiesHelper) {
try {
return tomcatManagerFactory.create(propertiesHelper);
} catch (MalformedURLException | URISyntaxException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
throw new BuildTriggerException(e.getMessage(), e);
}
}
private boolean isTargetMergeBranch(String mergeBranch, PullRequest pullRequest) {
String branchName = getBranchName(pullRequest.getDestination());
return mergeBranch.equals(branchName);
}
private void undeploy(TomcatManager tomcatManager, TomcatStagingDeploy stagingDeploy) throws IOException {
boolean success;
try {
String webPath = getWebAppUndeployPath(tomcatManager, stagingDeploy);
LOGGER.info("Undeploying WebAPP : " + webPath);
TomcatManagerResponse response = tomcatManager.undeploy(webPath);
int statusCode = response.getStatusCode();
LOGGER.info("Undeploying Status : " + statusCode);
success = HttpStatus.SC_OK == statusCode || HttpStatus.SC_NOT_FOUND == statusCode;
} catch (TomcatManagerException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
success = false;
}
stagingDeploy.setUndeployed(success);
}
private String getWebAppUndeployPath(TomcatManager tomcatManager,
TomcatStagingDeploy stagingDeploy) {
String tomcatUrl = UrlUtils.extractBaseUrl(tomcatManager.getURL());
return Strings.nullToEmpty(stagingDeploy.getWebPath())
.replace(tomcatUrl, "");
}
private String getBranchName(PullRequestTarget source) {
return source.getBranch().getName();
}
private String getPullRequestKey(String repositoryOwner, String repositoryName, PullRequest pullRequest) {
return vcsConstants.getPullRequestKey() + repositoryOwner + "_" + repositoryName + "_"
+ pullRequest.getId();
}
}