<commit_before>'use strict';

const options = {
  cors: {
    origin: 'http://localhost:8080',
  }
};
var io = require('socket.io')(1337, options);

var chatServer = (function (io) {
  var connections = [];
  var conversation = [
    // dummy conversation already in progress...
    {user: 'mike', message: 'this is mike here'},
    {user: 'jeff', message: 'hey mike, it\'s jeff'},
    {user: 'mike', message: 'oh cool'},
    {user: 'jeff', message: 'yeah kind of'},
    {user: 'steve', message: 'now im steve i guess'},
    {user: 'earl', message: 'and im earl'},
    {user: 'josef', message: 'roly-poly'},
    {user: 'jose', message: 'really'},
    {user: 'gertie', message: 'weee'},
    {user: 'allison', message: 'boo'},
    {user: 'ellie', message: 'so cool'},
    {user: 'luis', message: 'yo amo'},
    {user: 'roberto', message: 'we will walk the paved path'},
    {user: 'sylvie', message: 'yoiks'},
    {user: 'sylvie', message: 'oh noes'},
    {user: 'sylvie', message: 'c\'mon'},
    {user: 'sylvie', message: 'jsut jake'},
    {user: 'matt', message: 'what\'s doing?'},
    {user: 'matt', message: 'nothing'},
    {user: 'lebron', message: 'what happens now?'}
  ];

  function listUsers() {
    var userList = [];
    // for (var i = 0, len = connections.length; i < len; i++) {
    //   if (connections[i].store.data.nickname) {
    //     userList.push(connections[i].store.data.nickname);
    //   }
    // }
    return userList;
  }

  var server = io;
  server.sockets.on('connection', function (socket) {
    connections.push(socket);
    socket.on('setNickname', function (name) {
      socket.nickname = name;
      socket.emit('initConversation', conversation);
      socket.emit('updateUserList', listUsers());
      socket.broadcast.emit('updateUserList', listUsers());
    });
    socket.on('newMessage', function (data) {
      socket.get('nickname', function (err, name) {
        if (!err) {
          var message = {user: name, message: data.message};
          conversation.push(message);
          /* TODO: do I really need to do this twice? */
          socket.emit('pushMessage', message);
          socket.broadcast.emit('pushMessage', message);
        }
      });
    });
  });

  return server;
}(io));

console.log('Chat is go...');
<commit_msg>Clean up server code<commit_after>const options = {
  cors: {
    origin: 'http://localhost:8080',
  },
};
const io = require('socket.io')(1337, options);

const chatServer = (function (io) {
  const connections = [];
  const conversation = [
    // dummy conversation already in progress...
    { user: 'mike', message: 'this is mike here' },
    { user: 'jeff', message: "hey mike, it's jeff" },
    { user: 'mike', message: 'oh cool' },
    { user: 'jeff', message: 'yeah kind of' },
    { user: 'steve', message: 'now im steve i guess' },
    { user: 'earl', message: 'and im earl' },
    { user: 'josef', message: 'roly-poly' },
    { user: 'jose', message: 'really' },
    { user: 'gertie', message: 'weee' },
    { user: 'allison', message: 'boo' },
    { user: 'ellie', message: 'so cool' },
    { user: 'luis', message: 'yo amo' },
    { user: 'roberto', message: 'we will walk the paved path' },
    { user: 'sylvie', message: 'yoiks' },
    { user: 'sylvie', message: 'oh noes' },
    { user: 'sylvie', message: "c'mon" },
    { user: 'sylvie', message: 'jsut jake' },
    { user: 'matt', message: "what's doing?" },
    { user: 'matt', message: 'nothing' },
    { user: 'lebron', message: 'what happens now?' },
  ];

  function listUsers() {
    const userList = [];
    // for (var i = 0, len = connections.length; i < len; i++) {
    //   if (connections[i].store.data.nickname) {
    //     userList.push(connections[i].store.data.nickname);
    //   }
    // }
    return userList;
  }

  const server = io;
  server.sockets.on('connection', function (socket) {
    connections.push(socket);
    socket.on('setNickname', function (name) {
      socket.nickname = name;
      socket.emit('initConversation', conversation);
      socket.emit('updateUserList', listUsers());
      socket.broadcast.emit('updateUserList', listUsers());
    });
    socket.on('newMessage', function (data) {
      socket.get('nickname', function (err, name) {
        if (!err) {
          const message = { user: name, message: data.message };
          conversation.push(message);
          /* TODO: do I really need to do this twice? */
          socket.emit('pushMessage', message);
          socket.broadcast.emit('pushMessage', message);
        }
      });
    });
  });

  return server;
})(io);

console.log('Chat is go...');
<|endoftext|>


<commit_before>import { moment } from 'meteor/momentjs:moment';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { CronJob } from 'cron';

UltiSite.Tournaments.before.update(function (userId, doc, fieldNames, modifier, options) {
  modifier.$set = modifier.$set || {};
  modifier.$set.lastChange = new Date();
});

UltiSite.Tournaments.before.insert(function (userId, doc) {
  doc.lastChange = new Date();
  doc.participants = [];
});

UltiSite.getTeam = function (id) {
  const tournament = UltiSite.Tournaments.findOne({ 'teams._id': id });
  return tournament && tournament.teams[id];
};

UltiSite.getTournamentsStates = function (userId) {
  const teams = [];
  UltiSite.Tournaments.find({
    date: { $gte: new Date() },
    participants: { $elemMatch: { user: userId, state: { $gt: 50 } } },
  }), { sort: { date: 1 } }.forEach((tournament) => {
    tournament.participants.filter(p => p.user === userId).forEach((part) => {
      const team = _.find(tournament.teams, t => t._id === part.team);
      teams.push({
        url: FlowRouter.url('tournament', { _id: tournament._id }),
        name: tournament.name,
        date: moment(tournament.date).format('DD.MM.'),
        city: tournament.address && tournament.address.city,
        state: UltiSite.textState(part.state),
        comment: part.comment,
        teamName: team.name,
        teamState: team.state,
        sicher: tournament.participants.filter(p => (p.team === part.team) && (p.state > 90)).length,
        wahrscheinlich: tournament.participants.filter(p => (p.team === part.team) && (p.state < 90) && (p.state > 50)).length,
        interessiert: tournament.participants.filter(p => (p.team === part.team) && (p.state < 50) && (p.state > 0)).length,
      });
    });
  });
  return teams;
};

Meteor.methods({
  offlineTournamentCheck(ids) {
    check(ids, [String]);
    const existing = UltiSite.Tournaments.find({ _id: { $in: ids } }).map(t => t._id);
    return _.without(ids, existing);
  },
  myTournamentStates() {
    return UltiSite.getTournamentsStates(this.userId);
  },
  myTournaments() {
    const ids = UltiSite.Tournaments.find({
      date: {
        $gte: moment().toDate(),
      },
      $or: [
        { 'teams.clubTeam': true },
        { 'participants.user': this.userId },
      ],
    }, { fields: { _id: 1 } }).map(function (t) {
      return t._id;
    });
    ids.concat(UltiSite.Tournaments.find({
      tournamentDate: {
        $lte: moment().toDate(),
        $gte: moment().subtract(6, 'month').toDate(),
      },
      'teams.state': 'dabei',
      $or: [
        { 'teams.clubTeam': true },
        { 'participants.user': this.userId },
      ],
    }, {
        limit: 5, fields: { _id: 1 },
      }).map(function (t) {
        return t._id;
      }));
    return ids;
  },
  addTeam(teamData, tournamentId) {
    check(teamData, Object);
    check(tournamentId, String);
    if (!this.userId) { throw new Meteor.Error('not-logged-in', 'Nicht angemeldet'); }
    const userId = this.userId;
    const tourney = UltiSite.Tournaments.findOne(tournamentId);
    if (!tourney) { throw new Meteor.Error('does-not-exist', `Das Turnier ${tournamentId} existiert nicht`); }

    console.log(`Adding Team ${teamData.name} to ${tournamentId}`);
    teamData.tournamentDate = tourney.date;
    teamData.tournamentId = tournamentId;

    // set tournament defaults from type
    if (teamData.teamType.toLowerCase().indexOf('auslosung') > -1) {
      teamData.drawingDate = moment(tourney.date).clone().subtract(4, 'weeks').toDate();
      teamData.deadlineDate = moment(tourney.date).clone().subtract(3, 'weeks').toDate();
    } else if (teamData.teamType.toLowerCase().indexOf('international') > -1) {
      teamData.drawingDate = moment(tourney.date).clone().subtract(12, 'weeks').toDate();
      teamData.deadlineDate = moment(tourney.date).clone().subtract(10, 'weeks').toDate();
    }
    if (teamData.teamType.toLowerCase().indexOf('verein') > -1) {
      teamData.clubTeam = true;
    } else {
      teamData.clubTeam = false;
      teamData.responsible = this.userId;
      teamData.responsibleName = Meteor.users.findOne(this.userId).username;
    }
    teamData._id = Random.id();
    console.log(`Created Team ${teamData._id} `);
    UltiSite.Tournaments.update(tournamentId, {
      $set: { lastChange: new Date() },
      $push: { teams: teamData },
    });
    Meteor.call('addEvent', {
      type: 'tournament',
      _id: tournamentId,
      text: `Neues Team ${teamData.name}`,
    });
    return teamData._id;
  },
  tournamentUpdateInfos(id, infoId, content) {
    check(id, String);
    check(infoId, String);
    check(content, String);
    UltiSite.Tournaments.update({
      _id: id,
      'description._id': infoId,
    }, {
        $set: {
          lastChange: new Date(),
          'description.$.content': content,
        },
      });
  },
  tournamentUpdateReport(id, infoId, content) {
    check(id, String);
    check(infoId, String);
    check(content, String);
    UltiSite.Tournaments.update({
      _id: id,
      'reports._id': infoId,
    }, {
        $set: {
          lastChange: new Date(),
          'reports.$.content': content,
        },
      });
  },
  tournamentAddReport(id, report) {
    check(id, String);
    check(report, Object);
    UltiSite.Tournaments.update({
      _id: id,
    }, {
        $set: {
          lastChange: new Date(),
        },
        $push: {
          reports: {
            $each: [report],
            $position: 0,
          },
        },
      });
  },
  tournamentCoordinates() {
    return UltiSite.Tournaments.find({
      $and: [{
        'address.geocoords': {
          $ne: '',
        },
      }, {
        'address.geocoords': {
          $exists: true,
        },
      }],
      date: {
        $gte: new Date(),
      },
    }, {
        fields: {
          'address.geocoords': 1,
          name: 1,
          date: 1,
        },
      }).fetch();
  },
});

