<commit_before>// Description:
//   TODO
//
// Dependencies:
//   None
//
// Configuration:
//   None
//
// Commands:
//   hubot status show aliases - List all aliases
//
// Author:
//   christriddle

var Url = require('url'),
    aliases,
    logger;

module.exports = function(robot){
  logger = robot.logger;

  robot.brain.on('loaded', function(){
      aliases = robot.brain.data.deploymentAliases || {};
  });

  robot.respond(/deploy (\S+)$/i, function(msg){
    deploy(msg);
  });

  robot.respond(/deployment show last successful build for (\S+)$/i, function(msg){
    showLastSuccessfulBuild(msg);
  });

  robot.respond(/deployment show last successful deployment$/i, function(msg){
    showLastSuccessfulDeploy(msg);
  });

  robot.respond(/deployment show aliases$/i, function(msg){
    showAliases(msg);
  });

  robot.respond(/deployment set alias (\S+) (\S+) (\S+)$/i, function(msg){
    setAlias(msg, robot);
  });

  robot.respond(/deployment clear alias (\S+)$/i, function(msg){
    clearAlias(msg, robot);
  });

  robot.respond(/deploy all the things/i, function(msg){
    msg.send("I don't see why I should")
  });

};

var deploy = function(msg){


},

showLastSuccessfulBuild = function(msg){
  var app = msg.match[1];
  var alias = aliases[app]; // todo: check if this exists

  if (!alias){
    logger.error("No such application");
    return;
  }

  getBuildsFromBuildType(msg, alias.mainBuildTypeId, function(builds){

        var lastBuild = builds.build[0];
        msg.send("Last build: " + lastBuild.number + " Success:" + lastBuild.status);

        //var lastSuccessfulBuild = builds.build[0];
        //if both same, show build number
        //if different, show both
    });
},

getBuildsFromBuildType = function(msg, buildTypeId, callback){
  var buildsUrl = "http://teamcity/httpAuth/app/rest/buildTypes/id:" + buildTypeId + "/builds";
  logger.info("Getting from: " + buildsUrl);

  msg.http(buildsUrl)
    .headers({Accept: 'application/json', Authorization: 'Basic <KEY>'})
    .get()(function(err, res, body){
        if (err){
          logger.error("Error occured when retrieving builds. " + err);
        }
        else if (res.statusCode >= 300)
        {
          logger.error(res.statusCode + " status code when retrieving builds. Body: " + body);
        }
        else{
          logger.debug(body);
          callback(JSON.parse(body));
        }
    });
},

getBuildInfo = function(buildId){
  var url = "http://teamcity/httpAuth/app/rest/builds/" + buildId;
},

pinBuild = function(buildTypeId){

  var builds = getBuildsFromBuildType(buildTypeId);

  var lastBuild = response.build[0];
  if (lastBuild.status !== "SUCCESS"){
    throw new Error("The last build must be successful");
  }

  var lastBuildDetailed = getBuildInfo(lastBuild.id);
  if (lastBuildDetailed.pinned){
    throw new Error("The last successful build has already been pinned");
  }

  // PUT
  var pinUrl = "http://teamcity/httpAuth/app/rest/builds/" + lastBuildDetailed.id + "/pin";
},

runDeployment = function(){
  var builds = getBuildsFromBuildType(buildTypeId); // Use prod team city

  var deployUrl = "http://http://teamcity-prod.otenv.com//httpAuth/app/rest/buildQueue";
  // POSTP
  //<build>
  //  <buildType id="buildConfID"/>
  //</build>
},

showAliases = function(msg){
  var response = '';
  for(var al in aliases){
    response += al + ':\n';
    for(var s in aliases[al]){
      response += "  " + s + ": " + aliases[al][s] + "\n";
    }
  }
  msg.send(response || "No aliases set");
},


setAlias = function(msg, robot){
    var bits = {
        app: msg.match[1],
        mainBuildTypeId: msg.match[2],
        deployBuildTypeId: msg.match[3]
    };

    // todo: validate build type ids

    if(!aliases[bits.app]){
        aliases[bits.app] = {};
    }

    aliases[bits.app] = { mainBuildTypeId: bits.mainBuildTypeId, deployBuildTypeId: bits.deployBuildTypeId };
    robot.brain.data.deploymentAliases = aliases;

    msg.send('Ok, alias for ' + bits.app + ' was set');
},

clearAlias = function(msg, robot){
    var app = msg.match[1];

    delete aliases[app];
    robot.brain.data.deploymentAliases = aliases;

    msg.send('Ok, alias for ' + app + ' was cleared');
};<commit_msg>Hubot script nearing completion. Need to test trigger step.<commit_after>// Description:
//   Do deployments via hubot
//
// Dependencies:
//   Underscore
//
// Configuration:
//   HUBOT_TEAMCITY_DEV_USERNAME
//   HUBOT_TEAMCITY_DEV_PASSWORD
//   HUBOT_TEAMCITY_DEV_HOSTNAME
//   HUBOT_TEAMCITY_PROD_USERNAME
//   HUBOT_TEAMCITY_PROD_PASSWORD
//   HUBOT_TEAMCITY_PROD_HOSTNAME
//
// Commands:
//   hubot status show aliases - List all aliases
//   hubot status set alias <app alias> <dev build type id> <deploy build type id> - Sets an alias
//   hubot status clear aliases <app alias> - Clears an alias
//   hubot deployment show last successful build for <app alias> - Shows the last successful build
//   hubot deployment show last successful deployment for <app alias> - Shows the last successful deployment
//
// Author:
//   christriddle

