Feature: add command line to run app and environment variables settings

This commit is contained in:
2015-12-07 15:37:41 +00:00
parent 75c0ec650c
commit fe4ac511fc
6 changed files with 193 additions and 27 deletions

View File

@@ -6,30 +6,54 @@ Template.projects.helpers({
Template.projectForm.onRendered(function() { Template.projectForm.onRendered(function() {
new Clipboard('.btn.clipboard'); new Clipboard('.btn.clipboard');
Session.set('vars', []);
$('.variables input').val('');
}); });
Template.projectForm.events({ Template.projectForm.events({
'submit .new-project': function (event) { 'submit .new-project': function (event) {
event.preventDefault(); event.preventDefault();
var form = event.target; var form = event.target,
if( form.id.value ) { variables = Session.get('vars'),
Meteor.call('editProject',form.id.value, form.label.value, form.git_url.value, form.public_url.value, form.commands.value); callback = function(errors, result) {
form.id.value = '';
} else {
Meteor.call('addProject', form.label.value, form.git_url.value, form.public_url.value, form.commands.value);
}
Session.set('projectToEdit', undefined); if( errors ) {
form.label.value = '';
form.git_url.value = ''; } else {
form.public_url.value = ''; Session.set('projectToEdit', undefined);
form.commands.value = ''; Session.set('vars', []);
$('.new-project input').val('');
$('.new-project textarea').val('');
}
};
if( form.id.value ) {
Meteor.call('editProject',
form.id.value,
form.label.value,
form.git_url.value,
form.public_url.value,
form.commands.value,
form.run.value,
variables,
callback);
} else {
Meteor.call('addProject',
form.label.value,
form.git_url.value,
form.public_url.value,
form.commands.value,
form.run.value,
variables,
callback);
}
}, },
'click .cancel': function(event) { 'click .cancel': function(event) {
event.preventDefault(); event.preventDefault();
Session.set('projectToEdit', undefined); Session.set('projectToEdit', undefined);
Session.set('vars', []);
$('.variables input').val('');
}, },
'click .trash': function(event) { 'click .trash': function(event) {
@@ -37,7 +61,9 @@ Template.projectForm.events({
Meteor.call('deleteProject', Session.get('projectToEdit')._id); Meteor.call('deleteProject', Session.get('projectToEdit')._id);
Session.set('projectToEdit', undefined); Session.set('projectToEdit', undefined);
Session.set('vars', []);
} }
}); });
Template.projectForm.helpers({ Template.projectForm.helpers({
@@ -51,6 +77,69 @@ Template.projectForm.helpers({
deployLink: function() { deployLink: function() {
return Meteor.absoluteUrl('deploy?token=XXXX&project_id=' + Session.get('projectToEdit')._id); return Meteor.absoluteUrl('deploy?token=XXXX&project_id=' + Session.get('projectToEdit')._id);
},
vars: function() {
return Session.get('vars');
}
});
Template.variables.events({
'click .remove': function(event) {
event.preventDefault();
var variable = Template.currentData().name
vars = Session.get('vars');
vars = _.filter(vars, function(object) {
return object.name !== variable;
});
Session.set('vars', vars);
},
'click .add': function(event) {
event.preventDefault();
var instance = Template.instance(),
name = instance.$('.name').val(),
value = instance.$('.value').val();
var variables = Session.get('vars');
variables.push({name: name, value: value});
Session.set('vars', variables);
Session.set('variables.active', undefined);
instance.$('.name').val(undefined);
instance.$('.value').val(undefined);
}
});
Template.variables.helpers({
action: function() {
return Template.currentData() ? 'remove' : 'add';
},
logo: function() {
return Template.currentData() ? 'minus' : 'plus';
},
active: function() {
var data = Template.currentData(),
active = data && data.name && data.value;
return active || Session.get('variables.active') ? '' : 'disabled';
},
readonly: function() {
return Template.currentData() ? 'readonly' : '';
}
});
Template.variables.events({
'keyup .name, keyup .value': function(event) {
var instance = Template.instance(),
name = instance.$('.name').val(),
value = instance.$('.value').val();
Session.set('variables.active', name && value);
} }
}); });
@@ -59,6 +148,7 @@ Template.project.events({
event.preventDefault(); event.preventDefault();
return Meteor.call('getProject', this._id, function(error, result) { return Meteor.call('getProject', this._id, function(error, result) {
Session.set('projectToEdit', result); Session.set('projectToEdit', result);
Session.set('vars', result.variables || []);
}); });
}, },
}); });

View File

@@ -47,17 +47,36 @@
<input type="url" class="form-control" name="public_url" placeholder="Public URL" value="{{project.public_url}}" required/> <input type="url" class="form-control" name="public_url" placeholder="Public URL" value="{{project.public_url}}" required/>
</div> </div>
</div> </div>
<div class="form-group">
<label for="variables" class="col-sm-2 control-label">
<i class="fa fa-fw fa-cogs fa-2x" title="Environment variables"></i>
</label>
<div class="col-sm-10">
{{#each vars}}
{{> variables}}
{{/each}}
{{> variables }}
</div>
</div>
<div class="form-group"> <div class="form-group">
<label for="commands" class="col-sm-2 control-label"> <label for="commands" class="col-sm-2 control-label">
<i class="fa fa-fw fa-terminal fa-2x" title="Commands"></i> <i class="fa fa-fw fa-terminal fa-2x" title="Commands"></i>
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<textarea class="form-control" cols="25" rows="5" placeholder="Commands" value="{{project.commands}}" name="commands"></textarea> <textarea class="form-control" cols="25" rows="5" placeholder="Installation commands" value="{{project.commands}}" name="commands"></textarea>
</div>
</div>
<div class="form-group">
<label for="run" class="col-sm-2 control-label">
<i class="fa fa-fw fa-play-circle-o fa-2x" title="Run"></i>
</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Run commands" value="{{project.run}}" name="run" required />
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary save">
<i class="fa fa-fw fa-floppy-o"></i> <i class="fa fa-fw fa-floppy-o"></i>
</button> </button>
<a href="#" class="btn btn-default cancel"> <a href="#" class="btn btn-default cancel">
@@ -107,3 +126,18 @@
</li> </li>
</template> </template>
<template name="variables">
<div class="row variables">
<div class="col-sm-5">
<input type="text" class="form-control name" name="name" value="{{name}}" placeholder="Name" {{readonly}}/>
</div>
<div class="col-sm-5">
<input type="text" class="form-control value" name="value" value="{{value}}" placeholder="Value" {{readonly}}/>
</div>
<div class="col-sm-1">
<button class="btn btn-default {{action}}" {{active}}>
<i class="fa fa-fw fa-{{logo}}"></i>
</button>
</div>
</div>
</template>

View File

@@ -1,5 +1,11 @@
DEPLOYMENT_FOLDER = '/home/ubuntu/deployment'; DEPLOYMENT_FOLDER = '/home/ubuntu/deployment';
STEPS = [
'CREATION',
'COMMANDS',
'RUN'
];
SCRIPTS = { SCRIPTS = {
CREATE : [ CREATE : [
{ {

View File

@@ -33,7 +33,7 @@ var exec = Npm.require('child_process').exec,
CommandRunner = { CommandRunner = {
run: function( data, callback = undefined) { run: function( data, callback = undefined) {
var bundle = _.extend({deployment: {}, project:{}, stdout: console.log, stderr: console.error, counter: 0, deploy_script: true}, data), var bundle = _.extend({deployment: {}, project:{}, stdout: console.log, stderr: console.error, counter: 0, step: 0}, data),
customs = {'%CWD%': bundle.project._id, '%GIT%': bundle.project.git_url}; customs = {'%CWD%': bundle.project._id, '%GIT%': bundle.project.git_url};
var line = bundle.script[bundle.counter], var line = bundle.script[bundle.counter],
@@ -53,11 +53,15 @@ CommandRunner = {
bundle.counter++; bundle.counter++;
if( bundle.counter >= bundle.script.length ) { if( bundle.counter >= bundle.script.length ) {
if( bundle.deploy_script && bundle.project.commands ) { if( bundle.step < 1 ) {
bundle.deploy_script = false; bundle.step++;
bundle.script = bundle.project.commands.split('\n');
bundle.counter = 0; bundle.counter = 0;
CommandRunner.commands(bundle, callback); if( bundle.project.commands ) {
bundle.script = bundle.project.commands.split('\n');
CommandRunner.commands(bundle, callback);
} else if( callback ) {
callback();
}
} else if( callback ) { } else if( callback ) {
callback(); callback();
} }
@@ -85,10 +89,38 @@ CommandRunner = {
bundle.counter++; bundle.counter++;
if( bundle.counter >= bundle.script.length ) { if( bundle.counter >= bundle.script.length ) {
callback(); if( bundle.project.run ) {
bundle.script = [bundle.project.run];
bundle.counter = 0;
CommandRunner.launch(bundle, callback);
} else {
callback();
}
} else { } else {
CommandRunner.commands(bundle, callback); CommandRunner.commands(bundle, callback);
} }
}); });
},
launch: function(bundle, callback = undefined) {
var command = bundle.script[bundle.counter],
customs = {'%CWD%': bundle.project._id},
options = {
cwd: replace('%ROOT_CWD%/%CWD%', customs),
env: {}
},
variables = bundle.project.variables;
for( var index in variables ) {
options.env[variables[index].name] = variables[index].value;
}
execSync(command, options, bundle.stdout, bundle.stderr, function(errors) {
if( callback ) {
return callback();
} else {
return;
}
});
} }
} }

View File

@@ -7,16 +7,16 @@ Meteor.methods({
return ProjectService.get(id); return ProjectService.get(id);
}, },
addProject: function(label, git_url, public_url ,commands) { addProject: function(label, git_url, public_url ,commands, run, variables) {
return ProjectService.insert(label, git_url, public_url ,commands, function(errors, id) { return ProjectService.insert(label, git_url, public_url ,commands, run, variables, function(errors, id) {
if( id ) { if( id ) {
DeploymentService.create(ProjectService.get(id)); DeploymentService.create(ProjectService.get(id));
} }
}); });
}, },
editProject: function(id, label, git_url, public_url ,commands) { editProject: function(id, label, git_url, public_url ,commands, run, variables) {
ProjectService.update(id, label, git_url, public_url ,commands, function(errors, updated_count) { ProjectService.update(id, label, git_url, public_url ,commands, run, variables, function(errors, updated_count) {
if( updated_count ) { if( updated_count ) {
DeploymentService.update(id); DeploymentService.update(id);
} }

View File

@@ -1,23 +1,27 @@
Projects = new Mongo.Collection('projects'); Projects = new Mongo.Collection('projects');
ProjectService = { ProjectService = {
insert: function(label, git_url, public_url, commands, callback) { insert: function(label, git_url, public_url, commands, run, variables, callback) {
Projects.insert({ Projects.insert({
label: label, label: label,
git_url: git_url, git_url: git_url,
public_url: public_url, public_url: public_url,
commands: commands run: run,
commands: commands,
variables: variables
}, callback); }, callback);
}, },
update: function(id, label, git_url, public_url ,commands, callback) { update: function(id, label, git_url, public_url ,commands, run, variables, callback) {
Projects.update( Projects.update(
id, id,
{ $set: { { $set: {
label: label, label: label,
git_url: git_url, git_url: git_url,
public_url: public_url, public_url: public_url,
commands: commands commands: commands,
run: run,
variables: variables
} }
}, },
callback callback