Package ch.ethz.origo

Source Code of ch.ethz.origo.OrigoIssuePublisher$DescriptorImpl

/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Bruce Chapman, Erik Ramfelt, Jean-Baptiste Quenot, Luca Domenico Milanesio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package ch.ethz.origo;

import hudson.Extension;
import hudson.Functions;
import hudson.Launcher;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Hudson;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import hudson.tasks.Mailer;
import hudson.util.FormValidation;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.xmlrpc.XmlRpcException;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;

/**
* {@link Publisher} that creates/updates an Origo issue based on the build
* result.
*
* @author Patrick Ruckstuhl
*/
public class OrigoIssuePublisher extends Notifier {

  @Extension
  public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
    private String apiUrl;
    private String projectName;
    private String userKey;
    private String issueSubject;
    private String issueTag;
    private boolean issuePrivate = true;

    private String hudsonUrl;

    public DescriptorImpl() {
      load();
    }

    @Override
    public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
      req.bindParameters(this, "origo.issues.");
      // hudsonUrl is read from Mailer
      hudsonUrl = Mailer.descriptor().getUrl();
      save();
      return super.configure(req, formData);
    }

    public FormValidation doCheckApiUrl(@QueryParameter String value) {
      try {
        new URL(value);
        return FormValidation.ok();
      } catch (MalformedURLException e) {
        return FormValidation.error("Invalid url specified");
      }
    }

    public FormValidation doCheckIssueSubject(@QueryParameter String value) {
      if (StringUtils.isNotEmpty(value)) {
        return FormValidation.ok();
      } else {
        return FormValidation.error("Issue subject is mandatory");
      }
    }

    public FormValidation doCheckIssueTag(@QueryParameter String value) {
      if (StringUtils.isNotEmpty(value)) {
        return FormValidation.ok();
      } else {
        return FormValidation.error("Issue tag is mandatory");
      }
    }

    public FormValidation doCheckProjectName(@QueryParameter String value) {
      if (StringUtils.isNotEmpty(value)) {
        return FormValidation.ok();
      } else {
        return FormValidation.error("Project name is mandatory");
      }
    }

    public FormValidation doCheckUserKey(@QueryParameter String value) {
      if (StringUtils.isNotEmpty(value)) {
        return FormValidation.ok();
      } else {
        return FormValidation.error("User key is mandatory");
      }
    }

    public String getApiUrl() {
      return apiUrl;
    }

    @Override
    public String getDisplayName() {
      return "Origo Issues";
    }

    public String getHudsonUrl() {
      return hudsonUrl;
    }

    public String getIssueSubject() {
      return issueSubject;
    }

    public String getIssueTag() {
      return issueTag;
    }

    public String getProjectName() {
      return projectName;
    }

    public String getUserKey() {
      return userKey;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public boolean isApplicable(Class<? extends AbstractProject> jobType) {
      return true;
    }

    public boolean isIssuePrivate() {
      return issuePrivate;
    }

    @Override
    public Publisher newInstance(StaplerRequest req, JSONObject formData) throws FormException {
      if (hudsonUrl == null) {
        // if Hudson URL is not configured yet, infer some default
        hudsonUrl = Functions.inferHudsonURL(req);
        save();
      }
      return super.newInstance(req, formData);
    }

    public void setApiUrl(String apiUrl) {
      this.apiUrl = apiUrl;
    }

    public void setHudsonUrl(String hudsonUrl) {
      this.hudsonUrl = hudsonUrl;
    }

    public void setIssuePrivate(boolean issuePrivate) {
      this.issuePrivate = issuePrivate;
    }

    public void setIssueSubject(String issueSubject) {
      this.issueSubject = issueSubject;
    }

    public void setIssueTag(String issueTag) {
      this.issueTag = issueTag;
    }

    public void setProjectName(String projectName) {
      this.projectName = projectName;
    }

    public void setUserKey(String userKey) {
      this.userKey = userKey;
    }
  }

  private static final Logger LOGGER = Logger.getLogger(OrigoIssuePublisher.class.getName());

  static final String APPLICATION_KEY = "KEYFORTHEORIGOHUDSONISSUESPLUGIN";

  private String apiUrl;
  private String projectName;
  private String userKey;
  private String issueSubject;
  private String issueTag;
  private boolean issuePrivate;
  private OrigoApiClient client;

  OrigoIssuePublisher(String apiUrl, String projectName, String userKey, String issueSubject, String issueTag,
      boolean issuePrivate, OrigoApiClient client) {
    super();
    this.apiUrl = apiUrl;
    this.projectName = projectName;
    this.userKey = userKey;
    this.issueSubject = issueSubject;
    this.issueTag = issueTag;
    this.issuePrivate = issuePrivate;
    this.client = client;
  }

  @DataBoundConstructor
  public OrigoIssuePublisher(String apiUrl, String projectName, String userKey, String issueSubject, String issueTag,
      boolean issuePrivate) {
    super();
    this.apiUrl = apiUrl;
    this.projectName = projectName;
    this.userKey = userKey;
    this.issueSubject = issueSubject;
    this.issueTag = issueTag;
    this.issuePrivate = issuePrivate;
  }

  public String getApiUrl() {
    return apiUrl;
  }
 
  @Override
  public DescriptorImpl getDescriptor() {
    return Hudson.getInstance().getDescriptorByType(OrigoIssuePublisher.DescriptorImpl.class);
  }

  public String getIssueSubject() {
    return issueSubject;
  }

  public String getIssueTag() {
    return issueTag;
  }

  public String getProjectName() {
    return projectName;
  }

  public BuildStepMonitor getRequiredMonitorService() {
    return BuildStepMonitor.BUILD;
  }

  public String getUserKey() {
    return userKey;
  }

  public boolean isIssuePrivate() {
    return issuePrivate;
  }

  private OrigoApiClient createClient() throws MalformedURLException {
    if(client == null) {
      return new OrigoApiClient(new URL(apiUrl));
    }else{
      return client;
    }
  }
 
  @Override
  public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) {

    try {
      boolean isNewFailure = isNewFailure(build);
      boolean isRecovery = isRecovery(build);
      if (isNewFailure || isRecovery) {
        OrigoApiClient client= createClient();
       
        // login
        String session = client.login(userKey, APPLICATION_KEY);
        LOGGER.fine("Got session" + session);

        // get project id
        Integer projectId = client.retrieveProjectId(session, projectName);

        if (isNewFailure) {
          openNewIssue(build, client, session, projectId);
        } else if (isRecovery) {
          closeExistingIssue(build, client, session, projectId);
        }
      }
    } catch (Exception e) {
      LOGGER.log(Level.SEVERE, "Unable to update origo issue.", e);
    }

    return true;
  }

  private void closeExistingIssue(AbstractBuild<?, ?> build, OrigoApiClient client, String session, Integer projectId)
      throws XmlRpcException {
    // search issue
    HashMap<String, String> searchArgs = new HashMap<String, String>();
    searchArgs.put("status", "open");
    searchArgs.put("tags", issueTag);
    Object[] issues = client.searchIssue(session, projectId, searchArgs);
    if (issues != null && issues.length == 1) {
      // close issue
      Map<Object, Object> issue = (Map<Object, Object>) issues[0];
      Integer issueId = (Integer) issue.get("issue_id");
      LOGGER.fine("Found issue with id " + issueId);

      String issueDescription = "Build fixed see: " + createLinkUrl(build);
      client.extendedCommentIssue(session, projectId, issueId, issueDescription, "status::closed," + issueTag);
    } else {
      LOGGER.warning("Did not find exactly one match.");
    }
  }

  private String createLinkUrl(AbstractBuild<?, ?> build) {
    return getDescriptor().getHudsonUrl() + build.getUrl();
  }

  private boolean isNewFailure(AbstractBuild<?, ?> build) {
    Result previousResult = build.getPreviousBuild() != null ? build.getPreviousBuild().getResult()
        : Result.SUCCESS;
    Result currentResult = build.getResult();
    return previousResult == Result.SUCCESS
        && (currentResult == Result.FAILURE || build.getResult() == Result.UNSTABLE);
  }

  private boolean isRecovery(AbstractBuild<?, ?> build) {
    Result previousResult = build.getPreviousBuild() != null ? build.getPreviousBuild().getResult()
        : Result.SUCCESS;
    Result currentResult = build.getResult();
    return currentResult == Result.SUCCESS
        && (previousResult == Result.FAILURE || build.getPreviousBuild().getResult() == Result.UNSTABLE);
  }

  private void openNewIssue(AbstractBuild<?, ?> build, OrigoApiClient client, String session, Integer projectId)
      throws XmlRpcException {
    // create issue
    String issueDescription = "Build failed see: " + createLinkUrl(build);
    System.out.println(issueDescription);
    client.addIssue(session, projectId, issueSubject, issueDescription, "status::open," + issueTag, issuePrivate);
  }
}
TOP

Related Classes of ch.ethz.origo.OrigoIssuePublisher$DescriptorImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.