diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf4dbb202e..8fc1617a3d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,13 +18,14 @@ Before you fil an issue or a pull request, quickly read of the following tips on ### Prerequisites Most of the time, you'll have installed Kitematic before contibuting, but for the -sake of completeness, you can also install [Node.js](https://nodejs.org/) and the latest Xcode from the Apple App Store and then run from your Git clone. +sake of completeness, you can also install [Node.js 0.10.38](https://nodejs.org/dist/v0.10.38/). -Running `npm start` will download and install the OS X Docker client, -[Docker machine](https://github.com/docker/machine), -the [Boot2Docker iso](https://github.com/boot2docker/boot2docker), -[Electron](http://electron.atom.io/), and [VirtualBox](https://www.virtualbox.org/) -if needed. +### Other Prerequisites (Mac) +- The latest Xcode from the Apple App Store. + +### Other Prerequisites (Windows) +- [Visual Studio 2013 Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) (or similar) +- [Python](https://www.python.org/downloads/release/python-2710/) ### Getting Started @@ -34,6 +35,11 @@ To run the app in development: - `npm start` +Running `npm start` will download and install the OS X Docker client, +[Docker Machine](https://github.com/docker/machine), [Docker Compose](https://github.com/docker/compose) +the [Boot2Docker iso](https://github.com/boot2docker/boot2docker), +[Electron](http://electron.atom.io/). + ### Building & Release - `npm run release` diff --git a/__mocks__/remote.js b/__mocks__/remote.js new file mode 100644 index 0000000000..b2c2ab1348 --- /dev/null +++ b/__mocks__/remote.js @@ -0,0 +1,4 @@ +module.exports = { + require: jest.genMockFunction(), + match: jest.genMockFunction() +}; diff --git a/docs/index.md b/docs/index.md index 0ddfc9f3b9..60a58533b2 100755 --- a/docs/index.md +++ b/docs/index.md @@ -28,10 +28,9 @@ container! ## Technical Details -Kitematic is a self-contained .app, with a two exceptions: +Kitematic is a self-contained .app, with an exception: - It will install VirtualBox if it's not already installed. -- It copies the `docker` and `docker-machine` binaries to `/usr/local/bin` for convenience. ### Why does Kitematic need my root password? diff --git a/gulpfile.js b/gulpfile.js index b52142baa2..6099fb736b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -14,6 +14,9 @@ var plumber = require('gulp-plumber'); var runSequence = require('run-sequence'); var shell = require('gulp-shell'); var sourcemaps = require('gulp-sourcemaps'); +var execFile = require('child_process').execFile; +var request = require('request'); +var path = require('path'); var dependencies = Object.keys(packagejson.dependencies); var argv = require('minimist')(process.argv.slice(2)); @@ -175,16 +178,96 @@ gulp.task('settings', function () { string_src('settings.json', JSON.stringify(settings)).pipe(gulp.dest('dist/osx/' + options.appFilename.replace(' ', '\ ').replace('(','\(').replace(')','\)') + '/Contents/Resources/app')); }); -gulp.task('download-deps', function () { - if(process.platform === 'win32') { - return gulp.src('').pipe( - shell(['powershell.exe -ExecutionPolicy unrestricted -File util\\deps.ps1']) - ); - } else { - return gulp.src('').pipe( - shell(['./util/deps']) - ); +var version = function (str) { + var match = str.match(/(\d+\.\d+\.\d+)/); + if (match) { + return match[1]; + } else { + return null; + } +}; + +gulp.task('download-docker', function (cb) { + if (process.platform === 'win32' && fs.existsSync(path.join('resources', 'docker.exe'))) { + cb(); + return; + } + + execFile(path.join('resources', 'docker'), ['-v'], function (err, stdout, stderr) { + var currentVersion = version(stdout); + if (currentVersion && currentVersion === packagejson['docker-version']) { + cb(); + return; } + + gutil.log(gutil.colors.green('Downloading Docker')); + + if(process.platform === 'win32') { + request('https://master.dockerproject.com/windows/amd64/docker-1.7.0-dev.exe').pipe(fs.createWriteStream('./resources/docker.exe')).on('finish', cb); + } else { + request('https://get.docker.com/builds/Darwin/x86_64/docker-' + packagejson['docker-version']) + .pipe(fs.createWriteStream('./resources/docker')).on('finish', function () { + fs.chmodSync('./resources/docker', 0755); + cb(); + }); + } + }); +}); + +gulp.task('download-docker-machine', function (cb) { + execFile(path.join('resources', 'docker-machine'), ['-v'], function (err, stdout, stderr) { + var currentVersion = version(stdout); + if (currentVersion && currentVersion === version(packagejson['docker-machine-version'])) { + cb(); + return; + } + + gutil.log(gutil.colors.green('Downloading Docker Machine')); + + if(process.platform === 'win32') { + request('https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_windows-amd64.exe') + .pipe(fs.createWriteStream('./resources/docker-machine.exe')).on('finish', function () {cb()}); + } else { + request('https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_darwin-amd64') + .pipe(fs.createWriteStream('./resources/docker-machine')).on('finish', function () { + fs.chmodSync('./resources/docker-machine', 0755); + cb(); + }); + } + }); +}); + +gulp.task('download-docker-compose', function (cb) { + execFile(path.join('resources', 'docker-compose'), ['--version'], function (err, stdout, stderr) { + var currentVersion = version(stdout); + if (currentVersion && currentVersion === packagejson['docker-compose-version']) { + cb(); + return; + } + + if(process.platform === 'win32') { + // Todo: install windows version of compose + cb(); + } else { + gutil.log(gutil.colors.green('Downloading Docker Compose')); + request('https://github.com/docker/compose/releases/download/' + packagejson['docker-compose-version'] + '/docker-compose-Darwin-x86_64') + .pipe(fs.createWriteStream('./resources/docker-compose')).on('finish', function () { + fs.chmodSync('./resources/docker-compose', 0755); + cb(); + }); + } + }); +}); + +gulp.task('download-boot2docker-iso', function (cb) { + var b2dFile = path.join('resources', 'boot2docker-' + packagejson['docker-version'] + '.iso'); + if (!fs.existsSync(b2dFile)) { + gutil.log(gutil.colors.green('Downloading Boot2Docker iso')); + request('https://github.com/boot2docker/boot2docker/releases/download/v' + packagejson['docker-version'] + '/boot2docker.iso') + .pipe(fs.createWriteStream(b2dFile)).on('finish', cb); + } else { + cb(); + } }); gulp.task('reset', function () { @@ -200,10 +283,10 @@ gulp.task('reset', function () { }); gulp.task('release', function () { - runSequence('download-deps', 'download', 'dist', ['copy', 'images', 'js', 'styles', 'settings'], 'sign', 'zip'); + runSequence('download-docker', 'download-docker-machine', 'download-docker-compose', 'download-boot2docker-iso', 'download', 'dist', ['copy', 'images', 'js', 'styles', 'settings'], 'sign', 'zip'); }); -gulp.task('default', ['download-deps', 'download', 'copy', 'js', 'images', 'styles'], function () { +gulp.task('default', ['download-docker', 'download-docker-machine', 'download-docker-compose', 'download-boot2docker-iso', 'download', 'copy', 'js', 'images', 'styles'], function () { gulp.watch('src/**/*.js', ['js']); gulp.watch('index.html', ['copy']); gulp.watch('styles/**/*.less', ['styles']); diff --git a/index.html b/index.html index 69fafdb727..699c7186f0 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,6 @@