소스 검색

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

febbweiss 10 년 전
부모
커밋
fe4ac511fc
6개의 변경된 파일193개의 추가작업 그리고 27개의 파일을 삭제
  1. 100 10
      client/projects.controller.js
  2. 36 2
      client/projects.view.html
  3. 6 0
      server/constants.js
  4. 39 7
      server/lib/command_runner.js
  5. 4 4
      server/lib/projects.methods.js
  6. 8 4
      server/lib/projects.service.js

+ 100 - 10
client/projects.controller.js

@@ -6,30 +6,54 @@ Template.projects.helpers({
 
 Template.projectForm.onRendered(function() {
    new Clipboard('.btn.clipboard');
+   Session.set('vars', []);
+   $('.variables input').val('');
 });
 
 Template.projectForm.events({
   'submit .new-project': function (event) {
       event.preventDefault();
-      var form = event.target;
+      var form = event.target,
+          variables = Session.get('vars'),
+          callback = function(errors, result) {
+            
+            if( errors ) {
+              
+            } else {
+              Session.set('projectToEdit', undefined);
+              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.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);
+        Meteor.call('addProject', 
+            form.label.value, 
+            form.git_url.value, 
+            form.public_url.value, 
+            form.commands.value, 
+            form.run.value, 
+            variables,
+            callback);
       }
-      
-      Session.set('projectToEdit', undefined);
-      form.label.value = '';
-      form.git_url.value = '';
-      form.public_url.value = '';
-      form.commands.value = '';
   },
   
   'click .cancel': function(event) {
     event.preventDefault();
     
     Session.set('projectToEdit', undefined);
+    Session.set('vars', []);
+    $('.variables input').val('');
   },
   
   'click .trash': function(event) {
@@ -37,7 +61,9 @@ Template.projectForm.events({
     
     Meteor.call('deleteProject', Session.get('projectToEdit')._id);
     Session.set('projectToEdit', undefined);
+    Session.set('vars', []);
   }
+  
 });
 
 Template.projectForm.helpers({
@@ -51,6 +77,69 @@ Template.projectForm.helpers({
   
   deployLink: function() {
     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();
     return Meteor.call('getProject', this._id, function(error, result) {
       Session.set('projectToEdit', result);
+      Session.set('vars', result.variables || []);
     });
   },
 });

+ 36 - 2
client/projects.view.html

@@ -47,17 +47,36 @@
         <input type="url" class="form-control" name="public_url" placeholder="Public URL" value="{{project.public_url}}" required/>
       </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">
         <label for="commands" class="col-sm-2 control-label">
           <i class="fa fa-fw fa-terminal fa-2x" title="Commands"></i>
         </label>
       <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 class="form-group">
       <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>
         </button>
         <a href="#" class="btn btn-default cancel">
@@ -107,3 +126,18 @@
   </li>
 </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>

+ 6 - 0
server/constants.js

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

+ 39 - 7
server/lib/command_runner.js

@@ -33,7 +33,7 @@ var exec = Npm.require('child_process').exec,
     
 CommandRunner = {
     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};
             
         var line = bundle.script[bundle.counter],
@@ -50,14 +50,18 @@ CommandRunner = {
                     return;
                 }
             }
-            
+
             bundle.counter++;
             if( bundle.counter >= bundle.script.length ) {
-                if( bundle.deploy_script && bundle.project.commands ) {
-                    bundle.deploy_script = false;
-                    bundle.script = bundle.project.commands.split('\n');
+                if( bundle.step < 1 ) {
+                    bundle.step++;
                     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 ) {
                     callback();
                 }
@@ -85,10 +89,38 @@ CommandRunner = {
             
             bundle.counter++;
             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 {
                 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;
+            }
+        });
     }
 }

+ 4 - 4
server/lib/projects.methods.js

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

+ 8 - 4
server/lib/projects.service.js

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