Fixing outstanding installer & port mapping bugs

This commit is contained in:
Jeff Morgan 2014-11-28 17:56:38 -05:00
parent d1c6928321
commit 0357ce7b0e
23 changed files with 467 additions and 340 deletions

View File

@ -124,7 +124,10 @@ app.on('ready', function() {
width: 800,
height: 578,
resizable: false,
frame: false
frame: false,
'web-preferences': {
'web-security': false
}
};
mainWindow = new BrowserWindow(windowOptions);
mainWindow.hide();

View File

@ -1,6 +1,7 @@
var exec = require('exec');
var path = require('path');
var fs = require('fs');
var async = require('async');
var Convert = require('ansi-to-html');
var convert = new Convert();
@ -8,9 +9,10 @@ AppUtil = {};
AppUtil.run = function (app, callback) {
var image = Images.findOne({_id: app.imageId});
// Delete old container if one already exists
Apps.update(app._id, {$set: {
status: 'STARTING'
}});
Docker.removeContainer(app.name, function (err) {
if (err) { callback(err); }
Docker.runContainer(app, image, function (err, container) {
if (err) { callback(err); }
Docker.getContainerData(container.id, function (err, data) {
@ -26,22 +28,6 @@ AppUtil.run = function (app, callback) {
});
};
AppUtil.restartHelper = function (app) {
if (app.docker && app.docker.Id) {
var container = Docker.client().getContainer(app.docker.Id);
container.restart(function (err) {
if (err) { console.error(err); }
Docker.getContainerData(app.docker.Id, function (err, data) {
if (err) { console.error(err); }
Apps.update(app._id, {$set: {
status: 'READY',
docker: data
}});
});
});
}
};
AppUtil.start = function (appId) {
var app = Apps.findOne(appId);
if (app && app.docker) {
@ -78,16 +64,6 @@ AppUtil.stop = function (appId) {
}
};
AppUtil.restart = function (appId) {
var app = Apps.findOne(appId);
if (app && app.docker) {
Apps.update(app._id, {$set: {
status: 'STARTING'
}});
AppUtil.restartHelper(app);
}
};
AppUtil.remove = function (appId) {
var app = Apps.findOne(appId);
Apps.remove({_id: appId});
@ -153,35 +129,14 @@ AppUtil.recover = function () {
});
};
AppUtil.sync = function () {
AppUtil.sync = function (callback) {
Docker.listContainers(function (err, containers) {
if (err) {
console.error(err);
} else {
callback(err);
return;
}
var apps = Apps.find({}).fetch();
_.each(apps, function (app) {
var app = Apps.findOne(app._id);
if (app && app.docker && app.docker.Id) {
var duplicateApps = Apps.find({'docker.Id': app.docker.Id, _id: {$ne: app._id}}).fetch();
_.each(duplicateApps, function (duplicateApp) {
Apps.remove(duplicateApp._id);
});
Docker.getContainerData(app.docker.Id, function (err, data) {
var status = 'STARTING';
if (data && data.State && data.State.Running) {
status = 'READY';
} else if (data && data.State && !data.State.Running) {
status = 'ERROR';
}
Apps.update(app._id, {
$set: {
docker: data,
status: status
}
})
});
}
});
var dockerIds = _.map(apps, function (app) {
if (app.docker && app.docker.Id) {
return app.docker.Id;
@ -235,12 +190,42 @@ AppUtil.sync = function () {
path: appPath,
logs: [],
createdAt: new Date(),
volumesEnabled: true
};
if (container.HostConfig.Binds && container.HostConfig.Binds.length) {
appObj.volumesEnabled = true;
} else {
appObj.volumesEnabled = false;
}
console.log(appObj);
Apps.insert(appObj);
}
});
async.each(apps, function (app, callback) {
if (app && app.docker && app.docker.Id) {
var duplicateApps = Apps.find({'docker.Id': app.docker.Id, _id: {$ne: app._id}}).fetch();
_.each(duplicateApps, function (duplicateApp) {
Apps.remove(duplicateApp._id);
});
Docker.getContainerData(app.docker.Id, function (err, data) {
if (err) {callback(err); return;}
var status = 'STARTING';
if (data && data.State && data.State.Running) {
status = 'READY';
} else if (data && data.State && !data.State.Running) {
status = 'ERROR';
}
Apps.update(app._id, {
$set: {
docker: data,
status: status
}
});
callback();
});
}
}, function (err) {
callback(err);
});
});
};

View File

@ -2,11 +2,12 @@ var exec = require('exec');
var path = require('path');
var fs = require('fs');
var path = require('path');
var async = require('async');
var pkginfo = require('pkginfo')(module);
Boot2Docker = {};
Boot2Docker.REQUIRED_IP = '192.168.60.103';
Boot2Docker.VERSION = '1.3.1';
Boot2Docker.VERSION = module.exports['boot2docker-version'];
Boot2Docker.command = function () {
return path.join(Util.getBinDir(), 'boot2docker-' + Boot2Docker.VERSION);
@ -252,7 +253,43 @@ Boot2Docker.vmUpToDate = function (callback) {
if (err) {
callback(err); return;
}
var index = data.indexOf('Boot2Docker-v' + Boot2Docker.VERSION);
callback(null, index !== -1);
var match = data.match(/Boot2Docker-v(\d+\.\d+\.\d+)/);
if (!match) {
callback('Could not parse boot2docker iso version');
return;
}
callback (null, Util.compareVersions(match[1], Boot2Docker.VERSION) < 0);
});
}
};
Boot2Docker.status = function (callback) {
this.exec('status', function (stderr, stdout, code) {
if (code) {callback(stderr); return;}
callback(null, stdout.trim());
});
};
Boot2Docker.portAvailable = function (port, protocol, callback) {
this.exec('ssh netstat -lntu | grep LISTEN | grep ' + protocol + ' | grep -c ":::' + port + '\\s"', function (stdout, stderr, code) {
if (stderr.trim() === '0') {
callback(true);
} else {
callback(false);
}
});
};
Boot2Docker.waitWhileStatus = function (status, callback) {
var current = status;
async.whilst(function () {
return current === status;
}, function (innerCallback) {
Boot2Docker.status(function (err, vmStatus) {
if (err) {innerCallback(err); return;}
current = vmStatus.trim();
innerCallback();
});
}, function (err) {
callback(err);
});
};

View File

@ -95,13 +95,23 @@ Docker.runContainer = function (app, image, callback) {
var builtStr = key + '=' + app.config[key];
envParam.push(builtStr);
});
Docker.client().createContainer({
var containerOpts = {
Image: image.docker.Id,
Tty: false,
Env: envParam,
Hostname: app.name,
name: app.name
}, function (err, container) {
};
if (app.docker && app.docker.NetworkSettings.Ports) {
containerOpts.ExposedPorts = app.docker.NetworkSettings.Ports;
}
console.log(containerOpts);
Docker.client().createContainer(containerOpts, function (err, container) {
if (err) { callback(err, null); return; }
console.log('Created container: ' + container.id);
// Bind volumes
@ -111,11 +121,19 @@ Docker.runContainer = function (app, image, callback) {
binds.push([Util.getHomePath(), 'Kitematic', app.name, vol.Path].join('/') + ':' + vol.Path);
});
}
// Start the container
container.start({
PublishAllPorts: true,
var startOpts = {
Binds: binds
}, function (err) {
};
if (app.docker && app.docker.NetworkSettings.Ports) {
startOpts.PortBindings = app.docker.NetworkSettings.Ports;
} else {
startOpts.PublishAllPorts = true;
}
console.log(startOpts);
container.start(startOpts, function (err) {
if (err) { callback(err, null); return; }
console.log('Started container: ' + container.id);
callback(null, container);

View File

@ -2,11 +2,11 @@ FormSchema = {
formCreateApp: {
name: {
label: 'app name',
label: 'container name',
required: true,
transforms: ['clean', 'slugify'],
messages: {
'uniqueAppName': "This app name is already being used."
'uniqueAppName': "This container name is already being used."
},
rules: {
uniqueAppName: true

View File

@ -3,6 +3,7 @@ var convert = new Convert();
var exec = require('exec');
var path = require('path');
var fs = require('fs');
var async = require('async');
ImageUtil = {};
@ -239,55 +240,34 @@ ImageUtil.remove = function (imageId) {
}
};
ImageUtil.sync = function () {
ImageUtil.sync = function (callback) {
Docker.listImages(function (err, dockerImages) {
if (err) {
console.error(err);
} else {
return;
}
var images = Images.find({}).fetch();
_.each(images, function (image) {
var image = Images.findOne(image._id);
if (image && image.docker && image.docker.Id) {
var duplicateImages = Images.find({'docker.Id': image.docker.Id, _id: {$ne: image._id}}).fetch();
_.each(duplicateImages, function (duplicateImage) {
Images.remove(duplicateImage._id);
});
var imageData = _.find(dockerImages, function (dockerImage) {
return dockerImage.Id === image.docker.Id;
});
if (imageData && imageData.RepoTags) {
Images.update(image._id, {
$set: {
tags: imageData.RepoTags
}
});
}
Docker.getImageData(image.docker.Id, function (err, data) {
Images.update(image._id, {
$set: {
docker: data
}
})
});
}
});
var dockerIds = _.map(images, function (image) {
// Delete missing GUI images
var kitematicIds = _.map(images, function (image) {
if (image.docker && image.docker.Id) {
return image.docker.Id;
}
});
var imageIds = _.map(dockerImages, function (image) {
var daemonIds = _.map(daemonIds, function (image) {
return image.Id;
});
var diffImages = _.difference(dockerIds, imageIds);
var diffImages = _.difference(kitematicIds, daemonIds);
_.each(diffImages, function (imageId) {
var image = Images.findOne({'docker.Id': imageId});
if (image && image.status !== 'BUILDING') {
ImageUtil.remove(image._id);
Images.remove(image._id);
}
});
// Add missing Daemon images
var diffDockerImages = _.reject(dockerImages, function (image) {
return _.contains(dockerIds, image.Id);
return _.contains(kitematicIds, image.Id);
});
_.each(diffDockerImages, function (image) {
var repoTag = _.first(image.RepoTags);
@ -312,6 +292,36 @@ ImageUtil.sync = function () {
Images.insert(imageObj);
}
});
async.each(images, function (image, callback) {
var image = Images.findOne(image._id);
if (image && image.docker && image.docker.Id) {
var duplicateImages = Images.find({'docker.Id': image.docker.Id, _id: {$ne: image._id}}).fetch();
_.each(duplicateImages, function (duplicateImage) {
Images.remove(duplicateImage._id);
});
var imageData = _.find(dockerImages, function (dockerImage) {
return dockerImage.Id === image.docker.Id;
});
if (imageData && imageData.RepoTags) {
Images.update(image._id, {
$set: {
tags: imageData.RepoTags
}
});
}
Docker.getImageData(image.docker.Id, function (err, data) {
if (err) {callback(err); return;}
Images.update(image._id, {
$set: {
docker: data
}
});
callback();
});
}
}, function (err) {
callback(err);
});
});
};

View File

@ -52,7 +52,7 @@ Router.map(function () {
}
Session.set('onIntro', false);
startUpdatingBoot2DockerUtilization();
// startSyncingAppState();
startSyncingAppState();
Router.go('dashboard_apps');
}
});

View File

@ -67,6 +67,17 @@ Setup.steps = [
},
message: 'Downloading VirtualBox...'
},
{
run: function (callback) {
VirtualBox.shutdownVM('kitematic-vm', function (err, removed) {
if (err) {
console.log(err);
}
callback();
});
},
message: 'Cleaning up existing Docker VM...'
},
// Initialize Boot2Docker if necessary.
{
@ -74,10 +85,6 @@ Setup.steps = [
Boot2Docker.exists(function (err, exists) {
if (err) { callback(err); return; }
if (!exists) {
var vmFilesPath = path.join(Util.getHomePath(), 'VirtualBox\ VMs', 'boot2docker-vm');
if (fs.existsSync(vmFilesPath)) {
Util.deleteFolder(vmFilesPath);
}
Boot2Docker.init(function (err) {
callback(err);
});
@ -105,9 +112,10 @@ Setup.steps = [
},
{
run: function (callback) {
Boot2Docker.state(function (err, state) {
Boot2Docker.waitWhileStatus('saving', function (err) {
Boot2Docker.status(function (err, status) {
if (err) {callback(err); return;}
if (state !== 'running') {
if (status !== 'running') {
Boot2Docker.start(function (err) {
callback(err);
});
@ -115,6 +123,7 @@ Setup.steps = [
callback();
}
});
});
},
message: 'Starting the Docker VM...'
},

View File

@ -1,6 +1,7 @@
var fs = require('fs');
var exec = require('exec');
var path = require('path');
var async = require('async');
VirtualBox = {};
@ -51,7 +52,7 @@ VirtualBox.version = function (callback) {
});
};
VirtualBox.shutDownRunningVMs = function (callback) {
VirtualBox.saveRunningVMs = function (callback) {
if (!this.installed()) {
callback('VirtualBox not installed.');
return;
@ -66,7 +67,7 @@ VirtualBox.shutDownRunningVMs = function (callback) {
};
VirtualBox.killAllProcesses = function (callback) {
this.shutDownRunningVMs(function (err) {
this.saveRunningVMs(function (err) {
if (err) {callback(err); return;}
exec('pkill VirtualBox', function (stderr, stdout, code) {
if (code) {callback(stderr); return;}
@ -77,3 +78,41 @@ VirtualBox.killAllProcesses = function (callback) {
});
});
};
VirtualBox.vmState = function (name, callback) {
VirtualBox.exec('showvminfo ' + name + ' --machinereadable', function (stderr, stdout, code) {
if (code) { callback(stderr); return; }
var match = stdout.match(/VMState="(\w+)"/);
if (!match) {
callback('Could not parse VMState');
return;
}
callback(null, match[1]);
});
};
VirtualBox.shutdownVM = function (name, callback) {
VirtualBox.vmState(name, function (err, state) {
// No VM found
if (err) { callback(null, false); return; }
VirtualBox.exec('controlvm ' + name + ' acpipowerbutton', function (stderr, stdout, code) {
if (code) { callback(stderr, false); return; }
var state = null;
async.until(function () {
return state === 'poweroff';
}, function (callback) {
VirtualBox.vmState(name, function (err, newState) {
if (err) { callback(err); return; }
state = newState;
setTimeout(callback, 250);
});
}, function (err) {
VirtualBox.exec('unregistervm ' + name + ' --delete', function (stderr, stdout, code) {
if (code) { callback(err); return; }
callback();
});
});
});
});
};

View File

@ -100,10 +100,11 @@ startUpdatingBoot2DockerUtilization = function () {
};
startSyncingAppState = function () {
ImageUtil.sync();
AppUtil.sync();
Meteor.setTimeout(function () {
ImageUtil.sync();
AppUtil.sync();
}, 5000);
ImageUtil.sync(function (err) {
if (err) {console.log(err);}
AppUtil.sync(function (err) {
if (err) {console.log(err);}
Meteor.setTimeout(startSyncingAppState, 5000);
});
});
};

View File

@ -30,8 +30,11 @@
}
}
.ports {
position: relative;
top: -2px;
.dropdown-menu {
min-width: 241px;
padding: 10px 15px 3px;
}
.btn-group {
top: -2px;
@ -62,7 +65,6 @@
&.open + .tooltip {
display: none !important;
}
position: relative;
}
}
&:hover {
@ -281,10 +283,18 @@
}
}
.form-env-vars {
label {
font-size: 13px;
}
input {
font-size: 13px;
padding: 5px 9px;
}
.env-var-pair {
.make-row();
margin-bottom: 0.2em;
font-size: 12px;
font-size: 13px;
.env-var-key {
.make-xs-column(5);
text-overflow: ellipsis;
@ -301,10 +311,10 @@
.make-xs-column(2);
}
}
}
.app-ports {
cursor: default;
padding: 10px 15px 3px;
min-width: 240px;
li {
padding-bottom: 7px;

View File

@ -1,15 +1,6 @@
<template name="dashboardAppsPorts">
<div class="app-ports">
{{#each ports}}
{{#if this.web}}
<li role="menuitem">
<span class="port-wrapper">Port {{this.port}}</span>
<span class="arrow-wrapper"></span>
<span class="open-button-wrapper">
<a href="{{this.url}}" onclick="trackLink('view container')" class="btn btn-action btn-xs btn-view-port">Open in Browser</a>
</span>
</li>
{{else}}
<li role="menuitem">
<span class="port-wrapper">Port {{this.port}}</span>
<span class="arrow-wrapper">
@ -17,7 +8,6 @@
</span>
<span class="host-address-wrapper">{{this.hostIp}}:{{this.hostPort}}</span>
</li>
{{/if}}
{{/each}}
</div>
</template>

View File

@ -1,4 +1,14 @@
<template name="dashboardAppsSettings">
<div class="section">
<div class="left-section">
<h4>Ports</h4>
</div>
<div class="right-section">
<ul class="list-unstyled">
{{> dashboardAppsPorts}}
</ul>
</div>
</div>
<div class="section">
<div class="left-section">
<h4>Environment Variables</h4>

View File

@ -45,7 +45,7 @@ Template.dashboardAppsSettings.events({
e.preventDefault();
var appId = this._id;
dialog.showMessageBox({
message: 'Are you sure you want to delete this app?',
message: 'Are you sure you want to delete this container?',
buttons: ['Delete', 'Cancel']
}, function (index) {
if (index === 0) {

View File

@ -23,6 +23,7 @@
</h5>
<div class="options">
{{#if $eq status 'READY'}}
{{#if ports}}
{{#if viewPort}}
<div class="ports btn-group btn-icon" title="View" data-placement="bottom">
<a href="{{viewPort.url}}" onclick="trackLink('view container')" class="btn btn-action btn-xs btn-view btn-globe">
@ -50,10 +51,11 @@
</span>
{{/if}}
{{/if}}
{{/if}}
<a href="#" onclick="trackLink('open container folder')" class="btn-icon btn-folder" data-toggle="tooltip" data-placement="bottom" title="Volumes"><span class="typcn typcn-folder"></span></a>
{{#if $eq status 'READY'}}
<a href="#" onclick="trackLink('terminal into container')" class="btn-icon btn-terminal" data-toggle="tooltip" data-placement="bottom" title="Terminal"><span class="typcn typcn-device-laptop"></span></a>
<a href="#" onclick="trackLink('stop container')" class="btn-icon btn-stop" data-toggle="tooltip" data-placement="bottom" title="Stop"><span class="typcn typcn-media-pause-outline"></span></a>
<a href="#" onclick="trackLink('stop container')" class="btn-icon btn-stop" data-toggle="tooltip" data-placement="bottom" title="Stop"><span class="typcn typcn-media-stop-outline"></span></a>
{{/if}}
{{#if $eq status 'STOPPED'}}
<a href="#" onclick="trackLink('start container')" class="btn-icon btn-start" data-toggle="tooltip" data-placement="bottom" title="Start"><span class="typcn typcn-media-play-outline"></span></a>

View File

@ -1,6 +1,7 @@
var remote = require('remote');
var dialog = remote.require('dialog');
var exec = require('child_process').exec;
var path = require('path');
Template.dashboardSingleApp.rendered = function () {
Meteor.setInterval(function () {
@ -48,22 +49,39 @@ Template.dashboardSingleApp.events({
},
'click .btn-restart': function (e) {
e.preventDefault();
AppUtil.restart(this._id);
AppUtil.run(this, function (err) {});
},
'click .btn-folder': function (e) {
e.preventDefault();
var appId = this._id;
var app = Apps.findOne(appId);
var app = this;
if (!app) {
throw new Error('Cannot find app with id: ' + appId);
throw new Error('Cannot find app with id: ' + app._id);
}
if (app.volumesEnabled) {
exec('open ' + this.path, function (err) {
var openDirectory = function () {
var appPath = path.join(Util.KITE_PATH, app.name);
if (app.docker.Volumes.length) {
if (app.docker.Volumes[0].Value.indexOf(path.join(Util.getHomePath(), 'Kitematic')) !== -1) {
exec('open ' + appPath, function (err) {
if (err) { throw err; }
});
return;
} else {
exec('open ' + app.docker.Volumes[0].Value, function (err) {
if (err) { throw err; }
});
return;
}
} else {
exec('open ' + appPath, function (err) {
if (err) { throw err; }
});
}
};
if (app.volumesEnabled) {
openDirectory();
return;
}
dialog.showMessageBox({
@ -71,14 +89,12 @@ Template.dashboardSingleApp.events({
buttons: ['Enable Volumes', 'Cancel']
}, function (index) {
if (index === 0) {
Apps.update(appId, {
Apps.update(app._id, {
$set: {volumesEnabled: true}
});
AppUtil.run(Apps.findOne(appId), function (err) {
AppUtil.run(Apps.findOne(app._id), function (err) {
if (err) { throw err; }
exec('open ' + this.path, function (err) {
if (err) { throw err; }
});
openDirectory();
});
}
});

View File

@ -31,7 +31,6 @@ Template.modalCreateApp.events({
imageId: cleaned.imageId,
status: 'STARTING',
config: {},
path: appPath,
logs: [],
createdAt: new Date(),
volumesEnabled: true

View File

@ -59,7 +59,7 @@ Template.modalCreateImage.events({
if (imageObj.meta.logo) {
Images.update(imageId, {
$set: {
logoPath: path.join(imagePath, imageObj.meta.logo)
logoPath: path.join(directory, imageObj.meta.logo)
}
});
}

View File

@ -32,7 +32,8 @@ Template.dashboardAppsLayout.events({
},
'click .btn-folder': function () {
var exec = require('child_process').exec;
exec('open ' + this.path, function (err) {
var appPath = path.join(Util.KITE_PATH, this.name);
exec('open ' + appPath, function (err) {
if (err) { throw err; }
});
},

View File

@ -1,13 +1,13 @@
Apps = new Meteor.Collection('apps');
Apps.COMMON_WEB_PORTS = [
80,
8000,
8080,
3000,
5000,
2368,
443
'80',
'8000',
'8080',
'3000',
'5000',
'2368',
'443'
];
Apps.allow({
@ -35,22 +35,27 @@ Apps.helpers({
if (!app.docker || !app.docker.NetworkSettings.Ports) {
return [];
}
var results = _.map(app.docker.NetworkSettings.Ports, function (value, key) {
var portProtocolPair = key.split('/');
var res = {
'port': parseInt(portProtocolPair[0]),
'port': portProtocolPair[0],
'protocol': portProtocolPair[1]
};
if (value.length) {
if (value && value.length) {
var port = value[0].HostPort;
res['hostIp'] = Docker.hostIp;
res['hostPort'] = port;
res['web'] = Apps.COMMON_WEB_PORTS.indexOf(res.port) !== -1;
res['url'] = 'http://' + Docker.hostIp + ':' + port;
} else {
return null;
}
return res;
});
results = _.filter(results, function (res) { return res !== null; });
results.sort(function (a, b) {
// prefer lower ports
if (a.web && b.web) {

View File

@ -12,12 +12,12 @@
"type": "GNU",
"url": "https://raw.githubusercontent.com/kitematic/kitematic/master/LICENSE"
}],
"boot2docker-version": "1.3.2",
"main": "index.js",
"version": "0.4.0",
"dependencies": {
"ansi-to-html": "0.2.0",
"async": "^0.9.0",
"chokidar": "git+https://github.com/usekite/chokidar.git",
"dockerode": "2.0.4",
"exec": "^0.1.2",
"moment": "2.8.1",
@ -25,6 +25,7 @@
"open": "0.0.5",
"request": "2.42.0",
"request-progress": "0.3.1",
"tar": "0.1.20"
"tar": "0.1.20",
"pkginfo": "0.3.0"
}
}

View File

@ -2,35 +2,31 @@
set -e # Auto exit on error
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $DIR/colors.sh
BASE=$DIR/..
NPM="$BASE/cache/node/bin/npm"
NODE="$BASE/cache/node/bin/node"
VERSION=$($NODE -pe 'JSON.parse(process.argv[1]).version' "$(cat package.json)")
pushd $BASE/meteor
source $DIR/colors.sh
$BASE/script/setup.sh
rm -rf ../bundle
rm -rf ./bundle
cecho "-----> Building bundle from Meteor app, this may take a few minutes..." $blue
cd $BASE/meteor
meteor bundle --directory ../bundle
cd ../bundle
cd $BASE/bundle
cecho "-----> Installing bundle npm packages." $blue
pushd programs/server
cd programs/server
$NPM install
popd
cecho "Bundle created." $green
popd
cd $BASE
pushd $BASE
rm -rf ./dist/osx
rm -Rf ./dist/osx/
mkdir -p ./dist/osx/
DIST_APP=Kitematic.app
@ -39,6 +35,7 @@ cecho "-----> Creating $DIST_APP..." $blue
find cache/atom-shell -name "debug\.log" -print0 | xargs -0 rm -rf
cp -R cache/atom-shell/Atom.app dist/osx/
mv dist/osx/Atom.app dist/osx/$DIST_APP
mv dist/osx/$DIST_APP/Contents/MacOS/Atom dist/osx/$DIST_APP/Contents/MacOS/Kitematic
mkdir -p dist/osx/$DIST_APP/Contents/Resources/app
cecho "-----> Copying meteor bundle into $DIST_APP..." $blue
@ -58,7 +55,6 @@ cp kitematic.icns dist/osx/$DIST_APP/Contents/Resources/atom.icns
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/terminal
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/node
chmod -R u+w dist/osx/$DIST_APP/Contents/Resources/app/bundle
cecho "-----> Updating Info.plist version to $VERSION" $blue
@ -66,19 +62,17 @@ cecho "-----> Updating Info.plist version to $VERSION" $blue
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName Kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleName Kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.kitematic.kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleExecutable Kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
if [ -f $DIR/sign.sh ]; then
cecho "-----> Signing app file...." $blue
$DIR/sign.sh $BASE/dist/osx/$DIST_APP
fi
pushd dist/osx
cecho "-----> Creating disributable zip file...." $blue
ditto -c -k --sequesterRsrc --keepParent $DIST_APP Kitematic-$VERSION.zip
popd
cd $BASE/dist/osx
cecho "-----> Creating disributable zip file...." $blue
ditto -c -k --sequesterRsrc --keepParent $DIST_APP Kitematic-$VERSION.zip
cecho "Done." $green
cecho "Kitematic app available at dist/osx/$DIST_APP" $green
cecho "Kitematic zip distribution available at dist/osx/Kitematic.zip" $green
popd

View File

@ -1,22 +1,16 @@
#!/bin/bash
set -e # Auto exit on error
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $DIR/colors.sh
BASE=$DIR/..
pushd $BASE
mkdir -p cache
pushd cache
BOOT2DOCKER_CLI_VERSION=1.3.1
BOOT2DOCKER_CLI_VERSION_FILE=boot2docker-$BOOT2DOCKER_CLI_VERSION
BOOT2DOCKER_CLI_FILE=boot2docker
ATOM_SHELL_VERSION=0.19.1
ATOM_SHELL_FILE=atom-shell-v$ATOM_SHELL_VERSION-darwin-x64.zip
BASE=$DIR/..
source $DIR/colors.sh
cd $BASE
mkdir -p cache
cd cache
if [ ! -f $ATOM_SHELL_FILE ]; then
cecho "-----> Downloading Atom Shell..." $purple
@ -42,9 +36,13 @@ if [ ! -f "node-v0.10.29-darwin-x64.tar.gz" ]; then
cp node/LICENSE $BASE/resources/NODE_LICENSE.txt
fi
popd
cd $BASE
pushd resources
NODE="$BASE/cache/node/bin/node"
BOOT2DOCKER_CLI_VERSION=$($NODE -pe "JSON.parse(process.argv[1])['boot2dockerversion']" "$(cat package.json)")
BOOT2DOCKER_CLI_VERSION_FILE=boot2docker-$BOOT2DOCKER_CLI_VERSION
cd resources
if [ ! -f $BOOT2DOCKER_CLI_VERSION_FILE ]; then
cecho "-----> Downloading Boot2docker CLI..." $purple
@ -53,13 +51,12 @@ fi
chmod +x $BOOT2DOCKER_CLI_VERSION_FILE
popd
cd $BASE
# Build NPM modules
NPM="$BASE/cache/node/bin/npm"
export npm_config_disturl=https://gh-contractor-zcbenz.s3.amazonaws.com/atom-shell/dist
export npm_config_target=0.16.2
export npm_config_target=ATOM_SHELL_VERSION
export npm_config_arch=ia32
HOME=~/.atom-shell-gyp $NPM install
popd