var _ = require('underscore'),
    q = require('q'),
    aliases,
    logger,
    devTeamCity = {
        restUrl: "http://" + process.env.HUBOT_TEAMCITY_DEV_HOSTNAME + "/httpAuth/app/rest/",
        user: process.env.HUBOT_TEAMCITY_DEV_USERNAME,
        password: <PASSWORD>DEV_PASSWORD
    },
    prodTeamCity = {
        restUrl: "http://" + process.env.HUBOT_TEAMCITY_PROD_HOSTNAME + "/httpAuth/app/rest/",
        user: process.env.HUBOT_TEAMCITY_PROD_USERNAME,
        password: <PASSWORD>PRO<PASSWORD>,
    };

module.exports = function (robot) {
    logger = robot.logger;

    robot.brain.on('loaded', function () {
        aliases = robot.brain.data.deploymentAliases || {};
    });

    robot.respond(/deploy (\S+)$/i, function (msg) {
        doDeploy(msg);
    });

    robot.respond(/deployment show last successful build for (\S+)$/i, function (msg) {
        showLastSuccessfulBuild(msg);
    });

    robot.respond(/deployment show last successful deployment for (\S+)$/i, function (msg) {
        showLastSuccessfulDeploy(msg);
    });

    robot.respond(/deployment show aliases$/i, function (msg) {
        showAliases(msg);
    });

    robot.respond(/deployment set alias (\S+) (\S+) (\S+)$/i, function (msg) {
        setAlias(msg, robot);
    });

    robot.respond(/deployment clear alias (\S+)$/i, function (msg) {
        clearAlias(msg, robot);
    });

    robot.respond(/deploy all the things/i, function (msg) {
        msg.send("I don't see why I should")
    });

};

var doDeploy = function (msg) {

        var app = msg.match[1];
        var alias = aliases[app];

        if (!alias) {
            logger.error("No such application");
            return;
        }

        getBuilds(msg, alias.mainBuildTypeId, devTeamCity)
            .then(validateLastBuildIsSuccessful)
            .then(function(lastSuccessfulBuildId){
                return getBuildInfo(msg, lastSuccessfulBuildId, devTeamCity);
            })
            .then(function(lastSuccessfulBuild) {
                return pinAndTrigger(msg, lastSuccessfulBuild, alias.deployBuildTypeId, prodTeamCity);
            })
            .catch(function(err){
                msg.send("There was an error. " + err);
            })
            .done(function(){
                msg.send("Pinned and triggered deployment successfully")
            });
    },

    showLastSuccessfulBuild = function (msg) {
        var app = msg.match[1];
        var alias = aliases[app];

        if (!alias) {
            logger.error("No such application");
            return;
        }

        getBuilds(msg, alias.mainBuildTypeId, devTeamCity)
            .then(function (builds) {
                var lastBuild = builds[0];
                msg.send("Last build: " + lastBuild.number + " Status: " + lastBuild.status);

                if (lastBuild.status !== "SUCCESS") {
                    var lastSuccessful = _.find(builds, function (x) { return x.status === "SUCCESS"; });

                    if (lastSuccessful) {
                        msg.send("Last successful build: " + lastSuccessful.number);
                    }
                    else {
                        msg.send("There has been no successful builds for this project");
                    }
                }
            })
            .catch(function(err){
                msg.send("An error occured:" + err);
            });
    },

    showLastSuccessfulDeploy = function(msg){
        var app = msg.match[1];
        var alias = aliases[app];

        if (!alias) {
            logger.error("No such application");
            return;
        }

        getBuilds(msg, alias.deployBuildTypeId, prodTeamCity)
            .then(function(builds){
                var lastSuccessful = _.find(builds, function (x) { return x.status === "SUCCESS"; });

                if (lastSuccessful) {
                    msg.send("Last successful deployment: " + lastSuccessful.number);
                }
                else {
                    msg.send("There has been no successful deployments for this project");
                }
            })
            .catch(function(err){
                msg.send("An error occured:" + err);
            });
    },

    getBuilds = function (msg, buildTypeId, teamCityConfig) {
        var deferred = q.defer();

        var buildsUrl = teamCityConfig.restUrl +  "buildTypes/id:" + buildTypeId + "/builds";
        logger.info("Getting builds from: " + buildsUrl);

        msg.http(buildsUrl)
            .headers({Accept: 'application/json', Authorization: getAuthHeader(teamCityConfig)})
            .get()(function (err, res, body) {
                if (err) {
                    deferred.reject(err);
                }
                else if (res.statusCode >= 300) {
                    deferred.reject(new Error(res.statusCode + " status code when retrieving builds. Body: " + body));
                }
                else {
                    deferred.resolve(JSON.parse(body).build);
                }
            });

        return deferred.promise;
    },

    getBuildInfo = function (msg, buildId, teamCityConfig, callback, errorCallback) {
        var deferred = q.defer();

        var buildUrl = teamCityConfig.restUrl + "builds/" + buildId;
        logger.info("Getting build info from: " + buildUrl);

        msg.http(buildUrl)
            .headers({Accept: 'application/json', Authorization: getAuthHeader(teamCityConfig)})
            .get()(function (err, res, body) {
                if (err) {
                    deferred.reject(deferred);
                }
                else if (res.statusCode >= 300) {
                    deferred.reject(new Error(res.statusCode + " status code when retrieving builds. Body: " + body));
                }
                else {
                    deferred.resolve(JSON.parse(body));
                }
            });

        return deferred.promise;
    },

    validateLastBuildIsSuccessful = function(builds){
        return q.fcall(function() {

            var lastBuild = builds[0];
            if (lastBuild.status !== "SUCCESS") {
                throw new Error("The last build must be successful");
            }
            logger.info("Build ID: " + lastBuild.id);
            return lastBuild.id;
        });
    },

    pinAndTrigger = function(msg, lastSuccessfulBuild, deployBuildTypeId, prodTeamCity){
        if (lastSuccessfulBuild.pinned) {
            msg.send("This app is already pinned");
            return triggerBuild(msg, deployBuildTypeId, prodTeamCity);
        }
        else {
            return pinBuild(msg, lastSuccessfulBuild.id, prodTeamCity)
                .then(function(){
                    return triggerBuild(msg, deployBuildTypeId, prodTeamCity)
                });
        }
    },

    pinBuild = function(msg, buildId, teamCityConfig){
        var deferred = q.defer();

        var pinUrl = devTeamCity.restUrl + "builds/" + buildId + "/pin";
        logger.info("Pinning build by PUT: " + pinUrl);

        msg.http(pinUrl)
            .headers({Accept: 'application/json', Authorization: getAuthHeader(teamCityConfig)})
            .put()(function (err, res, body) {
                if (err) {
                    deferred.reject(err);
                }
                else if (res.statusCode >= 300) {
                    deferred.reject(new Error(res.statusCode + " status code when pinning build. Body: " + body));
                }
                else {
                    deferred.resolve();
                }
            });

        return deferred.promise;
    },

    triggerBuild = function (msg, buildTypeId, teamCityConfig) {
        var deferred = q.defer();

        var buildQueueUrl = teamCityConfig.restUrl + "buildQueue";
        var postData = JSON.stringify({
            build: {
                buildType: {
                    id: buildTypeId
                }
            }
        });
        logger.info("Trigger build on: " + buildQueueUrl + " with POST data: " + postData);

        msg.http(buildQueueUrl)
            .headers({
                Accept: 'application/json',
                "Content-Type": 'application/json',
                Authorization: getAuthHeader(teamCityConfig)
            })
            .post(postData)(function (err, res, body) {
                if (err) {
                    deferred.reject(err);
                }
                else if (res.statusCode >= 300) {
                    deferred.reject(new Error(res.statusCode + " status code when triggering build. Body: " + body));
                }
                else {
                    deferred.resolve();
                }
        });

        return deferred.promise;
    },

    getAuthHeader = function(teamCityConfig){
        return "Basic " + new Buffer(teamCityConfig.user + ":" + teamCityConfig.password).toString("base64");
    },

    showAliases = function (msg) {
        var response = '';
        for (var al in aliases) {
            response += al + ':\n';
            for (var s in aliases[al]) {
                response += "  " + s + ": " + aliases[al][s] + "\n";
            }
        }
        msg.send(response || "No aliases set");
    },

    setAlias = function (msg, robot) {
        var bits = {
            app: msg.match[1],
            mainBuildTypeId: msg.match[2],
            deployBuildTypeId: msg.match[3]
        };

        // todo: validate build type ids

        if (!aliases[bits.app]) {
            aliases[bits.app] = {};
        }

        aliases[bits.app] = { mainBuildTypeId: bits.mainBuildTypeId, deployBuildTypeId: bits.deployBuildTypeId };
        robot.brain.data.deploymentAliases = aliases;

        msg.send('Ok, alias for ' + bits.app + ' was set');
    },

    clearAlias = function (msg, robot) {
        var app = msg.match[1];

        delete aliases[app];
        robot.brain.data.deploymentAliases = aliases;

        msg.send('Ok, alias for ' + app + ' was cleared');
    };
{'fraction_non_alphanumeric': 0.1320403825717322, 'fraction_numerical': 0.0022582359192348566, 'mean_word_length': 2.0077906512185377, 'pattern_counts': {'":': 4, '<': 16, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2454035', 'n_tokens_mistral': 4519, 'n_tokens_neox': 4324, 'n_words': 970}