All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.ParameterExpander Maven / Gradle / Ivy

The newest version!
/*
 *  The MIT License
 *
 *  Copyright 2010 Sony Ericsson Mobile Communications.
 *
 *  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 com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier;

import com.sonyericsson.hudson.plugins.gerrit.trigger.config.IGerritHudsonTriggerConfig;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.model.BuildMemory.MemoryImprint;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.model.BuildMemory.MemoryImprint.Entry;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.model.BuildsStartedStats;
import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritTrigger;
import com.sonyericsson.hudson.plugins.gerrit.trigger.utils.StringUtil;
import com.sonyericsson.hudson.plugins.gerrit.gerritevents.dto.events.PatchsetCreated;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Hudson;
import hudson.model.Result;
import hudson.model.TaskListener;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Expands a parameterized string to it's full potential.
 * @author Robert Sandell <[email protected]>
 */
public class ParameterExpander {

    /**
     * How many default parameters there are (plus one) to initialize the size of the parameters-map.
     */
    public static final int DEFAULT_PARAMETERS_COUNT = 11;

    private static final Logger logger = LoggerFactory.getLogger(ParameterExpander.class);
    private IGerritHudsonTriggerConfig config;
    private Hudson hudson;

    /**
     * Constructor.
     * @param config the global config.
     * @param hudson the hudson instance.
     */
    public ParameterExpander(IGerritHudsonTriggerConfig config, Hudson hudson) {
        this.config = config;
        this.hudson = hudson;
    }

    /**
     * Constructor.
     * @param config the global config.
     */
    public ParameterExpander(IGerritHudsonTriggerConfig config) {
        this(config, Hudson.getInstance());
    }

    /**
     * Gets the expanded string to send to Gerrit for a build-started event.
     * @param r the build.
     * @param taskListener the taskListener.
     * @param event the event.
     * @param stats the statistics.
     * @return the "expanded" command string.
     */
    public String getBuildStartedCommand(AbstractBuild r, TaskListener taskListener,
            PatchsetCreated event, BuildsStartedStats stats) {

        String gerritCmd = config.getGerritCmdBuildStarted();
        Map parameters = createStandardParameters(r, event,
                getBuildStartedCodeReviewValue(r),
                getBuildStartedVerifiedValue(r));
        String startedStats = "";
        if (stats.getTotalBuildsToStart() > 1) {
            startedStats = stats.toString();
        }
        parameters.put("STARTED_STATS", startedStats);
        return expandParameters(gerritCmd, r, taskListener, parameters);
    }

    /**
     * Finds the verified vote for build started of the specified build.
     * If there is a {@link GerritTrigger} and it has a {@link GerritTrigger#getGerritBuildStartedVerifiedValue()}
     * specified, that value will be used, otherwise the global config value in
     * {@link IGerritHudsonTriggerConfig#getGerritBuildStartedVerifiedValue()} will be used.
     * @param r the build.
     * @return the value.
     */
    private int getBuildStartedVerifiedValue(AbstractBuild r) {
        GerritTrigger trigger = getTrigger(r.getProject());
        if (trigger == null) {
            logger.warn("Unable to get trigger config for build {} will use global value.");
            return config.getGerritBuildStartedVerifiedValue();
        } else if (trigger.getGerritBuildStartedVerifiedValue() != null) {
            final Integer value = trigger.getGerritBuildStartedVerifiedValue();
            logger.trace("BuildStartedVerified overridden in project config. returning {}", value);
            return value;
        } else {
            final int value = config.getGerritBuildStartedVerifiedValue();
            logger.trace("BuildStartedVerified standard value used {}", value);
            return value;
        }
    }

    /**
     * Finds the code review vote for build started of the specified build.
     * If there is a {@link GerritTrigger} and it has a {@link GerritTrigger#getGerritBuildStartedCodeReviewValue()}
     * specified, that value will be used, otherwise the global config value in
     * {@link IGerritHudsonTriggerConfig#getGerritBuildStartedCodeReviewValue()} will be used.
     * @param r the build.
     * @return the value.
     */
    private int getBuildStartedCodeReviewValue(AbstractBuild r) {
        GerritTrigger trigger = getTrigger(r.getProject());
        if (trigger == null) {
            logger.warn("Unable to get trigger config for build {} will use global value.");
            return config.getGerritBuildStartedCodeReviewValue();
        } else if (trigger.getGerritBuildStartedCodeReviewValue() != null) {
            final Integer value = trigger.getGerritBuildStartedCodeReviewValue();
            logger.trace("BuildStartedCodeReview overridden in project config. returning {}", value);
            return value;
        } else {
            final int value = config.getGerritBuildStartedCodeReviewValue();
            logger.trace("BuildStartedCodeReview standard value used {}", value);
            return value;
        }
    }

