From 9ee9b4b9cfa651f59d3a88ae4b856ade91314a96 Mon Sep 17 00:00:00 2001 From: GregZ Date: Fri, 26 Sep 2014 17:10:57 -0600 Subject: [PATCH 1/6] feat(gen:cloudfoundry): add cloudfoundry deploy sub-generator --- app/templates/Gruntfile.js | 4 +- cloudfoundry/USAGE | 8 ++ cloudfoundry/index.js | 174 ++++++++++++++++++++++++++++ cloudfoundry/templates/Procfile | 1 + cloudfoundry/templates/manifest.yml | 5 + 5 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 cloudfoundry/USAGE create mode 100644 cloudfoundry/index.js create mode 100644 cloudfoundry/templates/Procfile create mode 100644 cloudfoundry/templates/manifest.yml diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 6755db958..0a7a18e2f 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -216,7 +216,9 @@ module.exports = function (grunt) { '<%%= yeoman.dist %>/*', '!<%%= yeoman.dist %>/.git*', '!<%%= yeoman.dist %>/.openshift', - '!<%%= yeoman.dist %>/Procfile' + '!<%%= yeoman.dist %>/.cfignore', + '!<%%= yeoman.dist %>/Procfile', + '!<%%= yeoman.dist %>/manifest.yml' ] }] }, diff --git a/cloudfoundry/USAGE b/cloudfoundry/USAGE new file mode 100644 index 000000000..be7892e48 --- /dev/null +++ b/cloudfoundry/USAGE @@ -0,0 +1,8 @@ +Description: + Initalizes a cloud foundr app and generates a `dist` folder which is ready to push to cloud foundry. + +Example: + yo angular-fullstack:cloudfoundry + + This will create: + a dist folder and initialize a cloud foundry app diff --git a/cloudfoundry/index.js b/cloudfoundry/index.js new file mode 100644 index 000000000..56adf8849 --- /dev/null +++ b/cloudfoundry/index.js @@ -0,0 +1,174 @@ +'use strict'; +var util = require('util'); +var genUtils = require('../util.js'); +var yeoman = require('yeoman-generator'); +var exec = require('child_process').exec; +var chalk = require('chalk'); +var path = require('path'); + +var Generator = module.exports = function Generator() { + yeoman.generators.Base.apply(this, arguments); + this.sourceRoot(path.join(__dirname, './templates')); + + try { + this.appname = require(path.join(process.cwd(), 'bower.json')).name; + } catch (e) { + this.appname = path.basename(process.cwd()); + } + this.appname = this._.slugify(this.appname); + this.filters = this.config.get('filters') || {}; +}; + +util.inherits(Generator, yeoman.generators.NamedBase); + +Generator.prototype.askForRoute = function askForRoute() { + var done = this.async(); + + var prompts = [ + { + name: 'routeName', + message: 'Name of route to deploy (Leave blank for a random route name):' + } + ]; + + this.prompt(prompts, function (props) { + this.routeName = this._.slugify(props.routeName); + done(); + }.bind(this)); +}; + +Generator.prototype.checkInstallation = function checkInstallation() { + if (this.abort) return; + var done = this.async(); + + exec('cf --version', function (err) { + if (err) { + this.log.error('You don\'t have the Cloud Foundry CLI installed. ' + + 'Grab it from https://github.com/cloudfoundry/cli'); + this.abort = true; + } + done(); + }.bind(this)); +}; + +Generator.prototype.askForApiEndpoint = function askForApiEndpoint() { + if (this.abort) return; + var done = this.async(); + + var prompts = [ + { + name: 'apiEndpoint', + default: 'api.run.pivotal.io', + message: 'What api endpoint will you be using for Cloud Foundry?:' + } + ]; + + this.prompt(prompts, function (props) { + this.apiEndpoint = props.apiEndpoint; + done(); + }.bind(this)); +}; + +Generator.prototype.cfInit = function cfInit() { + if (this.abort) return; + var done = this.async(); + + this.log(chalk.bold('Setting Cloud Foundry api endpoint')); + this.mkdir('dist'); + var child = exec('cf api ' + this.apiEndpoint, { cwd: 'dist' }, function (err, stdout, stderr) { + if (err) { + this.abort = true; + this.log.error(err); + } else { + if (stdout.indexOf('Not logged in.') !== -1) { + this.log.error('You don\'t appear to be logged. Please login and try again.'); + this.abort = true; + } else { + this.log('stdout: ' + stdout); + } + + } + done(); + }.bind(this)); + + child.stdout.on('data', function (data) { + this.log(this._.trim(data.toString(), "\n\r")); + }.bind(this)); +} + +Generator.prototype.copyProcfile = function copyProcfile() { + if (this.abort) return; + var done = this.async(); + this.log(chalk.bold('Creating Procfile and manifest.yml')); + genUtils.processDirectory(this, '.', './dist'); + this.conflicter.resolve(function (err) { + done(); + }); +}; + +Generator.prototype.gruntBuild = function gruntBuild() { + if (this.abort) return; + var done = this.async(); + + this.log(chalk.bold('\nBuilding dist folder, please wait...')); + var child = exec('grunt build', function (err, stdout) { + done(); + }.bind(this)); + child.stdout.on('data', function (data) { + this.log(data.toString()); + }.bind(this)); +}; + +Generator.prototype.cfPush = function cfPush() { + if (this.abort) return; + var done = this.async(); + + this.log(chalk.bold("\nUploading your initial application code.\n This may take " + chalk.cyan('several minutes') + " depending on your connection speed...")); + + var randomRoute = this.routeName === '' ? '--random-route' : ''; + var child = exec(['cf push', this.appname, randomRoute].join(' '), { cwd: 'dist' }, function (err, stdout, stderr) { + if (err) { + this.log.error(err); + } else { + var hasWarning = false; + + if (this.filters.mongoose) { + this.log(chalk.yellow('\nBecause you\'re using mongoose, you must add mongoDB to your cloud foundry app.\n\t' + 'from `/dist`: ' + chalk.bold('cf create-service mongolab sandbox my-mongo') + '\n')); + hasWarning = true; + } + + if (this.filters.facebookAuth) { + this.log(chalk.yellow('You will need to set environment variables for facebook auth. From `/dist`:\n\t' + + chalk.bold('cf set-env ' + this.appName + ' FACEBOOK_ID appId\n\t') + + chalk.bold('cf set-env ' + this.appName + ' FACEBOOK_SECRET secret\n'))); + hasWarning = true; + } + if (this.filters.googleAuth) { + this.log(chalk.yellow('You will need to set environment variables for google auth. From `/dist`:\n\t' + + chalk.bold('cf set-env ' + this.appName + ' GOOGLE_ID appId\n\t') + + chalk.bold('cf set-env ' + this.appName + ' GOOGLE_SECRET secret\n'))); + hasWarning = true; + } + if (this.filters.twitterAuth) { + this.log(chalk.yellow('You will need to set environment variables for twitter auth. From `/dist`:\n\t' + + chalk.bold('cf set-env ' + this.appName + ' TWITTER_ID appId\n\t') + + chalk.bold('cf set-env ' + this.appName + ' TWITTER_SECRET secret\n'))); + hasWarning = true; + } + + this.log(chalk.green('\nYour app should now be live.')); + if (hasWarning) { + this.log(chalk.green('\nYou may need to address the issues mentioned above and restart the server for the app to work correctly.')); + } + /* + todo: build grunt plugin grunt-cf-deploy and add to this generator + this.log(chalk.yellow('After app modification run\n\t' + chalk.bold('grunt build') + + '\nThen deploy with\n\t' + chalk.bold('grunt cfDeploy'))); + */ + } + done(); + }.bind(this)); + child.stdout.on('data', function (data) { + this.log(this._.trim(data.toString(), "\n\r")); + }.bind(this)); +}; diff --git a/cloudfoundry/templates/Procfile b/cloudfoundry/templates/Procfile new file mode 100644 index 000000000..528737e6f --- /dev/null +++ b/cloudfoundry/templates/Procfile @@ -0,0 +1 @@ +web: node server/app.js diff --git a/cloudfoundry/templates/manifest.yml b/cloudfoundry/templates/manifest.yml new file mode 100644 index 000000000..9a9829d89 --- /dev/null +++ b/cloudfoundry/templates/manifest.yml @@ -0,0 +1,5 @@ +--- +applications: +- name: <%= appname %> + buildpack: https://github.com/cloudfoundry/heroku-buildpack-nodejs.git + command: node server/app.js \ No newline at end of file From b96da3f23c65d31bed207a0ef14824489eaa27cf Mon Sep 17 00:00:00 2001 From: Greg Ziebold and Nathan Barefield Date: Tue, 30 Sep 2014 13:21:25 -0600 Subject: [PATCH 2/6] feat(gen:cloudfoundry): add working tests, and support for mongolab services --- .../server/config/environment/index.js | 2 +- .../server/config/environment/production.js | 15 +- cloudfoundry/index.js | 81 ++++++--- test/cf-test-creation.js | 157 ++++++++++++++++++ 4 files changed, 230 insertions(+), 25 deletions(-) create mode 100644 test/cf-test-creation.js diff --git a/app/templates/server/config/environment/index.js b/app/templates/server/config/environment/index.js index 2476a7e8c..384197dba 100644 --- a/app/templates/server/config/environment/index.js +++ b/app/templates/server/config/environment/index.js @@ -19,7 +19,7 @@ var all = { root: path.normalize(__dirname + '/../../..'), // Server port - port: process.env.PORT || 9000, + port: process.env.PORT || process.env.VCAP_APP_PORT || 9000, // Should we populate the DB with sample data? seedDB: false, diff --git a/app/templates/server/config/environment/production.js b/app/templates/server/config/environment/production.js index e0b77bf97..24c51ea3e 100644 --- a/app/templates/server/config/environment/production.js +++ b/app/templates/server/config/environment/production.js @@ -2,6 +2,17 @@ // Production specific configuration // ================================= + +// cloud foundry +var getCfMongo = function() { + var vcap_services = JSON.parse(process.env.VCAP_SERVICES), + mongoUri; + if (vcap_services.mongolab && vcap_services.mongolab.length > 0) { + mongoUri = vcap_services.mongolab[0].credentials.uri; + } + return mongoUri; +}; + module.exports = { // Server IP ip: process.env.OPENSHIFT_NODEJS_IP || @@ -11,6 +22,7 @@ module.exports = { // Server port port: process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || + process.env.VCAP_APP_PORT || 8080, // MongoDB connection options @@ -19,6 +31,7 @@ module.exports = { process.env.MONGOHQ_URL || process.env.OPENSHIFT_MONGODB_DB_URL + process.env.OPENSHIFT_APP_NAME || + getCfMongo() || 'mongodb://localhost/<%= _.slugify(appname) %>' } -}; +}; \ No newline at end of file diff --git a/cloudfoundry/index.js b/cloudfoundry/index.js index 56adf8849..1047dd9df 100644 --- a/cloudfoundry/index.js +++ b/cloudfoundry/index.js @@ -31,7 +31,7 @@ Generator.prototype.askForRoute = function askForRoute() { } ]; - this.prompt(prompts, function (props) { + this.prompt(prompts, function(props) { this.routeName = this._.slugify(props.routeName); done(); }.bind(this)); @@ -41,10 +41,10 @@ Generator.prototype.checkInstallation = function checkInstallation() { if (this.abort) return; var done = this.async(); - exec('cf --version', function (err) { + exec('cf --version', function(err) { if (err) { this.log.error('You don\'t have the Cloud Foundry CLI installed. ' + - 'Grab it from https://github.com/cloudfoundry/cli'); + 'Grab it from https://github.com/cloudfoundry/cli'); this.abort = true; } done(); @@ -63,7 +63,7 @@ Generator.prototype.askForApiEndpoint = function askForApiEndpoint() { } ]; - this.prompt(prompts, function (props) { + this.prompt(prompts, function(props) { this.apiEndpoint = props.apiEndpoint; done(); }.bind(this)); @@ -75,7 +75,7 @@ Generator.prototype.cfInit = function cfInit() { this.log(chalk.bold('Setting Cloud Foundry api endpoint')); this.mkdir('dist'); - var child = exec('cf api ' + this.apiEndpoint, { cwd: 'dist' }, function (err, stdout, stderr) { + var child = exec('cf api ' + this.apiEndpoint, { cwd: 'dist' }, function(err, stdout, stderr) { if (err) { this.abort = true; this.log.error(err); @@ -91,7 +91,7 @@ Generator.prototype.cfInit = function cfInit() { done(); }.bind(this)); - child.stdout.on('data', function (data) { + child.stdout.on('data', function(data) { this.log(this._.trim(data.toString(), "\n\r")); }.bind(this)); } @@ -101,7 +101,7 @@ Generator.prototype.copyProcfile = function copyProcfile() { var done = this.async(); this.log(chalk.bold('Creating Procfile and manifest.yml')); genUtils.processDirectory(this, '.', './dist'); - this.conflicter.resolve(function (err) { + this.conflicter.resolve(function(err) { done(); }); }; @@ -111,10 +111,10 @@ Generator.prototype.gruntBuild = function gruntBuild() { var done = this.async(); this.log(chalk.bold('\nBuilding dist folder, please wait...')); - var child = exec('grunt build', function (err, stdout) { + var child = exec('grunt build', function(err, stdout) { done(); }.bind(this)); - child.stdout.on('data', function (data) { + child.stdout.on('data', function(data) { this.log(data.toString()); }.bind(this)); }; @@ -126,8 +126,44 @@ Generator.prototype.cfPush = function cfPush() { this.log(chalk.bold("\nUploading your initial application code.\n This may take " + chalk.cyan('several minutes') + " depending on your connection speed...")); var randomRoute = this.routeName === '' ? '--random-route' : ''; - var child = exec(['cf push', this.appname, randomRoute].join(' '), { cwd: 'dist' }, function (err, stdout, stderr) { + var child = exec(['cf push', this.appname, randomRoute, ' --no-start'].join(' '), { cwd: 'dist' }, function(err, stdout, stderr) { if (err) { + this.abort = true; + this.log.error(err); + } else { + this.log('stdout: ' + stdout); + } + done(); + }.bind(this)); + child.stdout.on('data', function(data) { + this.log(this._.trim(data.toString(), "\n\r")); + }.bind(this)); +}; + +Generator.prototype.cfSetEnvVars = function cfSetEnvVars() { + if (this.abort) return; + var done = this.async(); + + var child = exec('cf set-env ' + this.appname + ' NODE_ENV production', { cwd: 'dist' }, function(err, stdout, stderr) { + if (err) { + this.abort = true; + this.log.error(err); + } + done(); + + }.bind(this)); + child.stdout.on('data', function(data) { + this.log(this._.trim(data.toString(), "\n\r")); + }.bind(this)); +}; + +Generator.prototype.cfStart = function cfStart() { + if (this.abort) return; + var done = this.async(); + + var child = exec('cf start ' + this.appname, { cwd: 'dist' }, function(err, stdout, stderr) { + if (err) { + this.abort = true; this.log.error(err); } else { var hasWarning = false; @@ -139,20 +175,20 @@ Generator.prototype.cfPush = function cfPush() { if (this.filters.facebookAuth) { this.log(chalk.yellow('You will need to set environment variables for facebook auth. From `/dist`:\n\t' + - chalk.bold('cf set-env ' + this.appName + ' FACEBOOK_ID appId\n\t') + - chalk.bold('cf set-env ' + this.appName + ' FACEBOOK_SECRET secret\n'))); + chalk.bold('cf set-env ' + this.appname + ' FACEBOOK_ID appId\n\t') + + chalk.bold('cf set-env ' + this.appname + ' FACEBOOK_SECRET secret\n'))); hasWarning = true; } if (this.filters.googleAuth) { this.log(chalk.yellow('You will need to set environment variables for google auth. From `/dist`:\n\t' + - chalk.bold('cf set-env ' + this.appName + ' GOOGLE_ID appId\n\t') + - chalk.bold('cf set-env ' + this.appName + ' GOOGLE_SECRET secret\n'))); + chalk.bold('cf set-env ' + this.appname + ' GOOGLE_ID appId\n\t') + + chalk.bold('cf set-env ' + this.appname + ' GOOGLE_SECRET secret\n'))); hasWarning = true; } if (this.filters.twitterAuth) { this.log(chalk.yellow('You will need to set environment variables for twitter auth. From `/dist`:\n\t' + - chalk.bold('cf set-env ' + this.appName + ' TWITTER_ID appId\n\t') + - chalk.bold('cf set-env ' + this.appName + ' TWITTER_SECRET secret\n'))); + chalk.bold('cf set-env ' + this.appname + ' TWITTER_ID appId\n\t') + + chalk.bold('cf set-env ' + this.appname + ' TWITTER_SECRET secret\n'))); hasWarning = true; } @@ -160,15 +196,14 @@ Generator.prototype.cfPush = function cfPush() { if (hasWarning) { this.log(chalk.green('\nYou may need to address the issues mentioned above and restart the server for the app to work correctly.')); } - /* - todo: build grunt plugin grunt-cf-deploy and add to this generator - this.log(chalk.yellow('After app modification run\n\t' + chalk.bold('grunt build') + - '\nThen deploy with\n\t' + chalk.bold('grunt cfDeploy'))); - */ + this.log(chalk.yellow('After app modification run\n\t' + chalk.bold('grunt build') + + '\nThen deploy (from dist directory ) with\n\t' + chalk.bold('cf push'))); } done(); + }.bind(this)); - child.stdout.on('data', function (data) { + child.stdout.on('data', function(data) { this.log(this._.trim(data.toString(), "\n\r")); }.bind(this)); -}; + +}; \ No newline at end of file diff --git a/test/cf-test-creation.js b/test/cf-test-creation.js new file mode 100644 index 000000000..1e6e8ebe5 --- /dev/null +++ b/test/cf-test-creation.js @@ -0,0 +1,157 @@ +/*global describe, beforeEach, it */ +'use strict'; +var path = require('path'); +var helpers = require('yeoman-generator').test; +var chai = require('chai'); +var expect = chai.expect; +var fs = require('fs-extra'); +var exec = require('child_process').exec; + +describe('angular-fullstack:cloudfoundry', function () { + var gen, defaultOptions = { + script: 'js', + markup: 'html', + stylesheet: 'sass', + router: 'uirouter', + bootstrap: true, + uibootstrap: false, + mongoose: false, + auth: false, + oauth: [], + socketio: false + }; + + + function generatorTest(generatorType, name, mockPrompt, callback) { + gen.run({}, function () { + var afGenerator; + var deps = [path.join('../..', generatorType)]; + afGenerator = helpers.createGenerator('angular-fullstack:' + generatorType, deps, [name]); + + helpers.mockPrompt(afGenerator, mockPrompt); + afGenerator.run([], function () { + callback(); + }); + }); + } + + beforeEach(function (done) { + this.timeout(10000); + this.appname = 'testapp' + Math.floor(Math.random()*100000000).toString(); + var deps = [ + '../../app', + [ + helpers.createDummyGenerator(), + 'ng-component:app' + ] + ]; + + helpers.testDirectory(path.join(__dirname, this.appname), function (err) { + if (err) { + return done(err); + } + + gen = helpers.createGenerator('angular-fullstack:app', deps); + gen.options['skip-install'] = true; + + fs.mkdirSync(__dirname + '/' + this.appname + '/client'); + fs.symlinkSync(__dirname + '/fixtures/node_modules', __dirname + '/' + this.appname + '/node_modules'); + fs.symlinkSync(__dirname +'/fixtures/bower_components', __dirname + '/' + this.appname + '/client/bower_components'); + + helpers.mockPrompt(gen, defaultOptions); + this.timeout(60000); + + done(); + }.bind(this)); + }); + + afterEach(function (done) { + exec('cf delete ' + this.appname + " -r -f", function (error, stdout, stderr) { + gen.log("Deleting cloudfoundry app instance for " + this.appname + "..."); + if (error) { + gen.log(error); + } + done(); + }.bind(this)); + + }); + + afterEach(function (done) { + exec('rm -rf ' + this.appname, { cwd: '..' }, function (error, stdout, stderr) { + gen.log("Deleting local app instance for " + this.appname + "..."); + if (error) { + gen.log(error); + } + done(); + }.bind(this)); + + }); + + it('copies procfile and manifest files with named route', function (done) { + var mockPromptOptions = { + routeName: Math.floor(Math.random()*100000000).toString(), + apiEndpoint: '' + }; + generatorTest('cloudfoundry', 'cf-test', mockPromptOptions, function () { + helpers.assertFile([ + 'dist/Procfile', + 'dist/manifest.yml' + ]); + exec('cf app ' + this.appname, function (error, stdout, stderr) { + if (error) { + console.log(error); + console.log(stderr); + } + + gen.log(stdout); + expect(stdout, 'App failed to start: \n' + stdout).to.contain('running'); + done(); + }); + }.bind(this)); + }); + + it('copies procfile and manifest files with blank route name', function (done) { + var mockPromptOptions = { + routeName: '', + apiEndpoint: '' + }; + generatorTest('cloudfoundry', 'cf-test', mockPromptOptions, function () { + helpers.assertFile([ + 'dist/Procfile', + 'dist/manifest.yml' + ]); + exec('cf app ' + this.appname, function (error, stdout, stderr) { + if (error) { + console.log(error); + console.log(stderr); + } + gen.log(stdout); + expect(stdout, 'App failed to start: \n' + stdout).to.contain('running'); + done(); + }); + }.bind(this)); + }); + + it('copies procfile and manifest files with specific apiendpoint', function (done) { + var mockPromptOptions = { + routeName: '', + apiEndpoint: 'api.run.pivotal.io' + }; + generatorTest('cloudfoundry', 'cf-test', mockPromptOptions, function () { + helpers.assertFile([ + 'dist/Procfile', + 'dist/manifest.yml' + ]); + exec('cf app ' + this.appname, function (error, stdout, stderr) { + if (error) { + console.log(error); + console.log(stderr); + } + gen.log(stdout); + expect(stdout, 'App failed to start: \n' + stdout).to.contain('running'); + done(); + }); + }.bind(this)); + }); + +}); From d73b5730863517302a3276044431cb97b61e603c Mon Sep 17 00:00:00 2001 From: Greg Ziebold Date: Wed, 1 Oct 2014 20:05:19 -0600 Subject: [PATCH 3/6] feat(gen:cloudfoundry): update readme --- readme.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 31836c2a2..3cc37def9 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# AngularJS Full-Stack generator [![Build Status](https://travis-ci.org/DaftMonk/generator-angular-fullstack.svg?branch=master)](http://travis-ci.org/DaftMonk/generator-angular-fullstack) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/DaftMonk/generator-angular-fullstack) +# AngularJS Full-Stack generator [![Build Status](https://travis-ci.org/DaftMonk/generator-angular-fullstack.svg?branch=master)](http://travis-ci.org/DaftMonk/generator-angular-fullstack) > Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node - lets you quickly set up a project following best practices. @@ -78,6 +78,7 @@ Available generators: * Deployment - [angular-fullstack:openshift](#openshift) - [angular-fullstack:heroku](#heroku) + - [angular-fullstack:cloudfoundry](#cloudfoundry) ### App Sets up a new AngularJS + Express app, generating all the boilerplate you need to get started. @@ -291,6 +292,36 @@ Commit and push the resulting build, located in your dist folder: grunt buildcontrol:heroku +### Cloud Foundry / Pivotal Web Services + +Deploying to Cloud Foundry can be done with these steps. + + yo angular-fullstack:cloudfoundry + +To work with your new Cloud Foundry app using the command line, you will need to run any `cf` commands from the `dist` folder. + + +If you're using mongoDB you will need to create a service (MongoLab) and bind it to your app: + + cf create-service mongolab sandbox my-mongo + cf bind-service my-app my-mongo + +> +> If you're using any oAuth strategies, you must set environment variables for your selected oAuth. For example, if we're using **Facebook** oAuth we would do this : +> +> cf set-env my-app FACEBOOK_ID id +> cf set-env my-app FACEBOOK_SECRET secret +> + +#### Pushing Updates + + grunt + +Deploy the resulting build, from your `dist` folder: + + cf push + + ## Bower Components The following packages are always installed by the [app](#app) generator: From c9b05bad7356ee64f611d1825deca0a30e8d0d53 Mon Sep 17 00:00:00 2001 From: Greg Ziebold Date: Fri, 3 Oct 2014 23:37:23 -0600 Subject: [PATCH 4/6] feat(gen:cloudfoundry): disable cf deploy tests (for travis) and clean up for JavaScript Code Style checker --- Gruntfile.js | 3 ++- app/templates/server/config/environment/production.js | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index c81bffa5c..d98b8a089 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -66,7 +66,8 @@ module.exports = function (grunt) { mochaTest: { test: { src: [ - 'test/*.js' + 'test/*.js', + '!test/cf-test-creation.js' ], options: { reporter: 'spec', diff --git a/app/templates/server/config/environment/production.js b/app/templates/server/config/environment/production.js index 24c51ea3e..80595dc9c 100644 --- a/app/templates/server/config/environment/production.js +++ b/app/templates/server/config/environment/production.js @@ -5,10 +5,10 @@ // cloud foundry var getCfMongo = function() { - var vcap_services = JSON.parse(process.env.VCAP_SERVICES), - mongoUri; - if (vcap_services.mongolab && vcap_services.mongolab.length > 0) { - mongoUri = vcap_services.mongolab[0].credentials.uri; + var vcapServices = JSON.parse(process.env.vcapServices); + var mongoUri; + if (vcapServices.mongolab && vcapServices.mongolab.length > 0) { + mongoUri = vcapServices.mongolab[0].credentials.uri; } return mongoUri; }; @@ -34,4 +34,4 @@ module.exports = { getCfMongo() || 'mongodb://localhost/<%= _.slugify(appname) %>' } -}; \ No newline at end of file +}; From be9041b601aa32837898e194664e313d6006bc0e Mon Sep 17 00:00:00 2001 From: Greg Ziebold Date: Wed, 8 Oct 2014 12:54:53 -0600 Subject: [PATCH 5/6] replace gitter badge --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 3cc37def9..73b77ab9c 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# AngularJS Full-Stack generator [![Build Status](https://travis-ci.org/DaftMonk/generator-angular-fullstack.svg?branch=master)](http://travis-ci.org/DaftMonk/generator-angular-fullstack) +# AngularJS Full-Stack generator [![Build Status](https://travis-ci.org/DaftMonk/generator-angular-fullstack.svg?branch=master)](http://travis-ci.org/DaftMonk/generator-angular-fullstack) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/DaftMonk/generator-angular-fullstack) > Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node - lets you quickly set up a project following best practices. From 2b6c7105f345ca87d3531637b8a984d43a74dd91 Mon Sep 17 00:00:00 2001 From: Greg Ziebold Date: Wed, 8 Oct 2014 12:54:53 -0600 Subject: [PATCH 6/6] feat(gen:cloudfoundry): replace gitter badge --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 3cc37def9..73b77ab9c 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# AngularJS Full-Stack generator [![Build Status](https://travis-ci.org/DaftMonk/generator-angular-fullstack.svg?branch=master)](http://travis-ci.org/DaftMonk/generator-angular-fullstack) +# AngularJS Full-Stack generator [![Build Status](https://travis-ci.org/DaftMonk/generator-angular-fullstack.svg?branch=master)](http://travis-ci.org/DaftMonk/generator-angular-fullstack) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/DaftMonk/generator-angular-fullstack) > Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node - lets you quickly set up a project following best practices.