Skip to content

Commit 1ec1737

Browse files
committedDec 14, 2019
test/style: refactor remaining grunt tasks to use promises instead of callbacks
1 parent 1ebce2b commit 1ec1737

File tree

4 files changed

+211
-259
lines changed

4 files changed

+211
-259
lines changed
 

‎tasks/metrics.js

+20-17
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
1-
const _ = require('underscore'),
2-
async = require('neo-async'),
3-
metrics = require('../bench');
1+
const metrics = require('../bench');
2+
const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task');
43

54
module.exports = function(grunt) {
6-
grunt.registerTask('metrics', function() {
7-
const done = this.async(),
8-
execName = grunt.option('name'),
9-
events = {};
5+
const registerAsyncTask = createRegisterAsyncTaskFn(grunt);
106

11-
async.each(
12-
_.keys(metrics),
13-
function(name, complete) {
14-
if (/^_/.test(name) || (execName && name !== execName)) {
15-
return complete();
16-
}
7+
registerAsyncTask('metrics', function() {
8+
const onlyExecuteName = grunt.option('name');
9+
const events = {};
1710

11+
const promises = Object.keys(metrics).map(async name => {
12+
if (/^_/.test(name)) {
13+
return;
14+
}
15+
if (onlyExecuteName != null && name !== onlyExecuteName) {
16+
return;
17+
}
18+
19+
return new Promise(resolve => {
1820
metrics[name](grunt, function(data) {
1921
events[name] = data;
20-
complete();
22+
resolve();
2123
});
22-
},
23-
done
24-
);
24+
});
25+
});
26+
27+
return Promise.all(promises);
2528
});
2629
};

‎tasks/publish.js

+83-87
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,38 @@
1-
const _ = require('underscore'),
2-
async = require('neo-async'),
3-
AWS = require('aws-sdk'),
4-
git = require('./util/git'),
5-
semver = require('semver');
1+
const AWS = require('aws-sdk');
2+
const git = require('./util/git');
3+
const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task');
4+
const semver = require('semver');
65

76
module.exports = function(grunt) {
8-
grunt.registerTask('publish:latest', function() {
9-
const done = this.async();
10-
11-
git.debug(function(remotes, branches) {
12-
grunt.log.writeln('remotes: ' + remotes);
13-
grunt.log.writeln('branches: ' + branches);
14-
15-
git.commitInfo(function(err, info) {
16-
grunt.log.writeln('tag: ' + info.tagName);
17-
18-
const files = [];
19-
20-
// Publish the master as "latest" and with the commit-id
21-
if (info.isMaster) {
22-
files.push('-latest');
23-
files.push('-' + info.head);
24-
}
25-
26-
// Publish tags by their tag-name
27-
if (info.tagName && semver.valid(info.tagName)) {
28-
files.push('-' + info.tagName);
29-
}
30-
31-
if (files.length > 0) {
32-
initSDK();
33-
grunt.log.writeln('publishing files: ' + JSON.stringify(files));
34-
publish(fileMap(files), done);
35-
} else {
36-
// Silently ignore for branches
37-
done();
38-
}
39-
});
40-
});
41-
});
42-
grunt.registerTask('publish:version', function() {
43-
const done = this.async();
44-
initSDK();
7+
const registerAsyncTask = createRegisterAsyncTaskFn(grunt);
458

46-
git.commitInfo(function(err, info) {
47-
if (!info.tagName) {
48-
throw new Error('The current commit must be tagged');
49-
}
50-
publish(fileMap(['-' + info.tagName]), done);
51-
});
9+
registerAsyncTask('publish:latest', async () => {
10+
grunt.log.writeln('remotes: ' + (await git.remotes()));
11+
grunt.log.writeln('branches: ' + (await git.branches()));
12+
13+
const commitInfo = await git.commitInfo();
14+
grunt.log.writeln('tag: ' + commitInfo.tagName);
15+
16+
const suffixes = [];
17+
18+
// Publish the master as "latest" and with the commit-id
19+
if (commitInfo.isMaster) {
20+
suffixes.push('-latest');
21+
suffixes.push('-' + commitInfo.headSha);
22+
}
23+
24+
// Publish tags by their tag-name
25+
if (commitInfo.tagName && semver.valid(commitInfo.tagName)) {
26+
suffixes.push('-' + commitInfo.tagName);
27+
}
28+
29+
if (suffixes.length > 0) {
30+
initSDK();
31+
grunt.log.writeln(
32+
'publishing file-suffixes: ' + JSON.stringify(suffixes)
33+
);
34+
await publish(suffixes);
35+
}
5236
});
5337

5438
function initSDK() {
@@ -62,45 +46,57 @@ module.exports = function(grunt) {
6246

6347
AWS.config.update({ accessKeyId: key, secretAccessKey: secret });
6448
}
65-
function publish(files, callback) {
66-
const s3 = new AWS.S3(),
67-
bucket = process.env.S3_BUCKET_NAME;
68-
69-
async.each(
70-
_.keys(files),
71-
function(file, callback) {
72-
const params = {
73-
Bucket: bucket,
74-
Key: file,
75-
Body: grunt.file.read(files[file])
76-
};
77-
s3.putObject(params, function(err) {
78-
if (err) {
79-
throw err;
80-
} else {
81-
grunt.log.writeln('Published ' + file + ' to build server.');
82-
callback();
83-
}
84-
});
85-
},
86-
callback
87-
);
49+
50+
async function publish(suffixes) {
51+
const publishPromises = suffixes.map(suffix => publishSuffix(suffix));
52+
return Promise.all(publishPromises);
8853
}
89-
function fileMap(suffixes) {
90-
const map = {};
91-
_.each(
92-
[
93-
'handlebars.js',
94-
'handlebars.min.js',
95-
'handlebars.runtime.js',
96-
'handlebars.runtime.min.js'
97-
],
98-
function(file) {
99-
_.each(suffixes, function(suffix) {
100-
map[file.replace(/\.js$/, suffix + '.js')] = 'dist/' + file;
101-
});
102-
}
103-
);
104-
return map;
54+
55+
async function publishSuffix(suffix) {
56+
const filenames = [
57+
'handlebars.js',
58+
'handlebars.min.js',
59+
'handlebars.runtime.js',
60+
'handlebars.runtime.min.js'
61+
];
62+
const publishPromises = filenames.map(filename => {
63+
const nameInBucket = getNameInBucket(filename, suffix);
64+
const localFile = getLocalFile(filename);
65+
uploadToBucket(localFile, nameInBucket);
66+
grunt.log.writeln(
67+
`Published ${localFile} to build server (${nameInBucket})`
68+
);
69+
});
70+
return Promise.all(publishPromises);
71+
}
72+
73+
async function uploadToBucket(localFile, nameInBucket) {
74+
const bucket = process.env.S3_BUCKET_NAME;
75+
const uploadParams = {
76+
Bucket: bucket,
77+
Key: nameInBucket,
78+
Body: grunt.file.read(localFile)
79+
};
80+
return s3PutObject(uploadParams);
10581
}
10682
};
83+
84+
function s3PutObject(uploadParams) {
85+
const s3 = new AWS.S3();
86+
return new Promise((resolve, reject) => {
87+
s3.putObject(uploadParams, err => {
88+
if (err != null) {
89+
return reject(err);
90+
}
91+
resolve();
92+
});
93+
});
94+
}
95+
96+
function getNameInBucket(filename, suffix) {
97+
return filename.replace(/\.js$/, suffix + '.js');
98+
}
99+
100+
function getLocalFile(filename) {
101+
return 'dist/' + filename;
102+
}

‎tasks/util/git.js

+57-98
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,74 @@
11
const childProcess = require('child_process');
22

33
module.exports = {
4-
debug: function(callback) {
5-
childProcess.exec('git remote -v', {}, function(err, remotes) {
6-
if (err) {
7-
throw new Error('git.remote: ' + err.message);
8-
}
9-
10-
childProcess.exec('git branch -a', {}, function(err, branches) {
11-
if (err) {
12-
throw new Error('git.branch: ' + err.message);
13-
}
14-
15-
callback(remotes, branches);
16-
});
17-
});
4+
async remotes() {
5+
return git('remotes', '-v');
186
},
19-
clean: function(callback) {
20-
childProcess.exec('git diff-index --name-only HEAD --', {}, function(
21-
err,
22-
stdout
23-
) {
24-
callback(undefined, !err && !stdout);
25-
});
7+
async branches() {
8+
return git('branch', '-a');
269
},
27-
28-
commitInfo: function(callback) {
29-
module.exports.head(function(err, headSha) {
30-
module.exports.master(function(err, masterSha) {
31-
module.exports.tagName(function(err, tagName) {
32-
callback(undefined, {
33-
head: headSha,
34-
master: masterSha,
35-
tagName: tagName,
36-
isMaster: headSha === masterSha
37-
});
38-
});
39-
});
40-
});
10+
async clean() {
11+
const stdout = git('diff-index', '--name-only', 'HEAD', '--');
12+
return stdout === '';
4113
},
42-
43-
head: function(callback) {
44-
childProcess.exec('git rev-parse --short HEAD', {}, function(err, stdout) {
45-
if (err) {
46-
throw new Error('git.head: ' + err.message);
47-
}
48-
49-
callback(undefined, stdout.trim());
50-
});
14+
async commitInfo() {
15+
const headSha = await this.headSha();
16+
const masterSha = await this.masterSha();
17+
return {
18+
headSha,
19+
masterSha,
20+
tagName: await this.tagName(),
21+
isMaster: headSha === masterSha
22+
};
5123
},
52-
master: function(callback) {
53-
childProcess.exec('git rev-parse --short origin/master', {}, function(
54-
err,
55-
stdout
56-
) {
57-
// This will error if master was not checked out but in this case we know we are not master
58-
// so we can ignore.
59-
if (err && !/Needed a single revision/.test(err.message)) {
60-
throw new Error('git.master: ' + err.message);
61-
}
62-
63-
callback(undefined, stdout.trim());
64-
});
24+
async headSha() {
25+
const stdout = await git(' rev-parse', '--short', 'HEAD');
26+
return stdout.trim();
6527
},
66-
67-
add: function(path, callback) {
68-
childProcess.exec('git add -f ' + path, {}, function(err) {
69-
if (err) {
70-
throw new Error('git.add: ' + err.message);
28+
async masterSha() {
29+
try {
30+
const stdout = await git('rev-parse', '--short', 'origin/master');
31+
return stdout.trim();
32+
} catch (error) {
33+
if (/Needed a single revision/.test(error.message)) {
34+
// Master was not checked out but in this case, so we know we are not master. We can ignore this
35+
return '';
7136
}
72-
73-
callback();
74-
});
37+
throw error;
38+
}
7539
},
76-
commit: function(name, callback) {
77-
childProcess.exec('git commit --message=' + name, {}, function(err) {
78-
if (err) {
79-
throw new Error('git.commit: ' + err.message);
80-
}
8140

82-
callback();
83-
});
41+
async add(path) {
42+
return git('add', '-f', path);
8443
},
85-
tag: function(name, callback) {
86-
childProcess.exec('git tag -a --message=' + name + ' ' + name, {}, function(
87-
err
88-
) {
89-
if (err) {
90-
throw new Error('git.tag: ' + err.message);
91-
}
92-
93-
callback();
94-
});
44+
async commit(message) {
45+
return git('commit', '--message', message);
9546
},
96-
tagName: function(callback) {
97-
childProcess.exec('git describe --tags', {}, function(err, stdout) {
98-
if (err) {
99-
throw new Error('git.tagName: ' + err.message);
100-
}
101-
102-
let tags = stdout.trim().split(/\n/);
103-
tags = tags.filter(function(info) {
104-
info = info.split('-');
105-
return info.length == 1;
106-
});
47+
async tag(name) {
48+
return git('tag', '-a', `--message=${name}`, name);
49+
},
50+
async tagName() {
51+
const stdout = await git('tag', '-l', '--points-at', 'HEAD');
10752

108-
const versionTags = tags.filter(function(info) {
109-
return /^v/.test(info[0]);
110-
});
53+
const tags = stdout.trim().split(/\n|\r\n/);
54+
const versionTags = tags.filter(tag => /^v/.test(tag));
11155

112-
callback(undefined, versionTags[0] || tags[0]);
113-
});
56+
if (versionTags[0] != null) {
57+
return versionTags;
58+
}
59+
return tags[0];
11460
}
11561
};
62+
63+
async function git(...args) {
64+
return new Promise((resolve, reject) =>
65+
childProcess.execFile('git', args, (err, stdout) => {
66+
if (err != null) {
67+
return reject(
68+
new Error(`"git ${args.join(' ')}" caused error: ${err.message}`)
69+
);
70+
}
71+
resolve(stdout);
72+
})
73+
);
74+
}

‎tasks/version.js

+51-57
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,62 @@
1-
const async = require('neo-async'),
2-
git = require('./util/git'),
3-
semver = require('semver');
1+
const git = require('./util/git');
2+
const semver = require('semver');
3+
const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task');
44

55
module.exports = function(grunt) {
6-
grunt.registerTask(
7-
'version',
8-
'Updates the current release version',
9-
function() {
10-
const done = this.async(),
11-
pkg = grunt.config('pkg'),
12-
version = grunt.option('ver');
6+
const registerAsyncTask = createRegisterAsyncTaskFn(grunt);
137

14-
if (!semver.valid(version)) {
15-
throw new Error(
16-
'Must provide a version number (Ex: --ver=1.0.0):\n\t' +
17-
version +
18-
'\n\n'
19-
);
20-
}
21-
22-
pkg.version = version;
23-
grunt.config('pkg', pkg);
24-
25-
grunt.log.writeln('Updating to version ' + version);
26-
27-
async.each(
28-
[
29-
[
30-
'lib/handlebars/base.js',
31-
/const VERSION = ['"](.*)['"];/,
32-
"const VERSION = '" + version + "';"
33-
],
34-
[
35-
'components/bower.json',
36-
/"version":.*/,
37-
'"version": "' + version + '",'
38-
],
39-
[
40-
'components/package.json',
41-
/"version":.*/,
42-
'"version": "' + version + '",'
43-
],
44-
[
45-
'components/handlebars.js.nuspec',
46-
/<version>.*<\/version>/,
47-
'<version>' + version + '</version>'
48-
]
49-
],
50-
function(args, callback) {
51-
replace.apply(undefined, args);
52-
grunt.log.writeln(' - ' + args[0]);
53-
git.add(args[0], callback);
54-
},
55-
function() {
56-
grunt.task.run(['default']);
57-
done();
58-
}
8+
registerAsyncTask('version', async () => {
9+
const pkg = grunt.config('pkg');
10+
const version = grunt.option('ver');
11+
if (!semver.valid(version)) {
12+
throw new Error(
13+
'Must provide a version number (Ex: --ver=1.0.0):\n\t' +
14+
version +
15+
'\n\n'
5916
);
6017
}
61-
);
18+
pkg.version = version;
19+
grunt.config('pkg', pkg);
20+
21+
const replaceSpec = [
22+
{
23+
path: 'lib/handlebars/base.js',
24+
regex: /const VERSION = ['"](.*)['"];/,
25+
replacement: `const VERSION = '${version}';`
26+
},
27+
{
28+
path: 'components/bower.json',
29+
regex: /"version":.*/,
30+
replacement: `"version": "${version}",`
31+
},
32+
{
33+
path: 'components/package.json',
34+
regex: /"version":.*/,
35+
replacement: `"version": "${version}",`
36+
},
37+
{
38+
path: 'components/handlebars.js.nuspec',
39+
regex: /<version>.*<\/version>/,
40+
replacement: `<version>${version}</version>`
41+
}
42+
];
43+
44+
await Promise.all(
45+
replaceSpec.map(replaceSpec =>
46+
replaceAndAdd(
47+
replaceSpec.path,
48+
replaceSpec.regex,
49+
replaceSpec.replacement
50+
)
51+
)
52+
);
53+
grunt.task.run(['default']);
54+
});
6255

63-
function replace(path, regex, value) {
56+
async function replaceAndAdd(path, regex, value) {
6457
let content = grunt.file.read(path);
6558
content = content.replace(regex, value);
6659
grunt.file.write(path, content);
60+
await git.add(path);
6761
}
6862
};

0 commit comments

Comments
 (0)
Please sign in to comment.