When submitting PRs to library authors to add Meteor integration, it helps to match their build process.
Most packages use the Grunt task runner and a package.json
. To make it extra easy on the maintainers, below are quasi-diffs that do Meteor testing and publishing.
There is no direct Grunt plugin to publish to Atmosphere, because this should be done through the meteor
tool. We'll execute meteor publish
using the grunt-exec plugin.
For testing, we'll use spacejam, which in turn executes meteor test-packages
.
Add the lines below in the corresponding sections in the Gruntfile. For your convenience, there are 2- and 4-space indented sections, and a .coffee file.
First, you need to add the two devDepencencies
in package.json
:
"grunt-exec": "^0.4.6"
"spacejam": "^1.1.1"
It may be tempted to add Meteor as a sort of devDependency, but most of the time, the original author won't deal with Meteor; as for Meteor devs, they already have Meteor. Thus we'll install Meteor if it's not installed already, from the Grunt file. It has also been suggested to just check if Meteor is installed and print a warning otherwise when running meteor
tasks, instead of automagically installing it.
// if there's a "clean" task, add Meteor to it; otherwise, see meteor-cleanup below
clean: {
...
meteor: ['.build.*', 'versions.json', 'package.js']
}
...
exec: {
'meteor-init': {
command: [
// Make sure Meteor is installed, per https://meteor.com/install.
// The curl'ed script is safe; takes 2 minutes to read source & check.
'type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; }',
// Meteor expects package.js to be in the root directory of
// the checkout, so copy it there temporarily
'cp meteor/package.js .'
].join(';')
},
// !- only add this if there was no "clean" task
'meteor-cleanup': {
// remove build files and package.js
command: 'rm -rf .build.* versions.json package.js'
},
'meteor-test': {
command: 'node_modules/.bin/spacejam --mongo-url mongodb:// test-packages ./'
},
'meteor-publish': {
command: 'meteor publish'
}
}
...
// !- add the line below ONLY if you see other grunt.loadNpmTasks() calls
grunt.loadNpmTasks('grunt-exec');
// !- you DON'T need to add the line above if you see: require('load-grunt-tasks')(grunt);
...
// Meteor tasks
grunt.registerTask('meteor-test', ['exec:meteor-init', 'exec:meteor-test', 'exec:meteor-cleanup']);
grunt.registerTask('meteor-publish', ['exec:meteor-init', 'exec:meteor-publish', 'exec:meteor-cleanup']);
grunt.registerTask('meteor', ['exec:meteor-init', 'exec:meteor-test', 'exec:meteor-publish', 'exec:meteor-cleanup']);
// if there's a "clean" task, add Meteor to it; otherwise, see meteor-cleanup below
clean: {
...
meteor: ['.build.*', 'versions.json', 'package.js']
}
...
exec: {
'meteor-init': {
command: [
// Make sure Meteor is installed, per https://meteor.com/install.
// The curl'ed script is safe; takes 2 minutes to read source & check.
'type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; }',
// Meteor expects package.js to be in the root directory of
// the checkout, so copy it there temporarily
'cp meteor/package.js .'
].join(';')
},
// !- only add this if there was no "clean" task
'meteor-cleanup': {
// remove build files and package.js
command: 'rm -rf .build.* versions.json package.js'
},
'meteor-test': {
command: 'node_modules/.bin/spacejam --mongo-url mongodb:// test-packages ./'
},
'meteor-publish': {
command: 'meteor publish'
}
}
...
// !- add the line below ONLY if you see other grunt.loadNpmTasks() calls
grunt.loadNpmTasks('grunt-exec');
// !- you DON'T need to add the line above if you see: require('load-grunt-tasks')(grunt);
...
// Meteor tasks
grunt.registerTask('meteor-test', ['exec:meteor-init', 'exec:meteor-test', 'exec:meteor-cleanup']);
grunt.registerTask('meteor-publish', ['exec:meteor-init', 'exec:meteor-publish', 'exec:meteor-cleanup']);
grunt.registerTask('meteor', ['exec:meteor-init', 'exec:meteor-test', 'exec:meteor-publish', 'exec:meteor-cleanup']);
# if there's a "clean" task, add Meteor to it; otherwise, see meteor-cleanup below
clean:
...
meteor: ['.build.*', 'versions.json', 'package.js']
...
exec:
'meteor-init':
command: [
# Make sure Meteor is installed, per https://meteor.com/install.
# The curl'ed script is safe; takes 2 minutes to read source & check.
'type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; }',
# Meteor expects package.js to be in the root directory
# of the checkout, so copy it there temporarily
'cp meteor/package.js .'
].join(';')
# !- only add this if there was no "clean" task
'meteor-cleanup':
# remove build files and package.js
command: 'rm -rf .build.* versions.json package.js'
'meteor-test':
command: 'spacejam --mongo-url mongodb:// test-packages ./'
'meteor-publish':
command: 'meteor publish'
...
# !- add the line below ONLY if you see other grunt.loadNpmTasks() calls
grunt.loadNpmTasks 'grunt-exec'
# !- you DON'T need to add the line above if you see: require('load-grunt-tasks')(grunt);
...
# Meteor tasks
grunt.registerTask 'meteor-test', ['exec:meteor-init', 'exec:meteor-test', 'exec:meteor-cleanup']
grunt.registerTask 'meteor-publish', ['exec:meteor-init', 'exec:meteor-publish', 'exec:meteor-cleanup']
grunt.registerTask 'meteor', ['exec:meteor-init', 'exec:meteor-test', 'exec:meteor-publish', 'exec:meteor-cleanup']
We can include Meteor tests in the continuous integration file, .travis.yml:
language: node_js
node_js:
- "0.10"
before_script:
- npm install -g grunt-cli
# Install Meteor preemptively because installing via grunt-exect has failed in the past
- curl https://install.meteor.com | /bin/sh
script:
- grunt test-travis
- grunt meteor-test
Regarding the preemptive installation of Meteor, check this Travil build log for hammer.js. Installing Meteor via grunt-exec
has failed for no clear reason, but installing via .travis.yml
hasn't yet (ever), so be safe. On the other hand, it's possible that that particular grunt-exec failure was caused by a transient network error.