Meteor.startup(function () {
  UltiSite.teamDrawings = function () {
    UltiSite.Tournaments.find({
      date: {
        $gte: moment().startOf('day').toDate(),
      },
      'teams.drawingResult': { $exists: false },
      'teams.drawingDate': {
        $lte: moment().endOf('day').toDate(),
      },
    }).forEach(function (tournament) {
      tournament.teams.forEach((team) => {
        if (team.drawingResult) { return; }
        if (moment(team.drawingDate).isAfter(moment().startOf('day'))) { return; }
        const participants = tournament.participants.filter(p => p.team === team._id);

        const partCount = participants.length;
        let numbers = [];
        const result = {
          date: new Date(),
        };
        for (let i = 1; i <= partCount; i += 1) {
          numbers[i - 1] = i;
        }
        const orderedParticipants = _.sortBy(_.sortBy(participants, 'safeStateDate'), p => 100 - p.state);

        orderedParticipants.forEach((part, idx) => {
          const selection = (Math.random() * numbers.length).toFixed();
          let pos = numbers[selection];
          numbers = _.without(numbers, pos);
          if (idx < (team.maxPlayers / 2)) { pos = 0; }
          if (part.state !== 100) { pos = 1000; }
          UltiSite.Tournaments.update({ _id: tournament._id, 'participants.user': part.user }, {
            $set: { 'participants.$.drawing': pos },
          });
          result[part.user.toCamelCase()] = pos;
        });
        UltiSite.Tournaments.update({ _id: tournament._id, 'teams._id': team._id }, {
          $set: {
            'teams.$.drawingResult': result,
            lastChange: new Date(),
          },
        });
        const drawnParticipants = UltiSite.participantList(team._id).map(p => p.username).join(', ');

        console.log(`finished drawing:${drawnParticipants}`);
        if (team.maxPlayers < partCount * 2) {
          Meteor.call('addEvent', {
            type: 'tournament',
            _id: tournament._id,
            text: `Auslosung bei ${team.name}:${drawnParticipants}`,
          });
        }
      });
    });
  };

  const job = new CronJob('0 17 3 * * *', Meteor.bindEnvironment(UltiSite.teamDrawings), null, false, 'Europe/Berlin');
  job.start();
});
<commit_msg>fixed mails sending<commit_after>import { moment } from 'meteor/momentjs:moment';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { CronJob } from 'cron';

UltiSite.Tournaments.before.update(function (userId, doc, fieldNames, modifier, options) {
  modifier.$set = modifier.$set || {};
  modifier.$set.lastChange = new Date();
});

UltiSite.Tournaments.before.insert(function (userId, doc) {
  doc.lastChange = new Date();
  doc.participants = [];
});

UltiSite.getTeam = function (id) {
  const tournament = UltiSite.Tournaments.findOne({ 'teams._id': id });
  return tournament && tournament.teams[id];
};

UltiSite.getTournamentsStates = function (userId) {
  const teams = [];
  UltiSite.Tournaments.find({
    date: { $gte: new Date() },
    participants: { $elemMatch: { user: userId, state: { $gt: 50 } } },
  }, { sort: { date: 1 } }).forEach((tournament) => {
    tournament.participants.filter(p => p.user === userId).forEach((part) => {
      const team = _.find(tournament.teams, t => t._id === part.team);
      teams.push({
        url: FlowRouter.url('tournament', { _id: tournament._id }),
        name: tournament.name,
        date: moment(tournament.date).format('DD.MM.'),
        city: tournament.address && tournament.address.city,
        state: UltiSite.textState(part.state),
        comment: part.comment,
        teamName: team.name,
        teamState: team.state,
        sicher: tournament.participants.filter(p => (p.team === part.team) && (p.state > 90)).length,
        wahrscheinlich: tournament.participants.filter(p => (p.team === part.team) && (p.state < 90) && (p.state > 50)).length,
        interessiert: tournament.participants.filter(p => (p.team === part.team) && (p.state < 50) && (p.state > 0)).length,
      });
    });
  });
  return teams;
};

Meteor.methods({
  offlineTournamentCheck(ids) {
    check(ids, [String]);
    const existing = UltiSite.Tournaments.find({ _id: { $in: ids } }).map(t => t._id);
    return _.without(ids, existing);
  },
  myTournamentStates() {
    return UltiSite.getTournamentsStates(this.userId);
  },
  myTournaments() {
    const ids = UltiSite.Tournaments.find({
      date: {
        $gte: moment().toDate(),
      },
      $or: [
        { 'teams.clubTeam': true },
        { 'participants.user': this.userId },
      ],
    }, { fields: { _id: 1 } }).map(function (t) {
      return t._id;
    });
    ids.concat(UltiSite.Tournaments.find({
      tournamentDate: {
        $lte: moment().toDate(),
        $gte: moment().subtract(6, 'month').toDate(),
      },
      'teams.state': 'dabei',
      $or: [
        { 'teams.clubTeam': true },
        { 'participants.user': this.userId },
      ],
    }, {
        limit: 5, fields: { _id: 1 },
      }).map(function (t) {
        return t._id;
      }));
    return ids;
  },
  addTeam(teamData, tournamentId) {
    check(teamData, Object);
    check(tournamentId, String);
    if (!this.userId) { throw new Meteor.Error('not-logged-in', 'Nicht angemeldet'); }
    const userId = this.userId;
    const tourney = UltiSite.Tournaments.findOne(tournamentId);
    if (!tourney) { throw new Meteor.Error('does-not-exist', `Das Turnier ${tournamentId} existiert nicht`); }

    console.log(`Adding Team ${teamData.name} to ${tournamentId}`);
    teamData.tournamentDate = tourney.date;
    teamData.tournamentId = tournamentId;

    // set tournament defaults from type
    if (teamData.teamType.toLowerCase().indexOf('auslosung') > -1) {
      teamData.drawingDate = moment(tourney.date).clone().subtract(4, 'weeks').toDate();
      teamData.deadlineDate = moment(tourney.date).clone().subtract(3, 'weeks').toDate();
    } else if (teamData.teamType.toLowerCase().indexOf('international') > -1) {
      teamData.drawingDate = moment(tourney.date).clone().subtract(12, 'weeks').toDate();
      teamData.deadlineDate = moment(tourney.date).clone().subtract(10, 'weeks').toDate();
    }
    if (teamData.teamType.toLowerCase().indexOf('verein') > -1) {
      teamData.clubTeam = true;
    } else {
      teamData.clubTeam = false;
      teamData.responsible = this.userId;
      teamData.responsibleName = Meteor.users.findOne(this.userId).username;
    }
    teamData._id = Random.id();
    console.log(`Created Team ${teamData._id} `);
    UltiSite.Tournaments.update(tournamentId, {
      $set: { lastChange: new Date() },
      $push: { teams: teamData },
    });
    Meteor.call('addEvent', {
      type: 'tournament',
      _id: tournamentId,
      text: `Neues Team ${teamData.name}`,
    });
    return teamData._id;
  },
  tournamentUpdateInfos(id, infoId, content) {
    check(id, String);
    check(infoId, String);
    check(content, String);
    UltiSite.Tournaments.update({
      _id: id,
      'description._id': infoId,
    }, {
        $set: {
          lastChange: new Date(),
          'description.$.content': content,
        },
      });
  },
  tournamentUpdateReport(id, infoId, content) {
    check(id, String);
    check(infoId, String);
    check(content, String);
    UltiSite.Tournaments.update({
      _id: id,
      'reports._id': infoId,
    }, {
        $set: {
          lastChange: new Date(),
          'reports.$.content': content,
        },
      });
  },
  tournamentAddReport(id, report) {
    check(id, String);
    check(report, Object);
    UltiSite.Tournaments.update({
      _id: id,
    }, {
        $set: {
          lastChange: new Date(),
        },
        $push: {
          reports: {
            $each: [report],
            $position: 0,
          },
        },
      });
  },
  tournamentCoordinates() {
    return UltiSite.Tournaments.find({
      $and: [{
        'address.geocoords': {
          $ne: '',
        },
      }, {
        'address.geocoords': {
          $exists: true,
        },
      }],
      date: {
        $gte: new Date(),
      },
    }, {
        fields: {
          'address.geocoords': 1,
          name: 1,
          date: 1,
        },
      }).fetch();
  },
});