    /**
     * Creates a list of the "standard" trigger parameters.
     * They are present both for build started and completed.
     * The parameters are:
     * 
    *
  • GERRIT_NAME: The Gerrit project name.
  • *
  • CHANGE_ID: the Gerrit change-id (SHA-1)
  • *
  • BRANCH: The branch of the project.
  • *
  • CHANGE: The change number.
  • *
  • PATCHSET: The patchset number.
  • *
  • REFSPEC: the ref-spec. (refs/changes/xx/xxxx/z
  • *
  • BUILDURL: The URL to the build.
  • *
  • VERIFIED: The verified vote.
  • *
  • CODE_REVIEW: The code review vote.
  • *
* @param r the build. * @param event the event. * @param codeReview the code review vote. * @param verified the verified vote. * @return the parameters and their values. */ private Map createStandardParameters(AbstractBuild r, PatchsetCreated event, int codeReview, int verified) { // VERIFIED CODE_REVIEW Map map = new HashMap(DEFAULT_PARAMETERS_COUNT); map.put("GERRIT_NAME", event.getChange().getProject()); map.put("CHANGE_ID", event.getChange().getId()); map.put("BRANCH", event.getChange().getProject()); map.put("CHANGE", event.getChange().getNumber()); map.put("PATCHSET", event.getPatchSet().getNumber()); map.put("REFSPEC", StringUtil.makeRefSpec(event)); if (r != null) { map.put("BUILDURL", hudson.getRootUrl() + r.getUrl()); } map.put("VERIFIED", String.valueOf(verified)); map.put("CODE_REVIEW", String.valueOf(codeReview)); return map; } /** * Finds the GerritTrigger in a project. * @param project the project. * @return the trigger if there is one, null otherwise. */ private GerritTrigger getTrigger(AbstractProject project) { return (GerritTrigger)project.getTrigger(GerritTrigger.class); } /** * Expands all types of parameters in the string and returns the "replaced" string. * Both types means both $ENV_VARS and <PLUGIN_VARS> * @param gerritCommand the command "template" * @param r the build containing the environment vars. * @param taskListener the taskListener * @param parameters the <parameters> from the trigger. * @return the expanded string. */ private String expandParameters(String gerritCommand, AbstractBuild r, TaskListener taskListener, Map parameters) { if (r != null && taskListener != null) { try { gerritCommand = r.getEnvironment(taskListener).expand(gerritCommand); } catch (Exception ex) { logger.error("Failed to expand env vars into gerrit cmd. Gerrit won't be notified!!", ex); return null; } } for (Map.Entry param : parameters.entrySet()) { gerritCommand = gerritCommand.replace("<" + param.getKey() + ">", param.getValue()); } return gerritCommand; } /** * Finds the codereview value for the specified build result on the configured trigger. * @param res the build result. * @param trigger the trigger that might have overridden values. * @return the value. */ protected int getCodeReviewValue(Result res, GerritTrigger trigger) { if (res == Result.SUCCESS) { if (trigger.getGerritBuildSuccessfulCodeReviewValue() != null) { return trigger.getGerritBuildSuccessfulCodeReviewValue(); } else { return config.getGerritBuildSuccessfulCodeReviewValue(); } } else if (res == Result.FAILURE || res == Result.ABORTED) { if (trigger.getGerritBuildFailedCodeReviewValue() != null) { return trigger.getGerritBuildFailedCodeReviewValue(); } else { return config.getGerritBuildFailedCodeReviewValue(); } } else if (res == Result.UNSTABLE) { if (trigger.getGerritBuildUnstableCodeReviewValue() != null) { return trigger.getGerritBuildUnstableCodeReviewValue(); } else { return config.getGerritBuildUnstableCodeReviewValue(); } } else { //As bad as failue, for now if (trigger.getGerritBuildFailedCodeReviewValue() != null) { return trigger.getGerritBuildFailedCodeReviewValue(); } else { return config.getGerritBuildFailedCodeReviewValue(); } } } /** * Finds the verified value for the specified build result on the configured trigger. * @param res the build result. * @param trigger the trigger that might have overridden values. * @return the value. */ protected int getVerifiedValue(Result res, GerritTrigger trigger) { if (res == Result.SUCCESS) { if (trigger.getGerritBuildSuccessfulVerifiedValue() != null) { return trigger.getGerritBuildSuccessfulVerifiedValue(); } else { return config.getGerritBuildSuccessfulVerifiedValue(); } } else if (res == Result.FAILURE || res == Result.ABORTED) { if (trigger.getGerritBuildFailedVerifiedValue() != null) { return trigger.getGerritBuildFailedVerifiedValue(); } else { return config.getGerritBuildFailedVerifiedValue(); } } else if (res == Result.UNSTABLE) { if (trigger.getGerritBuildUnstableVerifiedValue() != null) { return trigger.getGerritBuildUnstableVerifiedValue(); } else { return config.getGerritBuildUnstableVerifiedValue(); } } else { //As bad as failue, for now if (trigger.getGerritBuildFailedVerifiedValue() != null) { return trigger.getGerritBuildFailedVerifiedValue(); } else { return config.getGerritBuildFailedVerifiedValue(); } } } /** * Returns the minimum verified value for the build results in the memory. * @param memoryImprint the memory. * @return the lowest verified value. */ protected int getMinimumVerifiedValue(MemoryImprint memoryImprint) { int verified = Integer.MAX_VALUE; for (Entry entry : memoryImprint.getEntries()) { verified = Math.min(verified, getVerifiedValue( entry.getBuild().getResult(), getTrigger(entry.getProject()))); } return verified; } /** * Returns the minimum code review value for the build results in the memory. * @param memoryImprint the memory * @return the lowest code review value. */ protected int getMinimumCodeReviewValue(MemoryImprint memoryImprint) { int codeReview = Integer.MAX_VALUE; for (Entry entry : memoryImprint.getEntries()) { codeReview = Math.min(codeReview, getCodeReviewValue( entry.getBuild().getResult(), getTrigger(entry.getProject()))); } return codeReview; } /** * Gets the "expanded" build completed command to send to gerrit. * @param memoryImprint the memory with all the information * @param listener the taskListener * @return the command. */ public String getBuildCompletedCommand(MemoryImprint memoryImprint, TaskListener listener) { String command; if (memoryImprint.whereAllBuildsSuccessful()) { command = config.getGerritCmdBuildSuccessful(); } else if (memoryImprint.whereAnyBuildsFailed()) { command = config.getGerritCmdBuildFailed(); } else if (memoryImprint.whereAnyBuildsUnstable()) { command = config.getGerritCmdBuildUnstable(); } else { //Just as bad as failed for now. command = config.getGerritCmdBuildFailed(); } int verified = getMinimumVerifiedValue(memoryImprint); int codeReview = getMinimumCodeReviewValue(memoryImprint); Map parameters = createStandardParameters(null, memoryImprint.getEvent(), codeReview, verified); parameters.put("BUILDS_STATS", createBuildsStats(memoryImprint)); AbstractBuild build = null; Entry[] entries = memoryImprint.getEntries(); if (entries.length > 0 && entries[0].getBuild() != null) { build = entries[0].getBuild(); } return expandParameters(command, build, listener, parameters); } /** * Creates the BUILD_STATS string to send in a message, * it contails the status of every build with it's URL. * @param memoryImprint the memory of all the builds. * @return the string. */ private String createBuildsStats(MemoryImprint memoryImprint) { StringBuilder str = new StringBuilder(""); final String rootUrl = hudson.getRootUrl(); Entry[] entries = memoryImprint.getEntries(); // In Gerrit, all lines before the first empty line is used as the summary. // For the summary all single linefeeds will be removed (only in Gerrit, not sent mails). // Hence, for the multi-builds, we will add a double linefeed before actually listing // the build results. if (entries.length > 0) { str.append("\n"); for (Entry entry : entries) { if (entry.getBuild() != null) { // For some reason, Gerrit wont except command linefeeds with out a space. str.append(" \n"); str.append(entry.getBuild().getResult().toString()).append(": "); str.append(rootUrl).append(entry.getBuild().getUrl()); } } } else { logger.error("I got a request to create build statistics, but no entries where found!"); } return str.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy