UNPKG

7.51 kBJavaScriptView Raw
1var _ = require('lodash'),
2AWS = require('aws-sdk'),
3cfValidate = require('./lib/gulp-cf-validate'),
4cutil = require('./lib/util'),
5rimraf = require('rimraf'),
6es = require('event-stream'),
7cache = require('gulp-cached'),
8gulpif = require('gulp-if'),
9gutil = require('gulp-util'),
10Handlebars = require('handlebars'),
11jsonlint = require('gulp-jsonlint'),
12jsonFormat = require('gulp-json-format'),
13lazypipe = require('lazypipe'),
14matter = require('gray-matter'),
15merge = require('merge-stream'),
16ParticleLoader = require('./lib/particle-loader'),
17path = require('path'),
18rename = require('gulp-rename'),
19
20through = require('through2');
21
22var DEFAULT_S3_PREFIX = exports.DEFAULT_S3_PREFIX = '';
23var DEFAULT_TASK_PREFIX = exports.DEFAULT_TASK_PREFIX = 'condensation';
24var PARTICLES_DIR = exports.PARTICLES_DIR = 'particles';
25var DEFAULT_ROOT = exports.DEFAULT_ROOT = './';
26
27var Condensation = function(gulp,options) {
28 this.gulp = gulp;
29 this.handlebars = Handlebars.create();
30 this.options = _.merge({
31 s3: [],
32 dist: 'dist',
33 root: DEFAULT_ROOT,
34 dependencySrc: [],
35 taskPrefix: DEFAULT_TASK_PREFIX
36 },options);
37 this.options.projectFullPath = path.join(process.cwd(),this.options.root);
38 this.options.particlesDir = path.join(this.options.root,PARTICLES_DIR);
39
40 if (!this.options.projectName) {
41 try { this.options.projectName = require(path.join(process.cwd(),'package.json')).name; } catch(e) {}
42 }
43
44 this.particleLoader = new ParticleLoader({
45 root: this.options.root
46 });
47 this.genTaskName = cutil.genTaskNameFunc({prefix:this.options.taskPrefix});
48 this.condense();
49};
50
51
52Condensation.prototype.condense = function() {
53 var self = this;
54 var options = this.options;
55
56 var gulp = this.gulp || require('gulp');
57
58 var helpers = require('./lib/template-helpers')({
59 particleLoader: this.particleLoader,
60 handlebars: this.handlebars
61 });
62
63 var buildTasks = [];
64 var deployTasks = [];
65 var labelTasks = {};
66
67 var s3config = options.s3 || [];
68
69
70 _.each(s3config, function(s3opts,i) {
71 s3opts = _.merge({
72 prefix: '',
73 labels: []
74 },s3opts);
75
76 var templateData = {};
77 var s3 = new AWS.S3({region: s3opts.aws.region});
78 var genDistPath = cutil.genDistPathFunc({
79 id: i.toString(),
80 s3prefix: s3opts.prefix,
81 root: options.dist
82 });
83
84
85 templateData.s3 = s3opts.aws;
86 templateData.s3.awsPath = s3.endpoint.href+path.join(s3opts.aws.bucket,s3opts.prefix);
87
88 gulp.task(self.genTaskName('build',i),[self.genTaskName('clean:errors')],function() {
89
90
91 var stream = es.readable(function(esCount,cb) {
92 var readable = this;
93
94 var totalCount = 0;
95 var lastTotalCount = 0;
96
97 var runStreams = function(globs,options) {
98 var s = gulp.src(globs,options)
99 .pipe(cache(self.options.projectName+i))
100 .pipe(gulpif(/\.hbs$/,through.obj(function(file,enc,cb) {
101 var m = matter(file.contents.toString());
102 var fn = self.handlebars.compile(m.content);
103 file.contents = new Buffer(fn(_.merge(_.merge(m.data,templateData),{_file: file})));
104 cb(null,file);
105 })))
106 .pipe(through.obj(function(file,enc,cb) {
107 totalCount = totalCount + 1;
108 readable.emit('data',file);
109 cb(null,file);
110 }));
111 s.on('data',function(){});
112 s.on('end',function() {
113 if (lastTotalCount === totalCount) {
114 readable.emit('end');
115 cb();
116 }
117 else {
118 var paths = _.invoke(
119 self.particleLoader.processablePaths(),
120 function() {
121 return this+"?(.hbs)";
122 }
123 );
124
125 lastTotalCount = totalCount;
126 runStreams(paths,{base:self.options.root});
127 }
128 });
129 };
130
131 runStreams(["particles/cftemplates/**"],{cwd:self.options.root,base:self.options.root});
132 });
133
134
135 var templateChannel = lazypipe()
136 .pipe(jsonlint)
137 .pipe(jsonlint.reporter)
138 .pipe(function() {
139 return jsonFormat(2);
140 })
141 .pipe(function() {
142 return gulpif(
143 s3opts.validate,
144 cfValidate({region: s3opts.aws.region})
145 )
146 });
147
148 stream = stream
149 .pipe(gulpif(/\.hbs$/,rename({extname:""})))
150 .pipe(gulpif(/cftemplates[\/\\]/,templateChannel()))
151 .pipe(gulp.dest(genDistPath()));
152
153 return stream;
154
155 });
156
157 buildTasks.push(self.genTaskName('build',i));
158
159
160 // Ensure the bucket(s) defined in the config exist
161 gulp.task(self.genTaskName('s3','bucket','ensure',i),function(cb) {
162 s3.headBucket({
163 Bucket: s3opts.aws.bucket
164 },function(err,response){
165 if (err && err.code === 'NotFound' && s3opts.create) {
166 s3.createBucket({
167 Bucket: s3opts.aws.bucket
168 },cb);
169 }
170 else {
171 cb(null,response);
172 //TODO Removed for cross account access. Need to revisit s3 bucket permissions and correct fallback
173 // cb(err,data);
174 }
175 });
176 });
177
178
179 // Write objects to s3
180 gulp.task(
181 self.genTaskName('s3','objects','write',i),
182 [
183 self.genTaskName('s3','bucket','ensure',i),
184 self.genTaskName('build',i)
185 ],
186 function() {
187 var streams = [];
188 _.each([path.join(options.dist,i.toString()),path.join(options.dist,'shared')],function(srcDir) {
189 var stream = gulp.src("**",{cwd:srcDir}).on("data",function(file) {
190 if (file.stat.isFile()) {
191 var newFilename = file.relative;
192
193 s3.putObject({
194 Bucket: s3opts.aws.bucket,
195 ACL: "bucket-owner-full-control",
196 //ACL: "private",
197 Key: newFilename,
198 Body: file.contents
199 },function(err,response) {
200 if (err) {
201 // TODO throw error
202 console.warn(err,response);
203 }
204 });
205 }
206 });
207 streams.push(stream);
208 });
209 return merge.apply(null,streams);
210 });
211
212 gulp.task(self.genTaskName('deploy',i),[self.genTaskName('s3','objects','write',i)]);
213 deployTasks.push(self.genTaskName('deploy',i));
214
215 _.each(s3opts.labels,function(label) {
216 labelTasks[label] = labelTasks[label] || {
217 buildTasks: [],
218 deployTasks: []
219 };
220 labelTasks[label].buildTasks.push(self.genTaskName('build',i));
221 labelTasks[label].deployTasks.push(self.genTaskName('deploy',i));
222 });
223
224 });
225
226 // Remove all files from 'dist'
227 gulp.task(self.genTaskName('clean'), function (cb) {
228 rimraf(options.dist, cb);
229 });
230
231 // Remove errors directory
232 gulp.task(self.genTaskName('clean:errors'), function (cb) {
233 rimraf('condensation_errors', cb);
234 });
235
236 gulp.task(self.genTaskName('s3','list'), function(cb) {
237 _.each(s3config, function(s3opts,i) {
238 gutil.log(i + ": " + s3opts.aws.bucket);
239 });
240 cb();
241 });
242
243
244 // Tasks to launch other tasks
245 gulp.task(self.genTaskName('build'),buildTasks);
246 gulp.task(self.genTaskName('deploy'), deployTasks);
247 gulp.task(self.genTaskName('default'),[self.genTaskName('build')]);
248 _.each(_.pairs(labelTasks),function(kv) {
249 gulp.task(self.genTaskName('build',kv[0]),kv[1].buildTasks);
250 gulp.task(self.genTaskName('deploy',kv[0]),kv[1].deployTasks);
251 });
252
253};
254
255module.exports.buildTasks = function(gulp,options) {
256 return new Condensation(gulp,options);
257};