Meteor.startup(function () {
  UltiSite.teamDrawings = function () {
    UltiSite.Tournaments.find({
      date: {
        $gte: moment().startOf('day').toDate(),
      },
      'teams.drawingResult': { $exists: false },
      'teams.drawingDate': {
        $lte: moment().endOf('day').toDate(),
      },
    }).forEach(function (tournament) {
      tournament.teams.forEach((team) => {
        if (team.drawingResult) { return; }
        if (moment(team.drawingDate).isAfter(moment().startOf('day'))) { return; }
        const participants = tournament.participants.filter(p => p.team === team._id);

        const partCount = participants.length;
        let numbers = [];
        const result = {
          date: new Date(),
        };
        for (let i = 1; i <= partCount; i += 1) {
          numbers[i - 1] = i;
        }
        const orderedParticipants = _.sortBy(_.sortBy(participants, 'safeStateDate'), p => 100 - p.state);

        orderedParticipants.forEach((part, idx) => {
          const selection = (Math.random() * numbers.length).toFixed();
          let pos = numbers[selection];
          numbers = _.without(numbers, pos);
          if (idx < (team.maxPlayers / 2)) { pos = 0; }
          if (part.state !== 100) { pos = 1000; }
          UltiSite.Tournaments.update({ _id: tournament._id, 'participants.user': part.user }, {
            $set: { 'participants.$.drawing': pos },
          });
          result[part.user.toCamelCase()] = pos;
        });
        UltiSite.Tournaments.update({ _id: tournament._id, 'teams._id': team._id }, {
          $set: {
            'teams.$.drawingResult': result,
            lastChange: new Date(),
          },
        });
        const drawnParticipants = UltiSite.participantList(team._id).map(p => p.username).join(', ');

        console.log(`finished drawing:${drawnParticipants}`);
        if (team.maxPlayers < partCount * 2) {
          Meteor.call('addEvent', {
            type: 'tournament',
            _id: tournament._id,
            text: `Auslosung bei ${team.name}:${drawnParticipants}`,
          });
        }
      });
    });
  };

  const job = new CronJob('0 17 3 * * *', Meteor.bindEnvironment(UltiSite.teamDrawings), null, false, 'Europe/Berlin');
  job.start();
});
00) { pos = 1000; }
          UltiSite.Tournaments.update({ _id: tournament._id, 'participants.user': part.user }, {
            $set: { 'participants.$.drawing': pos },
          });
          result[part.user.toCamelCase()] = pos;
        });
        UltiSite.Tournaments.update({ _id: tournament._id, 'teams._id': team._id }, {
          $set: {
            'teams.$.drawingResult': result,
            lastChange: new Date(),
          },
        });
        const drawnParticipants = UltiSite.participantList(team._id).map(p => p.username).join(', ');

        console.log(`finished drawing:${drawnParticipants}`);
        if (team.maxPlayers < partCount * 2) {
          Meteor.call('addEvent', {
            type: 'tournament',
            _id: tournament._id,
            text: `Auslosung bei ${team.name}:${drawnParticipants}`,
          });
        }
      });
    });
  };

  const job = new CronJob('0 17 3 * * *', Meteor.bindEnvironment(UltiSite.teamDrawings), null, false, 'Europe/Berlin'<|endoftext|>


<commit_before><commit_msg><commit_after><|endoftext|>


<commit_before>/**
 * Copyright 2015 Kitware 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.
 */

/**
 * Define tasks related to loading, configuring, and building plugins.
 */
module.exports = function (grunt) {
    var _ = require('underscore');
    var fs = require('fs');
    var path = require('path');
    var child_process = require('child_process'); // eslint-disable-line camelcase

    var ExtractTextPlugin = require('extract-text-webpack-plugin');
    var webpack = require('webpack');
    var paths = require('./webpack.paths.js');
    var webpackPlugins = require('./webpack.plugins.js');

    var configurePlugins = grunt.option('configure-plugins');
    var plugins = grunt.option('plugins');

    if (grunt.option('all-plugins')) {
        grunt.fail.warn(
            'The --all-plugins option no longer works, use `girder-install web --all-plugins` instead.');
    }

    if (_.isString(plugins) && plugins) {
        plugins = plugins.split(',');
    } else {
        plugins = [];
    }

    if (_.isString(configurePlugins) && configurePlugins) {
        configurePlugins = configurePlugins.split(',');
    } else {
        configurePlugins = [];
    }

    if (!plugins.length && !configurePlugins.length) {
        return;
    }

    require('colors');

    grunt.config.merge({
        default: {
            plugin: {}
        }
    });

    /**
     * Adds configuration for plugin related multitasks:
     *
     *   * copy:plugin-<plugin name>
     *      Copies any other files that are served statically
     */
    var addMultitasks = function (plugin) {
        var pluginTarget = 'plugin-' + plugin,
            pluginPath = path.resolve(grunt.config.get('pluginDir'), plugin),
            staticPath = path.resolve(grunt.config.get('staticDir'), 'built', 'plugins', plugin),
            cfg = {
                copy: {},
                default: {},
                plugin: {}
            };

        // create the plugin's build directory under the web-root
        grunt.file.mkdir(staticPath);

        // TODO: this could be moved to Webpack using kevlened/copy-webpack-plugin
        cfg.copy[pluginTarget] = {
            files: [{
                expand: true,
                cwd: pluginPath + '/web_client',
                src: ['extra/**'],
                dest: staticPath
            }]
        };

        // the task 'plugin:<plugin name>' is a task alias to run all
        // of the main tasks defined above and possibly more if
        // the plugin itself appends tasks to this array
        cfg.plugin[plugin] = {
            tasks: [
                'copy:' + pluginTarget
            ]
        };

        grunt.config.merge(cfg);
    };

    var getPluginLocalNodePath = function (plugin) {
        return path.resolve(path.join('node_modules', `girder_plugin_${plugin}`));
    };

    var configurePluginForBuilding = function (dir, buildPlugin) {
        var plugin = path.basename(dir);
        var json = path.resolve(dir, 'plugin.json');
        var yml = path.resolve(dir, 'plugin.yml');
        var config = {};
        var cfgFile = 'no config file';

        if (!fs.statSync(dir).isDirectory()) {
            grunt.fail.warn('Plugin directory not found: ' + dir);
            return;
        }

        if (fs.existsSync(json)) {
            config = grunt.file.readYAML(json);
            cfgFile = 'plugin.json';
        } else if (fs.existsSync(yml)) {
            cfgFile = 'plugin.yml';
            config = grunt.file.readYAML(yml);
        }

        var buildText = `build=${buildPlugin ? 'ON'.green : 'OFF'.red}`;
        grunt.log.writeln(`Configuring plugin ${plugin.magenta} (${cfgFile}, ${buildText})`);

        var doAutoBuild = (
            !_.isObject(config.grunt) ||
            _.isUndefined(config.grunt.autobuild) ||
            _.isNull(config.grunt.autobuild) ||
            !!config.grunt.autobuild
        );

        if (doAutoBuild) {
            // merge in configuration for the main plugin build tasks
            addMultitasks(plugin);
        }

        // Find the plugin's webpack helper file; default to the identity
        // function.
        var webpackHelperFile = path.resolve(dir, config.webpack && config.webpack.configHelper || 'webpack.helper.js');
        var webpackHelper;
        if (fs.existsSync(webpackHelperFile)) {
            grunt.log.writeln(`  >> Loading webpack helper from ${webpackHelperFile}`);
            webpackHelper = require(webpackHelperFile);
        } else {
            grunt.verbose.writeln('  >> No webpack helper file found.');
            webpackHelper = x => x;
        }

        // Configure the output file; default to 'plugin.min.js' - Girder loads
        // files named "plugin.min.js" into the Girder web client at runtime, so
        // the user can control whether this is a "Girder client extension" or
        // just a standalone web client.
        var output = config.webpack && config.webpack.output || 'plugin';
        var deps = config.dependencies || [];
        var pluginNodeDir = path.join(getPluginLocalNodePath(plugin), 'node_modules');

        // Add webpack target and name resolution for this plugin if
        // web_client/main.js (or user-specified name) exists.
        var webClient = path.resolve(dir + '/web_client');
        var mains = config.webpack && config.webpack.main || {};

        if (_.isString(mains)) {
            // If main was specified as a string, convert to an object
            mains = {
                [output]: mains
            };
        } else if (_.isEmpty(mains)) {
            // By default, use web_client/main.js if it exists.
            var mainJs = path.resolve(webClient, 'main.js');

            if (fs.existsSync(mainJs)) {
                mains = {
                    [output]: mainJs
                };
            }
        }

        _.each(mains, (main, output) => {
            if (!path.isAbsolute(main)) {
                main = path.resolve(dir, main);
            }
            if (!fs.existsSync(main)) {
                throw new Error(`Entry point file ${main} not found.`);
            }

            var helperConfig = {
                plugin,
                output,
                main,
                pluginEntry: `plugins/${plugin}/${output}`,
                pluginDir: dir,
                nodeDir: pluginNodeDir
            };

            var configOpts = {
                webpack: {
                    options: {
                        // Add an import alias to the global config for this plugin
                        resolve: {
                            alias: {
                                [`girder_plugins/${plugin}/node`]: pluginNodeDir,
                                [`girder_plugins/${plugin}`]: webClient
                            },
                            modules: [
                                path.resolve(process.cwd(), 'node_modules'),
                                pluginNodeDir
                            ]
                        },
                        resolveLoader: {
                            modules: [
                                path.resolve(process.cwd(), 'node_modules'),
                                pluginNodeDir
                            ]
                        }
                    }
                }
            };

            if (buildPlugin) {
                configOpts.webpack[`${output}_${plugin}`] = {
                    entry: {
                        [helperConfig.pluginEntry]: [main]
                    },
                    output: {
                        path: path.join(paths.web_built, 'plugins', plugin),
                        filename: `${output}.min.js`,
                        library: `girder_plugin_${plugin}`
                    },
                    resolve: {
                        modules: [
                            path.resolve(dir, 'node_modules')
                        ]
                    },
                    resolveLoader: {
                        modules: [
                            path.resolve(dir, 'node_modules')
                        ]
                    },
                    plugins: [
                        // DllPlugin causes the plugin bundle to build a manifest so that
                        // downstream bundles can share its modules at runtime rather
                        // than copying them in statically.
                        new webpack.DllPlugin({
                            path: path.join(paths.web_built, 'plugins', plugin, `${output}-manifest.json`),
                            name: `girder_plugin_${plugin}`
                        }),
                        // DllBootstrapPlugin allows the same plugin bundle to also
                        // execute an entry point at load time instead of just exposing symbols
                        // as a library.
                        new webpackPlugins.DllBootstrapPlugin({
                            [helperConfig.pluginEntry]: main
                        }),
                        // This plugin allows this bundle to dynamically link against girder's
                        // core library bundle.
                        new webpack.DllReferencePlugin({
                            context: '.',
                            manifest: path.join(paths.web_built, 'girder_lib-manifest.json')
                        }),
                        // This plugin pulls the CSS out of the bundle and into a separate file.
                        new ExtractTextPlugin({
                            filename: `${output}.min.css`,
                            allChunks: true
                        })
                    ].concat(_.map(deps, dep => {
                        // This dynamically links the current plugin against its
                        // dependencies' bundles so they can share code.
                        return new webpack.DllReferencePlugin({
                            context: '.',
                            manifest: path.join(paths.web_built, 'plugins', dep, 'plugin-manifest.json')
                        });
                    }))
                };
                configOpts.default = {
                    [`webpack:${output}_${plugin}`]: {
                        dependencies: ['build'] // plugin builds must run after core build
                    }
                };
            }
            grunt.config.merge(configOpts);

            // If the plugin config has no webpack section, no defaultLoaders
            // property in the webpack section, or the defaultLoaders is
            // explicitly set to anything besides false, then augment the
            // webpack loader configurations with the plugin source directory.
            if (!config.webpack || config.webpack.defaultLoaders === undefined || config.webpack.defaultLoaders !== false) {
                var numLoaders = grunt.config.get('webpack.options.module.loaders').length;
                for (var i = 0; i < numLoaders; i++) {
                    var selector = 'webpack.options.module.loaders.' + i + '.include';
                    var loaders = grunt.config.get(selector) || [];
                    var pluginPath = path.resolve(dir);
                    var realPath = fs.realpathSync(dir);
                    var loaderIncludes = [pluginPath];

                    // We add the plugin path to the include list for the loaders, and also
                    // add the realpath (i.e. following symlinks) to workaround an issue where
                    // webpack doesn't resolve symlinked include directories correctly.
                    if (realPath !== pluginPath) {
                        loaderIncludes.push(realPath);
                    }

                    grunt.config.set(selector, loaders.concat(loaderIncludes));
                }
            }

            var newConfig = webpackHelper(grunt.config.getRaw('webpack.options'), helperConfig);
            grunt.config.set('webpack.options', newConfig);
        });

        grunt.registerTask('npm-install', 'Install plugin NPM dependencies', function (plugin, localNodeModules) {
            var args, child;
            if (localNodeModules === 'install') {
                args = ['--color=always', 'install'];

                child = child_process.spawnSync('npm', args, {
                    cwd: path.resolve(dir),
                    stdio: 'inherit'
                });

                return child.status === 0;
            }

            // Start building the list of arguments to the NPM executable.
            //
            // We want color output embedded in the Grunt output.
            args = ['--color=always'];

            // If the plugin requested to install the dependencies in its own
            // dedicated directory, set the prefix option.
            if (localNodeModules === 'true') {
                args = args.concat(['--prefix', getPluginLocalNodePath(plugin)]);
            }

            // Get the list of the packages to install and append them to the
            // args object.
            var modules = Array.prototype.slice.call(arguments, 2);
            args = args.concat(['install'], modules);

            // Launch the child process.
            child = child_process.spawnSync('npm', args, {
                stdio: 'inherit'
            });

            return child.status === 0;
        });

        function addDependencies(deps, localNodeModules) {
            if (arguments.length === 0) {
                grunt.config.set('default.npm-install:' + plugin + ':install', {});
                return;
            }

            // install any additional npm packages during init
            var npm = (
                _(deps || {})
                    .map(function (version, dep) {
                        return [
                            dep.replace(':', '\\:'),
                            version.replace(':', '\\:')
                        ].join('@');
                    })
            );

            if (npm.length) {
                grunt.config.set('default.npm-install:' + plugin + ':' + !!localNodeModules + ':' + grunt.config.escape(npm.join(':')), {});
            }
        }

        if (config.npm && config.npm.install) {
            grunt.log.writeln('  >> Installing NPM dependencies in-place from: ' + path.resolve(dir, 'package.json'));
            addDependencies();
        } else if (config.npm) {
            var modules = {};

            // If the config contains a "file" section, load NPM dependencies
            // from it.
            if (config.npm.file) {
                var npmFile = require(path.resolve(dir, config.npm.file));
                var fields = config.npm.fields || ['devDependencies', 'dependencies', 'optionalDependencies'];

                grunt.log.writeln('  >> Loading NPM dependencies from: ' + config.npm.file);
                grunt.log.writeln('  >> Using fields: ' + fields.join(', '));

                fields.forEach(function (field) {
                    _.each(npmFile[field] || {}, function (version, dep) {
                        modules[dep] = version;
                    });
                });
            }

            // Additionally add any extra dependencies found in the
            // "dependencies" property.
            if (config.npm.dependencies) {
                if (config.npm.file) {
                    grunt.log.writeln('  >> Loading additional NPM dependencies');
                } else {
                    grunt.log.writeln('  >> Loading NPM dependencies');
                }

                _.each(config.npm.dependencies, function (version, dep) {
                    modules[dep] = version;
                });
            }

            if (config.npm.localNodeModules) {
                grunt.log.writeln(`  >> Installing NPM dependencies to dedicated directory: node_modules_${plugin}`);
            } else {
                grunt.verbose.writeln('  >> Installing NPM dependencies to Girder node_modules directory');
            }

            // Invoke the npm installation task.
            addDependencies(modules, config.npm.localNodeModules);
        }

        if (config.grunt) {
            grunt.log.writeln((
                'Configuring plugin: ' + plugin + ' (custom Gruntfile)'
            ).bold);

            addDependencies(config.grunt.dependencies);

            // load the plugin's gruntfile
            try {
                require(
                    path.resolve(dir, config.grunt.file || 'Gruntfile.js')
                )(grunt);
            } catch (e) {
                // the error can be safely ignored when doing `grunt init`
                // otherwise a default task will most likely fail later on
                // write out a warning to help the developers debug errors
                grunt.log.writeln((
                    'Failed to load ' + plugin + '/' + (config.grunt.file || 'Gruntfile.js') + ':'
                ).yellow);
                grunt.log.writeln('>>> ' + e.toString().split('\n').join('\n>>> ').yellow);
            }

            // add default targets
            _(config.grunt.defaultTargets || []).each(function (target) {
                grunt.config.set('default.' + target, {});
            });
        }
    };

    // Configure the plugins that were requested via --configure-plugins in order
    configurePlugins.forEach(function (name) {
        configurePluginForBuilding(path.resolve(grunt.config.get('pluginDir'), name), false);
    });
    // Build the plugins that were requested via --plugins in order
    plugins.forEach(function (name) {
        configurePluginForBuilding(path.resolve(grunt.config.get('pluginDir'), name), true);
    });

    /**
     * Register a "meta" task that will configure and run other tasks
     * to build a plugin. Keys in the config for this task should be the
     * directory of the plugin within the base plugins path.
     */
    grunt.registerMultiTask('plugin', 'Build and configure plugins', function () {
        var plugin = this.target,
            tasks = 'plugin.' + plugin + '.tasks';

        this.requiresConfig('pluginDir', tasks);

        // queue the build tasks
        grunt.config.get(tasks).forEach(function (task) {
            grunt.task.run(task);
        });
    });
};
<commit_msg>Use npm install --no-save for npm 5<commit_after>/**
 * Copyright 2015 Kitware 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.
 */

/**
 * Define tasks related to loading, configuring, and building plugins.
 */
module.exports = function (grunt) {
    var _ = require('underscore');
    var fs = require('fs');
    var path = require('path');
    var child_process = require('child_process'); // eslint-disable-line camelcase

    var ExtractTextPlugin = require('extract-text-webpack-plugin');
    var webpack = require('webpack');
    var paths = require('./webpack.paths.js');
    var webpackPlugins = require('./webpack.plugins.js');

    var configurePlugins = grunt.option('configure-plugins');
    var plugins = grunt.option('plugins');

    if (grunt.option('all-plugins')) {
        grunt.fail.warn(
            'The --all-plugins option no longer works, use `girder-install web --all-plugins` instead.');
    }

    if (_.isString(plugins) && plugins) {
        plugins = plugins.split(',');
    } else {
        plugins = [];
    }

    if (_.isString(configurePlugins) && configurePlugins) {
        configurePlugins = configurePlugins.split(',');
    } else {
        configurePlugins = [];
    }

    if (!plugins.length && !configurePlugins.length) {
        return;
    }

    require('colors');

    grunt.config.merge({
        default: {
            plugin: {}
        }
    });

    /**
     * Adds configuration for plugin related multitasks:
     *
     *   * copy:plugin-<plugin name>
     *      Copies any other files that are served statically
     */
    var addMultitasks = function (plugin) {
        var pluginTarget = 'plugin-' + plugin,
            pluginPath = path.resolve(grunt.config.get('pluginDir'), plugin),
            staticPath = path.resolve(grunt.config.get('staticDir'), 'built', 'plugins', plugin),
            cfg = {
                copy: {},
                default: {},
                plugin: {}
            };

        // create the plugin's build directory under the web-root
        grunt.file.mkdir(staticPath);

        // TODO: this could be moved to Webpack using kevlened/copy-webpack-plugin
        cfg.copy[pluginTarget] = {
            files: [{
                expand: true,
                cwd: pluginPath + '/web_client',
                src: ['extra/**'],
                dest: staticPath
            }]
        };

        // the task 'plugin:<plugin name>' is a task alias to run all
        // of the main tasks defined above and possibly more if
        // the plugin itself appends tasks to this array
        cfg.plugin[plugin] = {
            tasks: [
                'copy:' + pluginTarget
            ]
        };

        grunt.config.merge(cfg);
    };

    var getPluginLocalNodePath = function (plugin) {
        return path.resolve(path.join('node_modules', `girder_plugin_${plugin}`));
    };

    var configurePluginForBuilding = function (dir, buildPlugin) {
        var plugin = path.basename(dir);
        var json = path.resolve(dir, 'plugin.json');
        var yml = path.resolve(dir, 'plugin.yml');
        var config = {};
        var cfgFile = 'no config file';

        if (!fs.statSync(dir).isDirectory()) {
            grunt.fail.warn('Plugin directory not found: ' + dir);
            return;
        }

        if (fs.existsSync(json)) {
            config = grunt.file.readYAML(json);
            cfgFile = 'plugin.json';
        } else if (fs.existsSync(yml)) {
            cfgFile = 'plugin.yml';
            config = grunt.file.readYAML(yml);
        }

        var buildText = `build=${buildPlugin ? 'ON'.green : 'OFF'.red}`;
        grunt.log.writeln(`Configuring plugin ${plugin.magenta} (${cfgFile}, ${buildText})`);

        var doAutoBuild = (
            !_.isObject(config.grunt) ||
            _.isUndefined(config.grunt.autobuild) ||
            _.isNull(config.grunt.autobuild) ||
            !!config.grunt.autobuild
        );

        if (doAutoBuild) {
            // merge in configuration for the main plugin build tasks
            addMultitasks(plugin);
        }

        // Find the plugin's webpack helper file; default to the identity
        // function.
        var webpackHelperFile = path.resolve(dir, config.webpack && config.webpack.configHelper || 'webpack.helper.js');
        var webpackHelper;
        if (fs.existsSync(webpackHelperFile)) {
            grunt.log.writeln(`  >> Loading webpack helper from ${webpackHelperFile}`);
            webpackHelper = require(webpackHelperFile);
        } else {
            grunt.verbose.writeln('  >> No webpack helper file found.');
            webpackHelper = x => x;
        }

        // Configure the output file; default to 'plugin.min.js' - Girder loads
        // files named "plugin.min.js" into the Girder web client at runtime, so
        // the user can control whether this is a "Girder client extension" or
        // just a standalone web client.
        var output = config.webpack && config.webpack.output || 'plugin';
        var deps = config.dependencies || [];
        var pluginNodeDir = path.join(getPluginLocalNodePath(plugin), 'node_modules');

        // Add webpack target and name resolution for this plugin if
        // web_client/main.js (or user-specified name) exists.
        var webClient = path.resolve(dir + '/web_client');
        var mains = config.webpack && config.webpack.main || {};

        if (_.isString(mains)) {
            // If main was specified as a string, convert to an object
            mains = {
                [output]: mains
            };
        } else if (_.isEmpty(mains)) {
            // By default, use web_client/main.js if it exists.
            var mainJs = path.resolve(webClient, 'main.js');

            if (fs.existsSync(mainJs)) {
                mains = {
                    [output]: mainJs
                };
            }
        }

        _.each(mains, (main, output) => {
            if (!path.isAbsolute(main)) {
                main = path.resolve(dir, main);
            }
            if (!fs.existsSync(main)) {
                throw new Error(`Entry point file ${main} not found.`);
            }

            var helperConfig = {
                plugin,
                output,
                main,
                pluginEntry: `plugins/${plugin}/${output}`,
                pluginDir: dir,
                nodeDir: pluginNodeDir
            };

            var configOpts = {
                webpack: {
                    options: {
                        // Add an import alias to the global config for this plugin
                        resolve: {
                            alias: {
                                [`girder_plugins/${plugin}/node`]: pluginNodeDir,
                                [`girder_plugins/${plugin}`]: webClient
                            },
                            modules: [
                                path.resolve(process.cwd(), 'node_modules'),
                                pluginNodeDir
                            ]
                        },
                        resolveLoader: {
                            modules: [
                                path.resolve(process.cwd(), 'node_modules'),
                                pluginNodeDir
                            ]
                        }
                    }
                }
            };

            if (buildPlugin) {
                configOpts.webpack[`${output}_${plugin}`] = {
                    entry: {
                        [helperConfig.pluginEntry]: [main]
                    },
                    output: {
                        path: path.join(paths.web_built, 'plugins', plugin),
                        filename: `${output}.min.js`,
                        library: `girder_plugin_${plugin}`
                    },
                    resolve: {
                        modules: [
                            path.resolve(dir, 'node_modules')
                        ]
                    },
                    resolveLoader: {
                        modules: [
                            path.resolve(dir, 'node_modules')
                        ]
                    },
                    plugins: [
                        // DllPlugin causes the plugin bundle to build a manifest so that
                        // downstream bundles can share its modules at runtime rather
                        // than copying them in statically.
                        new webpack.DllPlugin({
                            path: path.join(paths.web_built, 'plugins', plugin, `${output}-manifest.json`),
                            name: `girder_plugin_${plugin}`
                        }),
                        // DllBootstrapPlugin allows the same plugin bundle to also
                        // execute an entry point at load time instead of just exposing symbols
                        // as a library.
                        new webpackPlugins.DllBootstrapPlugin({
                            [helperConfig.pluginEntry]: main
                        }),
                        // This plugin allows this bundle to dynamically link against girder's
                        // core library bundle.
                        new webpack.DllReferencePlugin({
                            context: '.',
                            manifest: path.join(paths.web_built, 'girder_lib-manifest.json')
                        }),
                        // This plugin pulls the CSS out of the bundle and into a separate file.
                        new ExtractTextPlugin({
                            filename: `${output}.min.css`,
                            allChunks: true
                        })
                    ].concat(_.map(deps, dep => {
                        // This dynamically links the current plugin against its
                        // dependencies' bundles so they can share code.
                        return new webpack.DllReferencePlugin({
                            context: '.',
                            manifest: path.join(paths.web_built, 'plugins', dep, 'plugin-manifest.json')
                        });
                    }))
                };
                configOpts.default = {
                    [`webpack:${output}_${plugin}`]: {
                        dependencies: ['build'] // plugin builds must run after core build
                    }
                };
            }
            grunt.config.merge(configOpts);

            // If the plugin config has no webpack section, no defaultLoaders
            // property in the webpack section, or the defaultLoaders is
            // explicitly set to anything besides false, then augment the
            // webpack loader configurations with the plugin source directory.
            if (!config.webpack || config.webpack.defaultLoaders === undefined || config.webpack.defaultLoaders !== false) {
                var numLoaders = grunt.config.get('webpack.options.module.loaders').length;
                for (var i = 0; i < numLoaders; i++) {
                    var selector = 'webpack.options.module.loaders.' + i + '.include';
                    var loaders = grunt.config.get(selector) || [];
                    var pluginPath = path.resolve(dir);
                    var realPath = fs.realpathSync(dir);
                    var loaderIncludes = [pluginPath];

                    // We add the plugin path to the include list for the loaders, and also
                    // add the realpath (i.e. following symlinks) to workaround an issue where
                    // webpack doesn't resolve symlinked include directories correctly.
                    if (realPath !== pluginPath) {
                        loaderIncludes.push(realPath);
                    }

                    grunt.config.set(selector, loaders.concat(loaderIncludes));
                }
            }

            var newConfig = webpackHelper(grunt.config.getRaw('webpack.options'), helperConfig);
            grunt.config.set('webpack.options', newConfig);
        });

        grunt.registerTask('npm-install', 'Install plugin NPM dependencies', function (plugin, localNodeModules) {
            var args, child;
            if (localNodeModules === 'install') {
                args = ['--color=always', 'install'];

                child = child_process.spawnSync('npm', args, {
                    cwd: path.resolve(dir),
                    stdio: 'inherit'
                });

                return child.status === 0;
            }

            // Start building the list of arguments to the NPM executable.
            //
            // We want color output embedded in the Grunt output.
            args = ['--color=always'];

            // If the plugin requested to install the dependencies in its own
            // dedicated directory, set the prefix option.
            if (localNodeModules === 'true') {
                args = args.concat(['--prefix', getPluginLocalNodePath(plugin)]);
            }

            // Get the list of the packages to install and append them to the
            // args object.
            var modules = Array.prototype.slice.call(arguments, 2);

            // npm@5 saves dependencies to package.json by default, add
            // the --no-save flag to disable this behavior
            args = args.concat(['install', '--no-save'], modules);

            // Launch the child process.
            child = child_process.spawnSync('npm', args, {
                stdio: 'inherit'
            });

            return child.status === 0;
        });

        function addDependencies(deps, localNodeModules) {
            if (arguments.length === 0) {
                grunt.config.set('default.npm-install:' + plugin + ':install', {});
                return;
            }

            // install any additional npm packages during init
            var npm = (
                _(deps || {})
                    .map(function (version, dep) {
                        return [
                            dep.replace(':', '\\:'),
                            version.replace(':', '\\:')
                        ].join('@');
                    })
            );

            if (npm.length) {
                grunt.config.set('default.npm-install:' + plugin + ':' + !!localNodeModules + ':' + grunt.config.escape(npm.join(':')), {});
            }
        }

        if (config.npm && config.npm.install) {
            grunt.log.writeln('  >> Installing NPM dependencies in-place from: ' + path.resolve(dir, 'package.json'));
            addDependencies();
        } else if (config.npm) {
            var modules = {};

            // If the config contains a "file" section, load NPM dependencies
            // from it.
            if (config.npm.file) {
                var npmFile = require(path.resolve(dir, config.npm.file));
                var fields = config.npm.fields || ['devDependencies', 'dependencies', 'optionalDependencies'];

                grunt.log.writeln('  >> Loading NPM dependencies from: ' + config.npm.file);
                grunt.log.writeln('  >> Using fields: ' + fields.join(', '));

                fields.forEach(function (field) {
                    _.each(npmFile[field] || {}, function (version, dep) {
                        modules[dep] = version;
                    });
                });
            }

            // Additionally add any extra dependencies found in the
            // "dependencies" property.
            if (config.npm.dependencies) {
                if (config.npm.file) {
                    grunt.log.writeln('  >> Loading additional NPM dependencies');
                } else {
                    grunt.log.writeln('  >> Loading NPM dependencies');
                }

                _.each(config.npm.dependencies, function (version, dep) {
                    modules[dep] = version;
                });
            }

            if (config.npm.localNodeModules) {
                grunt.log.writeln(`  >> Installing NPM dependencies to dedicated directory: node_modules_${plugin}`);
            } else {
                grunt.verbose.writeln('  >> Installing NPM dependencies to Girder node_modules directory');
            }

            // Invoke the npm installation task.
            addDependencies(modules, config.npm.localNodeModules);
        }

        if (config.grunt) {
            grunt.log.writeln((
                'Configuring plugin: ' + plugin + ' (custom Gruntfile)'
            ).bold);

            addDependencies(config.grunt.dependencies);

            // load the plugin's gruntfile
            try {
                require(
                    path.resolve(dir, config.grunt.file || 'Gruntfile.js')
                )(grunt);
            } catch (e) {
                // the error can be safely ignored when doing `grunt init`
                // otherwise a default task will most likely fail later on
                // write out a warning to help the developers debug errors
                grunt.log.writeln((
                    'Failed to load ' + plugin + '/' + (config.grunt.file || 'Gruntfile.js') + ':'
                ).yellow);
                grunt.log.writeln('>>> ' + e.toString().split('\n').join('\n>>> ').yellow);
            }

            // add default targets
            _(config.grunt.defaultTargets || []).each(function (target) {
                grunt.config.set('default.' + target, {});
            });
        }
    };

    // Configure the plugins that were requested via --configure-plugins in order
    configurePlugins.forEach(function (name) {
        configurePluginForBuilding(path.resolve(grunt.config.get('pluginDir'), name), false);
    });
    // Build the plugins that were requested via --plugins in order
    plugins.forEach(function (name) {
        configurePluginForBuilding(path.resolve(grunt.config.get('pluginDir'), name), true);
    });

    /**
     * Register a "meta" task that will configure and run other tasks
     * to build a plugin. Keys in the config for this task should be the
     * directory of the plugin within the base plugins path.
     */
    grunt.registerMultiTask('plugin', 'Build and configure plugins', function () {
        var plugin = this.target,
            tasks = 'plugin.' + plugin + '.tasks';

        this.requiresConfig('pluginDir', tasks);

        // queue the build tasks
        grunt.config.get(tasks).forEach(function (task) {
            grunt.task.run(task);
        });
    });
};
<|endoftext|>


<commit_before><commit_msg>Update reveal.js<commit_after><|endoftext|>


<commit_before>// === SVG ICONS
// ============================================================================

module.exports = function(gulp, plugins, browserSync){

    var path = require('../settings/paths'),
        error = require('../settings/error-handler');

    gulp.task('sprites', function () {

        browserSync.notify('Running svg sprites');

        return gulp.src(path.to.svg.files)
            .pipe(plugins.svgSprite({
                svgId: "svg-%f",
                mode: "symbols",
                cssFile: path.to.scss.source + '/_sprite.scss',
                svg: {
                    symbols: "symbols.svg"
                }
            }))
            .pipe(gulp.dest(path.to.svg.source));
    });

};<commit_msg>Corrected the svgSprites task<commit_after>// === SVG ICONS
// ============================================================================

module.exports = function(gulp, plugins, browserSync){

    var path = require('../settings/paths'),
        error = require('../settings/error-handler');

    gulp.task('sprites', function () {

        browserSync.notify('Running svg sprites');

        return gulp.src(path.to.svg.files)
            .pipe(plugins.svgSprites({
                svgId: "svg-%f",
                mode: "symbols",
                cssFile: path.to.scss.source + '/_sprite.scss',
                svg: {
                    symbols: "symbols.svg"
                }
            }))
            .pipe(gulp.dest(path.to.svg.source));
    });

};<|endoftext|>


<commit_before>'use strict';

var feedbackUrl = '';
var gateHost = '{%gate.baseUrl%}';
var bakeryDetailUrl = (gateHost + '/bakery/logs/{{context.region}}/{{context.status.resourceId}}');
var authEndpoint = (gateHost + '/auth/user');
var authEnabled = '{%features.auth%}' === 'true';
var chaosEnabled = '{%features.chaos%}' === 'true';
var fiatEnabled = '{%features.fiat%}' === 'true';
var jobsEnabled = '{%features.jobs%}' === 'true';
var infrastructureStagesEnabled = "{%features.infrastructureStages%}" === "true";
var pipelineTemplatesEnabled = '{%features.pipelineTemplates%}' === 'true';
var artifactsEnabled = '{%features.artifacts%}' === 'true';
var mineCanaryEnabled = '{%features.mineCanary%}' === 'true';
var reduxLoggerEnabled = '{%canary.reduxLogger%}' === 'true';
var defaultMetricsAccountName = '{%canary.defaultMetricsAccount%}';
var defaultStorageAccountName = '{%canary.defaultStorageAccount%}';
var defaultCanaryJudge = '{%canary.defaultJudge%}';
var defaultMetricsStore = '{%canary.defaultMetricsStore%}';
var canaryStagesEnabled = '{%canary.stages%}' === 'true';
var atlasWebComponentsUrl = '{%canary.atlasWebComponentsUrl%}';
var templatesEnabled = '{%canary.templatesEnabled%}' === 'true';
var showAllConfigsEnabled = '{%canary.showAllCanaryConfigs%}' === 'true';
var canaryFeatureDisabled = '{%canary.featureEnabled%}' !== 'true';
var timezone = '{%timezone%}';
var version = '{%version%}';
var changelogGistId = '{%changelog.gist.id%}';
var changelogGistName = '{%changelog.gist.name%}';
var gce = {
  defaults: {
    account: '{%google.default.account%}',
    region: '{%google.default.region%}',
    zone: '{%google.default.zone%}'
  },
  associatePublicIpAddress: true,
};
var kubernetes = {
  defaults: {
    account: '{%kubernetes.default.account%}',
    namespace: '{%kubernetes.default.namespace%}',
    proxy: '{%kubernetes.default.proxy%}',
    internalDNSNameTemplate: '{{name}}.{{namespace}}.svc.cluster.local',
    instanceLinkTemplate: '{{host}}/api/v1/proxy/namespaces/{{namespace}}/pods/{{name}}',
  }
};
var appengine = {
  defaults: {
    account: '{%appengine.default.account%}',
    editLoadBalancerStageEnabled: '{%appengine.enabled%}' === 'true'
  }
};
var openstack = {
  defaults: {
    account: '{%openstack.default.account%}',
    region: '{%openstack.default.region%}'
  }
};
var azure = {
  defaults: {
    account: '{%azure.default.account%}',
    region: '{%azure.default.region%}'
  }
};
var oraclebmcs = {
  defaults: {
    account: '{%oraclebmcs.default.account%}',
    region: '{%oraclebmcs.default.region%}'
  }
};
var dcos = {
  defaults: {
    account: '{%dcos.default.account%}'
  }
};
var entityTagsEnabled = false;
var netflixMode = false;
var notificationsEnabled = '{%notifications.enabled%}' === 'true';
var slack = {
  enabled: '{%notifications.slack.enabled%}' === 'true',
  botName: '{%notifications.slack.botName%}'
};

window.spinnakerSettings = {
  version: version,
  checkForUpdates: false,
  defaultProviders: ['aws', 'gce', 'azure', 'cf', 'kubernetes', 'titus', 'openstack', 'oraclebmcs', 'dcos'],
  feedbackUrl: feedbackUrl,
  gateUrl: gateHost,
  bakeryDetailUrl: bakeryDetailUrl,
  authEndpoint: authEndpoint,
  pollSchedule: 30000,
  defaultTimeZone: timezone, // see http://momentjs.com/timezone/docs/#/data-utilities/
  defaultCategory: 'serverGroup',
  defaultInstancePort: 80,
  providers: {
    azure: azure,
    aws: {
      defaults: {
        account: 'test',
        region: 'us-east-1',
        iamRole: 'BaseIAMRole',
      },
      defaultSecurityGroups: [],
      loadBalancers: {
        // if true, VPC load balancers will be created as internal load balancers if the selected subnet has a purpose
        // tag that starts with "internal"
        inferInternalFlagFromSubnet: false,
      },
      useAmiBlockDeviceMappings: false,
    },
    gce: gce,
    titus: {
      defaults: {
        account: 'titustestvpc',
        region: 'us-east-1',
        iamProfile: '{{application}}InstanceProfile',
      },
    },
    openstack: openstack,
    kubernetes: kubernetes,
    appengine: appengine,
    oraclebmcs: oraclebmcs,
    dcos: dcos
  },
  changelog: {
    gistId: changelogGistId,
    fileName: changelogGistName,
  },
  notifications: {
    email: {
      enabled: true,
    },
    hipchat: {
      enabled: true,
      botName: 'Skynet T-800'
    },
    sms: {
      enabled: true,
    },
    slack: slack
  },
  pagerDuty: {
    required: false
  },
  authEnabled: authEnabled,
  authTtl: 600000,
  gitSources: ['stash', 'github', 'bitbucket'],
  triggerTypes: ['git', 'pipeline', 'docker', 'cron', 'jenkins', 'travis', 'pubsub', 'webhook'],
  canary: {
    reduxLogger: reduxLoggerEnabled,
    metricsAccountName: defaultMetricsAccountName,
    storageAccountName: defaultStorageAccountName,
    defaultJudge: defaultCanaryJudge,
    metricStore: defaultMetricsStore,
    stagesEnabled: canaryStagesEnabled,
    atlasWebComponentsUrl: atlasWebComponentsUrl,
    templatesEnabled: templatesEnabled,
    showAllConfigs: showAllConfigsEnabled,
    featureDisabled: canaryFeatureDisabled,
  },
  feature: {
    entityTags: entityTagsEnabled,
    fiatEnabled: fiatEnabled,
    netflixMode: netflixMode,
    chaosMonkey: chaosEnabled,
    jobs: jobsEnabled,
    pipelineTemplates: pipelineTemplatesEnabled,
    notifications: notificationsEnabled,
    artifacts: artifactsEnabled,
    canary: mineCanaryEnabled,
    infrastructureStages: infrastructureStagesEnabled,
    pipelines: true,
    fastProperty: true,
    vpcMigrator: true,
    pagerDuty: false,
    clusterDiff: false,
    roscoMode: true,
    infrastructureStages: false,
    snapshots: false,
    travis: false,
    versionedProviders: true,
  },
};
<commit_msg>feat(provider/appengine): add halyard feature flag for container image url deployments (#5126)<commit_after>'use strict';

var feedbackUrl = '';
var gateHost = '{%gate.baseUrl%}';
var bakeryDetailUrl = (gateHost + '/bakery/logs/{{context.region}}/{{context.status.resourceId}}');
var authEndpoint = (gateHost + '/auth/user');
var authEnabled = '{%features.auth%}' === 'true';
var chaosEnabled = '{%features.chaos%}' === 'true';
var fiatEnabled = '{%features.fiat%}' === 'true';
var jobsEnabled = '{%features.jobs%}' === 'true';
var infrastructureStagesEnabled = "{%features.infrastructureStages%}" === "true";
var pipelineTemplatesEnabled = '{%features.pipelineTemplates%}' === 'true';
var artifactsEnabled = '{%features.artifacts%}' === 'true';
var mineCanaryEnabled = '{%features.mineCanary%}' === 'true';
var reduxLoggerEnabled = '{%canary.reduxLogger%}' === 'true';
var defaultMetricsAccountName = '{%canary.defaultMetricsAccount%}';
var defaultStorageAccountName = '{%canary.defaultStorageAccount%}';
var defaultCanaryJudge = '{%canary.defaultJudge%}';
var defaultMetricsStore = '{%canary.defaultMetricsStore%}';
var canaryStagesEnabled = '{%canary.stages%}' === 'true';
var atlasWebComponentsUrl = '{%canary.atlasWebComponentsUrl%}';
var templatesEnabled = '{%canary.templatesEnabled%}' === 'true';
var showAllConfigsEnabled = '{%canary.showAllCanaryConfigs%}' === 'true';
var canaryFeatureDisabled = '{%canary.featureEnabled%}' !== 'true';
var timezone = '{%timezone%}';
var version = '{%version%}';
var changelogGistId = '{%changelog.gist.id%}';
var changelogGistName = '{%changelog.gist.name%}';
var appengineContainerImageUrlDeploymentsEnabled = '{%features.appengineContainerImageUrlDeployments%}' === 'true';
var gce = {
  defaults: {
    account: '{%google.default.account%}',
    region: '{%google.default.region%}',
    zone: '{%google.default.zone%}'
  },
  associatePublicIpAddress: true,
};
var kubernetes = {
  defaults: {
    account: '{%kubernetes.default.account%}',
    namespace: '{%kubernetes.default.namespace%}',
    proxy: '{%kubernetes.default.proxy%}',
    internalDNSNameTemplate: '{{name}}.{{namespace}}.svc.cluster.local',
    instanceLinkTemplate: '{{host}}/api/v1/proxy/namespaces/{{namespace}}/pods/{{name}}',
  }
};
var appengine = {
  defaults: {
    account: '{%appengine.default.account%}',
    editLoadBalancerStageEnabled: '{%appengine.enabled%}' === 'true',
    containerImageUrlDeployments: appengineContainerImageUrlDeploymentsEnabled,
  }
};
var openstack = {
  defaults: {
    account: '{%openstack.default.account%}',
    region: '{%openstack.default.region%}'
  }
};
var azure = {
  defaults: {
    account: '{%azure.default.account%}',
    region: '{%azure.default.region%}'
  }
};
var oraclebmcs = {
  defaults: {
    account: '{%oraclebmcs.default.account%}',
    region: '{%oraclebmcs.default.region%}'
  }
};
var dcos = {
  defaults: {
    account: '{%dcos.default.account%}'
  }
};
var entityTagsEnabled = false;
var netflixMode = false;
var notificationsEnabled = '{%notifications.enabled%}' === 'true';
var slack = {
  enabled: '{%notifications.slack.enabled%}' === 'true',
  botName: '{%notifications.slack.botName%}'
};

window.spinnakerSettings = {
  version: version,
  checkForUpdates: false,
  defaultProviders: ['aws', 'gce', 'azure', 'cf', 'kubernetes', 'titus', 'openstack', 'oraclebmcs', 'dcos'],
  feedbackUrl: feedbackUrl,
  gateUrl: gateHost,
  bakeryDetailUrl: bakeryDetailUrl,
  authEndpoint: authEndpoint,
  pollSchedule: 30000,
  defaultTimeZone: timezone, // see http://momentjs.com/timezone/docs/#/data-utilities/
  defaultCategory: 'serverGroup',
  defaultInstancePort: 80,
  providers: {
    azure: azure,
    aws: {
      defaults: {
        account: 'test',
        region: 'us-east-1',
        iamRole: 'BaseIAMRole',
      },
      defaultSecurityGroups: [],
      loadBalancers: {
        // if true, VPC load balancers will be created as internal load balancers if the selected subnet has a purpose
        // tag that starts with "internal"
        inferInternalFlagFromSubnet: false,
      },
      useAmiBlockDeviceMappings: false,
    },
    gce: gce,
    titus: {
      defaults: {
        account: 'titustestvpc',
        region: 'us-east-1',
        iamProfile: '{{application}}InstanceProfile',
      },
    },
    openstack: openstack,
    kubernetes: kubernetes,
    appengine: appengine,
    oraclebmcs: oraclebmcs,
    dcos: dcos
  },
  changelog: {
    gistId: changelogGistId,
    fileName: changelogGistName,
  },
  notifications: {
    email: {
      enabled: true,
    },
    hipchat: {
      enabled: true,
      botName: 'Skynet T-800'
    },
    sms: {
      enabled: true,
    },
    slack: slack
  },
  pagerDuty: {
    required: false
  },
  authEnabled: authEnabled,
  authTtl: 600000,
  gitSources: ['stash', 'github', 'bitbucket'],
  triggerTypes: ['git', 'pipeline', 'docker', 'cron', 'jenkins', 'travis', 'pubsub', 'webhook'],
  canary: {
    reduxLogger: reduxLoggerEnabled,
    metricsAccountName: defaultMetricsAccountName,
    storageAccountName: defaultStorageAccountName,
    defaultJudge: defaultCanaryJudge,
    metricStore: defaultMetricsStore,
    stagesEnabled: canaryStagesEnabled,
    atlasWebComponentsUrl: atlasWebComponentsUrl,
    templatesEnabled: templatesEnabled,
    showAllConfigs: showAllConfigsEnabled,
    featureDisabled: canaryFeatureDisabled,
  },
  feature: {
    entityTags: entityTagsEnabled,
    fiatEnabled: fiatEnabled,
    netflixMode: netflixMode,
    chaosMonkey: chaosEnabled,
    jobs: jobsEnabled,
    pipelineTemplates: pipelineTemplatesEnabled,
    notifications: notificationsEnabled,
    artifacts: artifactsEnabled,
    canary: mineCanaryEnabled,
    infrastructureStages: infrastructureStagesEnabled,
    pipelines: true,
    fastProperty: true,
    vpcMigrator: true,
    pagerDuty: false,
    clusterDiff: false,
    roscoMode: true,
    infrastructureStages: false,
    snapshots: false,
    travis: false,
    versionedProviders: true,
  },
};
<|endoftext|>


<commit_before>'use strict';

var gateHost = '{%gate.baseUrl%}';
var artifactsEnabled = '{%features.artifacts%}' === 'true';
var artifactsRewriteEnabled = '{%features.artifactsRewrite%}' === 'true';
var atlasWebComponentsUrl = '{%canary.atlasWebComponentsUrl%}';
var authEnabled = '{%features.auth%}' === 'true';
var authEndpoint = gateHost + '/auth/user';
var bakeryDetailUrl = gateHost + '/bakery/logs/{{context.region}}/{{context.status.resourceId}}';
var canaryFeatureDisabled = '{%canary.featureEnabled%}' !== 'true';
var canaryStagesEnabled = '{%canary.stages%}' === 'true';
var changelogGistId = '{%changelog.gist.id%}';
var changelogGistName = '{%changelog.gist.name%}';
var chaosEnabled = '{%features.chaos%}' === 'true';
var defaultCanaryJudge = '{%canary.defaultJudge%}';
var defaultMetricsStore = '{%canary.defaultMetricsStore%}';
var defaultMetricsAccountName = '{%canary.defaultMetricsAccount%}';
var defaultStorageAccountName = '{%canary.defaultStorageAccount%}';
var displayTimestampsInUserLocalTime = '{%features.displayTimestampsInUserLocalTime%}' === 'true';
var entityTagsEnabled = false;
var fiatEnabled = '{%features.fiat%}' === 'true';
var gceScaleDownControlsEnabled = '{%features.gceScaleDownControlsEnabled%}' === 'true';
var gceStatefulMigsEnabled = '{%features.gceStatefulMigsEnabled%}' === 'true';
var gremlinEnabled = '{%features.gremlin%}' === 'true';
var iapRefresherEnabled = '{%features.iapRefresherEnabled%}' === 'true';
var infrastructureStagesEnabled = '{%features.infrastructureStages%}' === 'true';
var maxPipelineAgeDays = '{%maxPipelineAgeDays%}';
var mineCanaryEnabled = '{%features.mineCanary%}' === 'true';
var notificationsEnabled = '{%notifications.enabled%}' === 'true';
var onDemandClusterThreshold = '{%onDemandClusterThreshold%}';
var pipelineTemplatesEnabled = '{%features.pipelineTemplates%}' === 'true';
var reduxLoggerEnabled = '{%canary.reduxLogger%}' === 'true';
var showAllConfigsEnabled = '{%canary.showAllCanaryConfigs%}' === 'true';
var slack = {
  botName: '{%notifications.slack.botName%}',
  enabled: '{%notifications.slack.enabled%}' === 'true',
};
var sms = {
  enabled: '{%notifications.twilio.enabled%}' === 'true',
};
var githubStatus = {
  enabled: '{%notifications.github-status.enabled%}' === 'true',
};
var templatesEnabled = '{%canary.templatesEnabled%}' === 'true';
var travisEnabled = '{%features.travis%}' === 'true';
var timezone = '{%timezone%}';
var version = '{%version%}';
var werckerEnabled = '{%features.wercker%}' === 'true';
var functionsEnabled = '{%features.functions%}' === 'true';

// Cloud Providers
var appengine = {
  defaults: {
    account: '{%appengine.default.account%}',
    editLoadBalancerStageEnabled: '{%appengine.enabled%}' === 'true',
  },
};
var aws = {
  defaults: {
    account: '{%aws.default.account%}',
    iamRole: 'BaseIAMRole',
    region: '{%aws.default.region%}',
  },
  defaultSecurityGroups: [],
  loadBalancers: {
    // if true, VPC load balancers will be created as internal load balancers if the selected subnet has a purpose
    // tag that starts with "internal"
    inferInternalFlagFromSubnet: false,
  },
  useAmiBlockDeviceMappings: false,
};
var azure = {
  defaults: {
    account: '{%azure.default.account%}',
    region: '{%azure.default.region%}',
  },
};
var cloudfoundry = {
  defaults: {
    account: '{%cloudfoundry.default.account%}',
  },
};
var dcos = {
  defaults: {
    account: '{%dcos.default.account%}',
  },
};
var ecs = {
  defaults: {
    account: '{%ecs.default.account%}',
  },
};
var gce = {
  defaults: {
    account: '{%google.default.account%}',
    region: '{%google.default.region%}',
    zone: '{%google.default.zone%}',
  },
  associatePublicIpAddress: true,
};
var kubernetes = {
  defaults: {
    account: '{%kubernetes.default.account%}',
    instanceLinkTemplate: '{{host}}/api/v1/proxy/namespaces/{{namespace}}/pods/{{name}}',
    internalDNSNameTemplate: '{{name}}.{{namespace}}.svc.cluster.local',
    namespace: '{%kubernetes.default.namespace%}',
    proxy: '{%kubernetes.default.proxy%}',
  },
};
var huaweicloud = {
  defaults: {
    account: '{%huaweicloud.default.account%}',
    region: '{%huaweicloud.default.region%}',
  },
};
var oracle = {
  defaults: {
    account: '{%oracle.default.account%}',
    region: '{%oracle.default.region%}',
  },
};

window.spinnakerSettings = {
  authEnabled: authEnabled,
  authEndpoint: authEndpoint,
  authTtl: 600000,
  bakeryDetailUrl: bakeryDetailUrl,
  canary: {
    atlasWebComponentsUrl: atlasWebComponentsUrl,
    defaultJudge: defaultCanaryJudge,
    featureDisabled: canaryFeatureDisabled,
    reduxLogger: reduxLoggerEnabled,
    metricsAccountName: defaultMetricsAccountName,
    metricStore: defaultMetricsStore,
    showAllConfigs: showAllConfigsEnabled,
    stagesEnabled: canaryStagesEnabled,
    storageAccountName: defaultStorageAccountName,
    templatesEnabled: templatesEnabled,
  },
  changelog: {
    fileName: changelogGistName,
    gistId: changelogGistId,
  },
  checkForUpdates: false,
  defaultInstancePort: 80,
  defaultProviders: [
    'appengine',
    'aws',
    'azure',
    'cloudfoundry',
    'dcos',
    'ecs',
    'gce',
    'huaweicloud',
    'kubernetes',
    'oracle',
    'titus',
  ],
  defaultTimeZone: timezone, // see http://momentjs.com/timezone/docs/#/data-utilities/
  feature: {
    artifacts: artifactsEnabled,
    artifactsRewrite: artifactsRewriteEnabled,
    canary: mineCanaryEnabled,
    chaosMonkey: chaosEnabled,
    displayTimestampsInUserLocalTime: displayTimestampsInUserLocalTime,
    entityTags: entityTagsEnabled,
    fiatEnabled: fiatEnabled,
    gceScaleDownControlsEnabled: gceScaleDownControlsEnabled,
    gceStatefulMigsEnabled: gceStatefulMigsEnabled,
    gremlinEnabled: gremlinEnabled,
    iapRefresherEnabled: iapRefresherEnabled,
    infrastructureStages: infrastructureStagesEnabled,
    notifications: notificationsEnabled,
    pagerDuty: false,
    pipelines: true,
    pipelineTemplates: pipelineTemplatesEnabled,
    roscoMode: true,
    slack: false,
    snapshots: false,
    travis: travisEnabled,
    wercker: werckerEnabled,
    functions: functionsEnabled,
  },
  gateUrl: gateHost,
  gitSources: ['bitbucket', 'gitlab', 'github', 'stash'],
  maxPipelineAgeDays: maxPipelineAgeDays,
  newApplicationDefaults: {
    chaosMonkey: false,
  },
  notifications: {
    bearychat: {
      enabled: true,
    },
    email: {
      enabled: true,
    },
    githubStatus: githubStatus,
    googlechat: {
      enabled: true,
    },
    pubsub: {
      enabled: true,
    },
    slack: slack,
    sms: sms,
  },
  onDemandClusterThreshold: onDemandClusterThreshold,
  pagerDuty: {
    required: false,
  },
  pollSchedule: 30000,
  providers: {
    appengine: appengine,
    aws: aws,
    azure: azure,
    cloudfoundry: cloudfoundry,
    dcos: dcos,
    ecs: ecs,
    gce: gce,
    huaweicloud: huaweicloud,
    kubernetes: kubernetes,
    oracle: oracle,
    titus: {
      defaults: {
        account: 'titustestvpc',
        iamProfile: '{{application}}InstanceProfile',
        region: 'us-east-1',
      },
    },
  },
  pubsubProviders: ['google'], // TODO(joonlim): Add amazon once it is confirmed that amazon pub/sub works.
  triggerTypes: [
    'artifactory',
    'nexus',
    'concourse',
    'cron',
    'docker',
    'git',
    'jenkins',
    'pipeline',
    'pubsub',
    'travis',
    'webhook',
    'wercker',
  ],
  version: version,
};
<commit_msg>feat(pubsub): Add amazon as pubsubProvider (#7908)<commit_after>'use strict';

var gateHost = '{%gate.baseUrl%}';
var artifactsEnabled = '{%features.artifacts%}' === 'true';
var artifactsRewriteEnabled = '{%features.artifactsRewrite%}' === 'true';
var atlasWebComponentsUrl = '{%canary.atlasWebComponentsUrl%}';
var authEnabled = '{%features.auth%}' === 'true';
var authEndpoint = gateHost + '/auth/user';
var bakeryDetailUrl = gateHost + '/bakery/logs/{{context.region}}/{{context.status.resourceId}}';
var canaryFeatureDisabled = '{%canary.featureEnabled%}' !== 'true';
var canaryStagesEnabled = '{%canary.stages%}' === 'true';
var changelogGistId = '{%changelog.gist.id%}';
var changelogGistName = '{%changelog.gist.name%}';
var chaosEnabled = '{%features.chaos%}' === 'true';
var defaultCanaryJudge = '{%canary.defaultJudge%}';
var defaultMetricsStore = '{%canary.defaultMetricsStore%}';
var defaultMetricsAccountName = '{%canary.defaultMetricsAccount%}';
var defaultStorageAccountName = '{%canary.defaultStorageAccount%}';
var displayTimestampsInUserLocalTime = '{%features.displayTimestampsInUserLocalTime%}' === 'true';
var entityTagsEnabled = false;
var fiatEnabled = '{%features.fiat%}' === 'true';
var gceScaleDownControlsEnabled = '{%features.gceScaleDownControlsEnabled%}' === 'true';
var gceStatefulMigsEnabled = '{%features.gceStatefulMigsEnabled%}' === 'true';
var gremlinEnabled = '{%features.gremlin%}' === 'true';
var iapRefresherEnabled = '{%features.iapRefresherEnabled%}' === 'true';
var infrastructureStagesEnabled = '{%features.infrastructureStages%}' === 'true';
var maxPipelineAgeDays = '{%maxPipelineAgeDays%}';
var mineCanaryEnabled = '{%features.mineCanary%}' === 'true';
var notificationsEnabled = '{%notifications.enabled%}' === 'true';
var onDemandClusterThreshold = '{%onDemandClusterThreshold%}';
var pipelineTemplatesEnabled = '{%features.pipelineTemplates%}' === 'true';
var reduxLoggerEnabled = '{%canary.reduxLogger%}' === 'true';
var showAllConfigsEnabled = '{%canary.showAllCanaryConfigs%}' === 'true';
var slack = {
  botName: '{%notifications.slack.botName%}',
  enabled: '{%notifications.slack.enabled%}' === 'true',
};
var sms = {
  enabled: '{%notifications.twilio.enabled%}' === 'true',
};
var githubStatus = {
  enabled: '{%notifications.github-status.enabled%}' === 'true',
};
var templatesEnabled = '{%canary.templatesEnabled%}' === 'true';
var travisEnabled = '{%features.travis%}' === 'true';
var timezone = '{%timezone%}';
var version = '{%version%}';
var werckerEnabled = '{%features.wercker%}' === 'true';
var functionsEnabled = '{%features.functions%}' === 'true';

// Cloud Providers
var appengine = {
  defaults: {
    account: '{%appengine.default.account%}',
    editLoadBalancerStageEnabled: '{%appengine.enabled%}' === 'true',
  },
};
var aws = {
  defaults: {
    account: '{%aws.default.account%}',
    iamRole: 'BaseIAMRole',
    region: '{%aws.default.region%}',
  },
  defaultSecurityGroups: [],
  loadBalancers: {
    // if true, VPC load balancers will be created as internal load balancers if the selected subnet has a purpose
    // tag that starts with "internal"
    inferInternalFlagFromSubnet: false,
  },
  useAmiBlockDeviceMappings: false,
};
var azure = {
  defaults: {
    account: '{%azure.default.account%}',
    region: '{%azure.default.region%}',
  },
};
var cloudfoundry = {
  defaults: {
    account: '{%cloudfoundry.default.account%}',
  },
};
var dcos = {
  defaults: {
    account: '{%dcos.default.account%}',
  },
};
var ecs = {
  defaults: {
    account: '{%ecs.default.account%}',
  },
};
var gce = {
  defaults: {
    account: '{%google.default.account%}',
    region: '{%google.default.region%}',
    zone: '{%google.default.zone%}',
  },
  associatePublicIpAddress: true,
};
var kubernetes = {
  defaults: {
    account: '{%kubernetes.default.account%}',
    instanceLinkTemplate: '{{host}}/api/v1/proxy/namespaces/{{namespace}}/pods/{{name}}',
    internalDNSNameTemplate: '{{name}}.{{namespace}}.svc.cluster.local',
    namespace: '{%kubernetes.default.namespace%}',
    proxy: '{%kubernetes.default.proxy%}',
  },
};
var huaweicloud = {
  defaults: {
    account: '{%huaweicloud.default.account%}',
    region: '{%huaweicloud.default.region%}',
  },
};
var oracle = {
  defaults: {
    account: '{%oracle.default.account%}',
    region: '{%oracle.default.region%}',
  },
};

window.spinnakerSettings = {
  authEnabled: authEnabled,
  authEndpoint: authEndpoint,
  authTtl: 600000,
  bakeryDetailUrl: bakeryDetailUrl,
  canary: {
    atlasWebComponentsUrl: atlasWebComponentsUrl,
    defaultJudge: defaultCanaryJudge,
    featureDisabled: canaryFeatureDisabled,
    reduxLogger: reduxLoggerEnabled,
    metricsAccountName: defaultMetricsAccountName,
    metricStore: defaultMetricsStore,
    showAllConfigs: showAllConfigsEnabled,
    stagesEnabled: canaryStagesEnabled,
    storageAccountName: defaultStorageAccountName,
    templatesEnabled: templatesEnabled,
  },
  changelog: {
    fileName: changelogGistName,
    gistId: changelogGistId,
  },
  checkForUpdates: false,
  defaultInstancePort: 80,
  defaultProviders: [
    'appengine',
    'aws',
    'azure',
    'cloudfoundry',
    'dcos',
    'ecs',
    'gce',
    'huaweicloud',
    'kubernetes',
    'oracle',
    'titus',
  ],
  defaultTimeZone: timezone, // see http://momentjs.com/timezone/docs/#/data-utilities/
  feature: {
    artifacts: artifactsEnabled,
    artifactsRewrite: artifactsRewriteEnabled,
    canary: mineCanaryEnabled,
    chaosMonkey: chaosEnabled,
    displayTimestampsInUserLocalTime: displayTimestampsInUserLocalTime,
    entityTags: entityTagsEnabled,
    fiatEnabled: fiatEnabled,
    gceScaleDownControlsEnabled: gceScaleDownControlsEnabled,
    gceStatefulMigsEnabled: gceStatefulMigsEnabled,
    gremlinEnabled: gremlinEnabled,
    iapRefresherEnabled: iapRefresherEnabled,
    infrastructureStages: infrastructureStagesEnabled,
    notifications: notificationsEnabled,
    pagerDuty: false,
    pipelines: true,
    pipelineTemplates: pipelineTemplatesEnabled,
    roscoMode: true,
    slack: false,
    snapshots: false,
    travis: travisEnabled,
    wercker: werckerEnabled,
    functions: functionsEnabled,
  },
  gateUrl: gateHost,
  gitSources: ['bitbucket', 'gitlab', 'github', 'stash'],
  maxPipelineAgeDays: maxPipelineAgeDays,
  newApplicationDefaults: {
    chaosMonkey: false,
  },
  notifications: {
    bearychat: {
      enabled: true,
    },
    email: {
      enabled: true,
    },
    githubStatus: githubStatus,
    googlechat: {
      enabled: true,
    },
    pubsub: {
      enabled: true,
    },
    slack: slack,
    sms: sms,
  },
  onDemandClusterThreshold: onDemandClusterThreshold,
  pagerDuty: {
    required: false,
  },
  pollSchedule: 30000,
  providers: {
    appengine: appengine,
    aws: aws,
    azure: azure,
    cloudfoundry: cloudfoundry,
    dcos: dcos,
    ecs: ecs,
    gce: gce,
    huaweicloud: huaweicloud,
    kubernetes: kubernetes,
    oracle: oracle,
    titus: {
      defaults: {
        account: 'titustestvpc',
        iamProfile: '{{application}}InstanceProfile',
        region: 'us-east-1',
      },
    },
  },
  pubsubProviders: ['amazon', 'google'],
  triggerTypes: [
    'artifactory',
    'nexus',
    'concourse',
    'cron',
    'docker',
    'git',
    'jenkins',
    'pipeline',
    'pubsub',
    'travis',
    'webhook',
    'wercker',
  ],
  version: version,
};
<|endoftext|>