forked from GoogleChrome/workbox
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgulpfile.babel.js
More file actions
211 lines (186 loc) · 6.98 KB
/
gulpfile.babel.js
File metadata and controls
211 lines (186 loc) · 6.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
Copyright 2016 Google Inc. All Rights Reserved.
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.
*/
import eslint from 'gulp-eslint';
import express from 'express';
import gulp from 'gulp';
import handlebars from 'gulp-compile-handlebars';
import minimist from 'minimist';
import mocha from 'gulp-mocha';
import npmPath from 'npm-path';
import path from 'path';
import promisify from 'promisify-node';
import rename from 'gulp-rename';
import runSequence from 'run-sequence';
import serveIndex from 'serve-index';
import serveStatic from 'serve-static';
import {globPromise, processPromiseWrapper, taskHarness} from './build-utils.js';
const fsePromise = promisify('fs-extra');
const tmpPromise = promisify('tmp');
const options = minimist(process.argv.slice(2));
const projectOrStar = options.project || '*';
// Before doing anything, modify process.env.PATH so the the ChromeDriver
// and documentation binaries in node_modules/.bin are picked up.
npmPath.setSync();
/**
* Lints a given project.
* @param project The path to a project directory.
* @returns {Promise} Resolves if linting succeeds, rejects if it fails.
*/
const lintPackage = project => {
return new Promise((resolve, reject) => {
gulp.src([`${project}/**/*.js`, `!${project}/**/build/**`])
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.results(results => {
if ((results.warningCount + results.errorCount) > 0) {
reject(`Linting '${project}' failed.`);
} else {
resolve();
}
}));
});
};
/**
* Buids a given project.
* @param project The path to a project directory.
* @returns {Promise} Resolves if building succeeds, rejects if it fails.
*/
const buildPackage = project => {
const buildDir = `${project}/build`;
// Copy over package.json and README.md so that build/ contains what we
// need to publish to npm.
return fsePromise.emptyDir(buildDir)
.then(() => fsePromise.copy(`${project}/package.json`,
`${buildDir}/package.json`))
.then(() => fsePromise.copy(`${project}/README.md`,
`${buildDir}/README.md`))
.then(() => {
// Let each project define its own build process.
const build = require(`./${project}/build.js`);
return build();
});
};
/**
* Documents a given project.
* @param project The path to a project directory.
* @returns {Promise} Resolves if documenting succeeds, rejects if it fails.
*/
const documentPackage = project => {
const projectMetadata = require(`./${project}/package.json`);
return new Promise(resolve => {
// First, use metadata from package.json to write out an initial README.md.
gulp.src('templates/Project-README.hbs')
.pipe(handlebars({
name: projectMetadata.name,
description: projectMetadata.description,
background: projectMetadata.background
}))
.pipe(rename('README.md'))
.pipe(gulp.dest(project))
.on('end', resolve);
}).then(() => {
// Then use the inline JSDoc to populate the "API" section.
return globPromise(`${project}/src/**/*.js`).then(files => {
const args = ['readme', ...files, '--github', '--section', 'API',
'--readme-file', `${project}/README.md`];
return processPromiseWrapper('documentation', args);
});
});
};
/**
* Publishes a given project to npm.
* @param project The path to a project directory.
* @returns {Promise} Resolves if publishing succeeds, rejects if it fails.
*/
const publishPackage = project => {
return processPromiseWrapper('npm', ['publish', `${project}/build`]);
};
gulp.task('lint', () => {
return taskHarness(lintPackage, projectOrStar);
});
gulp.task('test', () => {
return gulp.src(`projects/${projectOrStar}/test/*.js`, {read: false})
.pipe(mocha())
.once('error', () => {
process.exit(1);
});
});
gulp.task('build', () => {
return taskHarness(buildPackage, projectOrStar);
});
gulp.task('build:watch', unusedCallback => {
gulp.watch(`projects/${projectOrStar}/src/**/*`, ['build']);
gulp.watch(`lib/**/*`, ['build']);
});
gulp.task('serve', unusedCallback => {
const port = options.port || 3000;
const app = express();
const rootDirectory = projectOrStar === '*' ?
'projects' :
path.join('projects', projectOrStar);
app.use(serveStatic(rootDirectory));
app.use(serveIndex(rootDirectory, {view: 'details'}));
app.listen(port, () => {
console.log(`Serving '${rootDirectory}' at http://localhost:${port}/`);
});
});
gulp.task('documentation:projects', () => {
return taskHarness(documentPackage, projectOrStar);
});
gulp.task('documentation:repo', ['build'], () => {
if (projectOrStar !== '*') {
throw Error('Please do not use --project= with documentation:repo.');
}
return new Promise(resolve => {
// First, generate a repo README.md based on metadata from each project.
return globPromise('projects/*/package.json')
.then(pkgs => pkgs.map(pkg => require(`./${pkg}`)))
.then(projects => {
gulp.src('templates/README.hbs')
.pipe(handlebars({projects: projects}))
.pipe(rename({extname: '.md'}))
.pipe(gulp.dest('.'))
.on('end', resolve);
});
}).then(() => {
// The gh-pages module ends up pulling in https://www.npmjs.com/package/collections
// which in turn breaks the native Array.filter() implementation in some
// versions of Node, triggering a bug in selenium-webdriver (sigh).
// To work around this, only pull in gh-pages when it's needed, rather than
// globally at the top of this file.
const ghPagesPromise = promisify('gh-pages');
// Then publish all of the build + demo files to gh-pages.
return tmpPromise.dir().then(tmpDir => {
return new Promise(resolve => {
gulp.src('projects/*/{build,demo}/**')
.pipe(gulp.dest(tmpDir))
.on('end', resolve);
}).then(() => ghPagesPromise.publish(tmpDir));
});
});
});
gulp.task('documentation', ['documentation:repo', 'documentation:projects']);
gulp.task('publish', callback => {
if (projectOrStar === '*') {
throw Error('Please use the --project= parameter to specify a project.');
}
// We need things run in a specific sequence: the project-level documentation
// needs to be created before build, so that the correct README.md is copied
// over to the build/ directory.
runSequence(['lint', 'test'], 'documentation:projects', 'build', () => {
return taskHarness(publishPackage, projectOrStar).then(() => callback());
});
});
gulp.task('default', callback => {
runSequence(['lint', 'test'], 'documentation', callback);
});