Skip to content

Instantly share code, notes, and snippets.

@joshmatz
Last active November 25, 2016 07:52
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save joshmatz/d8214df523b0a561cdc5 to your computer and use it in GitHub Desktop.
Save joshmatz/d8214df523b0a561cdc5 to your computer and use it in GitHub Desktop.
  • grunt serve

  • grunt serve:dist

  • grunt serve:dist --api=qa

  • grunt test

  • grunt test:jshint

  • grunt test:e2e.update

  • grunt test:e2e.start

  • grunt test:e2e

  • grunt test:suite

  • grunt deploy

  • grunt deploy:staging

// Generated on 2014-07-08 using generator-angular 0.9.3
'use strict';
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'
var modRewrite = require('connect-modrewrite');
module.exports = function (grunt) {
/**
* Allow the ability to switch between local API and QA API.
*/
var api = grunt.option('api'),
apiHost = grunt.option('apiHost'),
apiPort = grunt.option('apiPort');
if (typeof apiHost !== 'string') {
apiHost = 'localhost';
}
if (typeof apiPort !== 'number') {
apiPort = 8080;
}
if(typeof api === 'boolean') {
console.warn('No API set. Using default localhost option.');
}
if (api === 'qa') {
apiHost = 'your-api-server.com';
apiPort = 80;
}
/**
* Continue Configuration
*/
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
// Configurable paths for the application
var appConfig = {
app: require('./bower.json').appPath || 'app',
dist: 'dist'
};
// Define the configuration for all the tasks
grunt.initConfig({
// Project settings
yeoman: appConfig,
// Watches files for changes and runs tasks based on the changed files
watch: {
bower: {
files: ['bower.json'],
tasks: ['wiredep']
},
js: {
files: ['<%= yeoman.app %>/scripts/**/*.js', '!<%= yeoman.app %>/scripts/**/*.test.js'],
tasks: ['newer:jshint:all'],
options: {
livereload: '<%= connect.options.livereload %>'
}
},
jsTest: {
files: ['<%= yeoman.app %>/scripts/**/*.test.js', 'test/e2e/**/*.js', 'test/karma.conf.js', 'test/protractor.conf.js'],
tasks: ['newer:jshint:test']
},
html: {
files: ['<%= yeoman.app %>/**/*.html'],
tasks: ['ngtemplates:serve'],
options: {
livereload: '<%= connect.options.livereload %>'
}
},
sass: {
files: ['<%= yeoman.app %>/**/*.{scss,sass}'],
tasks: ['sass:server', 'autoprefixer']
},
gruntfile: {
files: ['Gruntfile.js']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= yeoman.app %>/**/*.html',
'.tmp/styles/{,*/}*.css',
'<%= yeoman.app %>/images/**/*.{png,jpg,jpeg,gif,webp,svg}'
]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
require('grunt-connect-proxy/lib/utils').proxyRequest,
modRewrite(['!/api|\\.jpg|\\.gif|\\.png|\\.svg|\\.woff2|\\.eot|\\.html|\\.js|\\.css|\\.woff|\\.ttf|\\.swf$ /index.html [L]']),
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app)
];
}
},
proxies: {
context: '/api',
host: apiHost,
port: apiPort,
changeOrgin: true
}
},
test: {
options: {
port: 9001,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect.static('test'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app)
];
}
}
},
dist: {
options: {
open: true,
middleware: function (connect) {
var proxy = require('grunt-connect-proxy/lib/utils').proxyRequest;
return [
// Include the proxy first
proxy,
modRewrite(['!/api|\\.jpg|\\.gif|\\png|\\.svg|\\.woff2|\\.eot|\\.html|\\.js|\\.css|\\.woff|\\.ttf|\\.swf$ /index.html [L]']),
// Serve static files.
connect.static(appConfig.dist)
];
}
},
proxies: [{
context: '/api',
host: apiHost,
port: apiPort,
changeOrgin: true
}]
}
},
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: {
src: [
'Gruntfile.js',
'<%= yeoman.app %>/scripts/**/*.js',
'!<%= yeoman.app %>/scripts/**/*.test.js'
]
},
test: {
options: {
jshintrc: 'test/.jshintrc'
},
src: [
'<%= yeoman.app %>/scripts/**/*.test.js',
'test/e2e/**/*.js',
'test/karma.conf.js',
'test/protractor.conf.js'
]
}
},
// html linting with good angular support
// https://github.com/nikestep/grunt-html-angular-validate
htmlangular: {
options: {
},
all: {
src: [
'<%= yeoman.app %>/**/*.html'
]
}
},
ngtemplates: {
options: {
module: 'SourceClear',
url: function (templateString) {
return '/' + templateString;
}
},
serve: {
cwd: '<%= yeoman.app %>/',
src: [
'**/*.html',
'!index.html',
'!404.html'
],
dest: '.tmp/scripts/templates.js',
options: {
}
},
dist: {
cwd: '<%= yeoman.app %>/',
src: [
'**/*.html',
'!index.html',
'!404.html'
],
dest: '.tmp/scripts/templates.js',
options: {
usemin: '/scripts/app.js' // <~~ This came from the <!-- build:js --> block
}
}
},
injector: {
options: {
ignorePath: '<%= yeoman.app %>/'
},
localDependencies: {
files: {
'<%= yeoman.app %>/index.html': [
'<%= yeoman.app %>/**/*.js',
'!<%= yeoman.app %>/**/*.test.js', // no tests in client... duh
'!<%= yeoman.app %>/scripts/segment.js' // any files in our <head> area
],
}
}
},
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= yeoman.dist %>'
]
}]
},
server: '.tmp'
},
// Add vendor prefixed styles
autoprefixer: {
options: {
browsers: ['last 3 versions', 'ie 8', 'ie 9']
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
}
},
// Automatically inject Bower components into the app
wiredep: {
options: {
},
app: {
src: ['<%= yeoman.app %>/index.html'],
exclude: ['bower_components/bootstrap-sass-official', 'sourceclear-style-guide'],
ignorePath: /\.\./ // removes ".."
},
sass: {
src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
ignorePath: /(\.\.\/){1,2}bower_components\// // removes "../bower_components"
}
},
// Compiles sass to CSS and generates necessary files if requested
sass: {
options: {
// libsassDir: '<%= yeoman.app %>/styles',
// cssDir: '.tmp/styles',
// generatedImagesDir: '.tmp/images/generated',
// imagesDir: '<%= yeoman.app %>/images',
// javascriptsDir: '<%= yeoman.app %>/scripts',
// fontsDir: '<%= yeoman.app %>/styles/fonts',
// importPath: './bower_components',
// httpImagesPath: '/images',
// httpGeneratedImagesPath: '/images/generated',
// httpFontsPath: '/styles/fonts',
// relativeAssets: false,
// assetCacheBuster: false,
// raw: 'sass::Script::Number.precision = 10\n'
precision: 10,
update: true
},
dist: {
options: {
sourceMap: true
},
files: {
'.tmp/styles/main.css': '<%= yeoman.app %>/styles/main.scss'
}
},
server: {
options: {
debugInfo: true
},
files: {
'.tmp/styles/main.css': '<%= yeoman.app %>/styles/main.scss'
}
}
},
// Renames files for browser caching purposes
filerev: {
dist: {
src: [
'.tmp/scripts/templates.js',
'<%= yeoman.dist %>/scripts/{,*/}*.js',
'<%= yeoman.dist %>/styles/{,*/}*.css',
'<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
'<%= yeoman.dist %>/styles/fonts/*'
]
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
html: '<%= yeoman.app %>/**/*.html',
options: {
dest: '<%= yeoman.dist %>'
}
},
// Performs rewrites based on filerev and the useminPrepare configuration
usemin: {
html: ['<%= yeoman.dist %>/**/*.html'],
js: ['<%= yeoman.dist %>/**/*.js'],
css: ['<%= yeoman.dist %>/**/*.css'],
options: {
assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images'],
patterns: {
// FIXME While usemin won't have full support for revved files we have to put all references manually here
js: [
[/(images\/.*?\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the JS to reference our revved images']
]
}
}
},
// The following *-min tasks will produce minified files in the dist folder
// By default, your `index.html`'s <!-- Usemin block --> will take care of
// minification. These next options are pre-configured if you do not wish
// to use the Usemin blocks.
// cssmin: {
// dist: {
// files: {
// '<%= yeoman.dist %>/styles/main.css': [
// '.tmp/styles/{,*/}*.css'
// ]
// }
// }
// },
uglify: {
options: {
mangle: false
}
},
// concat: {
// dist: {}
// },
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.{png,jpg,jpeg,gif}',
dest: '<%= yeoman.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.svg',
dest: '<%= yeoman.dist %>/images'
}]
}
},
htmlmin: {
dist: {
options: {
collapseWhitespace: true,
conservativeCollapse: true,
collapseBooleanAttributes: true,
removeCommentsFromCDATA: true,
removeOptionalTags: true
},
files: [{
expand: true,
cwd: '<%= yeoman.dist %>',
src: ['*.html', 'views/{,*/}*.html'],
dest: '<%= yeoman.dist %>'
}]
}
},
// ngAnnotate adds, removes, and rebuilds angularjs dependency injection annotations
ngAnnotate: {
options: {
singleQuotes: true
},
app: {
files: [
{
expand: true,
src: ['<%= yeoman.app %>/**/*.js', '!<%= yeoman.app %>/**/*.test.js'],
dest: '.tmp'
}
]
}
},
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'index.html',
'404.html',
'images/{,*/}*.{webp}',
'fonts/**/*'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dist %>/images',
src: ['generated/*']
}, {
expand: true,
cwd: './bower_components/components-font-awesome/fonts',
src: '*',
dest: '<%= yeoman.dist %>/fonts'
}]
}
},
// Run some tasks in parallel to speed up the build process
concurrent: {
server: [
'sass:server'
],
test: [
'sass'
],
dist: [
'sass:dist',
'imagemin',
'svgmin'
]
},
// Test settings
karma: {
unit: {
configFile: 'test/karma.conf.js',
singleRun: true
}
},
buildcontrol: {
options: {
dir: 'dist',
commit: true,
push: true,
message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
},
staging: {
options: {
remote: 'git@github.com:sourceclear/app.sourceclear.com-frontend.git',
branch: 'staging'
}
},
release: {
options: {
remote: 'git@github.com:sourceclear/app.sourceclear.com-frontend.git',
branch: 'release'
}
}
},
bump: {
options: {
files: ['package.json'],
updateConfigs: [],
commit: true,
commitMessage: 'Release v%VERSION%',
commitFiles: ['package.json'],
createTag: true,
tagName: 'v%VERSION%',
tagMessage: 'Version %VERSION%',
push: true,
pushTo: 'origin',
gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d'
}
},
exec: {
// Download and update webdriver-manager script within protractor node module
updateWebDriverManager: './node_modules/protractor/bin/webdriver-manager update',
// Start webdriver-manager server
startWebDriverManager: './node_modules/protractor/bin/webdriver-manager start',
// Run protractor e2e tests
runProtractor: './node_modules/protractor/bin/protractor test/protractor.conf.js'
}
});
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'injector',
'configureProxies:livereload',
'wiredep',
'concurrent:server',
'ngtemplates:serve',
'autoprefixer',
'connect:livereload',
'watch'
]);
});
grunt.registerTask('test', 'Execute tests', function (target) {
// Update webdriver-manager on 'grunt test:e2e.update'
if (target === 'e2e.update') {
return grunt.task.run(['exec:updateWebDriverManager']);
}
// Start webdriver-manager on 'grunt test:e2e.start'
if (target === 'e2e.start') {
return grunt.task.run(['exec:startWebDriverManager']);
}
// Execute karma unit tests on 'grunt test' or 'grunt test:suite'
if (typeof target === 'undefined' || target === 'suite') {
grunt.task.run([
'clean:server',
'injector',
'concurrent:test',
'autoprefixer',
'connect:test',
'karma'
]);
}
// Execute protractor e2e tests on 'grunt test:e2e' or 'grunt test:suite'
if (target === 'e2e' || target === 'suite') {
grunt.task.run(['exec:runProtractor']);
}
// Execute jshint on 'grunt test:jshint' or 'grunt test:suite'
if (target === 'jshint' || target === 'suite') {
grunt.task.run(['newer:jshint']);
}
});
grunt.registerTask('build', [
'clean:dist',
'configureProxies:dist',
'wiredep',
'ngAnnotate',
'injector',
'concurrent:dist',
'useminPrepare',
'ngtemplates:dist',
'autoprefixer',
'concat',
'copy:dist',
'cssmin',
'uglify',
'filerev',
'usemin',
'htmlmin'
]);
/**
* Use:
* grunt deploy:target --force
* @param {string} target matches what follows deploy:*
*/
grunt.registerTask('deploy', 'Test, build, then git deploy', function (target) {
// returns true if included but not set to anything in particular
var force = grunt.option('force');
/*
Don't allow forced deploys to prod... for now.
*/
if(force) {
return grunt.task.run(['build', 'buildcontrol:staging']);
}
if(target === 'prod') {
grunt.task.run([
'test:suite',
'build',
'buildcontrol:' + target
]);
} else {
grunt.task.run([
'test:suite',
'build',
'buildcontrol:' + target
]);
}
});
};
{
"name": "Your Project",
"version": "0.0.1",
"repository": {
"type": "git",
"url": "https://github.com/owner/project.git"
},
"dependencies": {},
"devDependencies": {
"connect": "^3.0.2",
"connect-modrewrite": "^0.7.6",
"grunt": "^0.4.1",
"grunt-angular-templates": "^0.5.7",
"grunt-autoprefixer": "^0.7.3",
"grunt-build-control": "^0.1.3",
"grunt-bump": "0.0.15",
"grunt-concurrent": "^0.5.0",
"grunt-connect-proxy": "^0.1.10",
"grunt-contrib-clean": "^0.5.0",
"grunt-contrib-concat": "^0.4.0",
"grunt-contrib-connect": "^0.7.1",
"grunt-contrib-copy": "^0.5.0",
"grunt-contrib-cssmin": "^0.9.0",
"grunt-contrib-htmlmin": "^0.3.0",
"grunt-contrib-imagemin": "^0.7.0",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-uglify": "^0.4.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-exec": "^0.4.6",
"grunt-filerev": "^0.2.1",
"grunt-google-cdn": "^0.4.0",
"grunt-html-angular-validate": "^0.4.0",
"grunt-injector": "^0.6.0",
"grunt-karma": "^0.8.3",
"grunt-modernizr": "^0.5.2",
"grunt-newer": "^0.7.0",
"grunt-ng-annotate": "^0.3.0",
"grunt-sass": "^0.18.0",
"grunt-svgmin": "^0.4.0",
"grunt-usemin": "^2.1.1",
"grunt-wiredep": "^1.7.0",
"jshint-stylish": "^0.2.0",
"karma-chrome-launcher": "^0.1.4",
"karma-coverage": "^0.2.5",
"karma-jasmine": "^0.3.4",
"karma-ng-html2js-preprocessor": "^0.1.0",
"karma-ng-scenario": "^0.1.0",
"load-grunt-tasks": "^0.4.0",
"protractor": "1.4.0",
"time-grunt": "^0.3.1"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "grunt test"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment