1 | var _ = require('lodash'),
|
2 | AWS = require('aws-sdk'),
|
3 | cfValidate = require('./lib/gulp-cf-validate'),
|
4 | cutil = require('./lib/util'),
|
5 | rimraf = require('rimraf'),
|
6 | es = require('event-stream'),
|
7 | cache = require('gulp-cached'),
|
8 | gulpif = require('gulp-if'),
|
9 | gutil = require('gulp-util'),
|
10 | Handlebars = require('handlebars'),
|
11 | jsonlint = require('gulp-jsonlint'),
|
12 | jsonFormat = require('gulp-json-format'),
|
13 | lazypipe = require('lazypipe'),
|
14 | matter = require('gray-matter'),
|
15 | merge = require('merge-stream'),
|
16 | ParticleLoader = require('./lib/particle-loader'),
|
17 | path = require('path'),
|
18 | rename = require('gulp-rename'),
|
19 |
|
20 | through = require('through2');
|
21 |
|
22 | var DEFAULT_S3_PREFIX = exports.DEFAULT_S3_PREFIX = '';
|
23 | var DEFAULT_TASK_PREFIX = exports.DEFAULT_TASK_PREFIX = 'condensation';
|
24 | var PARTICLES_DIR = exports.PARTICLES_DIR = 'particles';
|
25 | var DEFAULT_ROOT = exports.DEFAULT_ROOT = './';
|
26 |
|
27 | var 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 |
|
52 | Condensation.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 |
|
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 |
|
173 |
|
174 | }
|
175 | });
|
176 | });
|
177 |
|
178 |
|
179 |
|
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 |
|
197 | Key: newFilename,
|
198 | Body: file.contents
|
199 | },function(err,response) {
|
200 | if (err) {
|
201 |
|
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 |
|
227 | gulp.task(self.genTaskName('clean'), function (cb) {
|
228 | rimraf(options.dist, cb);
|
229 | });
|
230 |
|
231 |
|
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 |
|
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 |
|
255 | module.exports.buildTasks = function(gulp,options) {
|
256 | return new Condensation(gulp,options);
|
257 | };
|