Register or edit a project
@@ -97,6 +101,9 @@
+
+
+
diff --git a/lib/routes.js b/lib/routes.js
index 4c42b21..4da11c0 100644
--- a/lib/routes.js
+++ b/lib/routes.js
@@ -7,13 +7,32 @@ Router.map(function () {
this.route('home', {
path: '/',
});
- this.route('management', function() {
- this.subscribe('projects').wait();
-
+ this.route('projects', {
+ waitOn: function() {
+ return Meteor.subscribe('projects');
+ },
+ action: function() {
if (this.ready()) {
this.render();
} else {
this.render('Loading');
}
+ }
+ });
+ this.route('project_details', {
+ path: '/project/:_id',
+ waitOn: function() {
+ return [Meteor.subscribe('projects', this.params._id), Meteor.subscribe('deployments', this.params._id)];
+ },
+ data: function () {
+ return ProjectService.get(this.params._id);
+ },
+ action: function() {
+ if (this.ready()) {
+ this.render();
+ } else {
+ this.render('Loading');
+ }
+ }
});
});
\ No newline at end of file
diff --git a/server/constants.js b/server/constants.js
index 9066beb..8c0a7de 100644
--- a/server/constants.js
+++ b/server/constants.js
@@ -1,6 +1,6 @@
-var DEPLOYMENT_FOLDER = 'deployment',
+DEPLOYMENT_FOLDER = '/home/ubuntu/deployment';
- SCRIPTS = {
+SCRIPTS = {
CREATE : [
{
cmd: 'mkdir %CWD%',
@@ -8,17 +8,27 @@ var DEPLOYMENT_FOLDER = 'deployment',
cwd: '%ROOT_CWD%'
}
},
- {
- cmd: 'cd %CWD%',
- options : {
- cwd: '%ROOT_CWD%'
- }
- },
{
cmd: 'git clone %GIT% .',
options : {
cwd: '%ROOT_CWD%/%CWD%'
}
}
+ ],
+ UPDATE : [
+ {
+ cmd: 'git pull',
+ options : {
+ cwd: '%ROOT_CWD%/%CWD%'
+ }
+ }
+ ],
+ DELETE : [
+ {
+ cmd: 'rm -rf %CWD%',
+ options : {
+ cwd: '%ROOT_CWD%'
+ }
+ }
]
};
\ No newline at end of file
diff --git a/server/jobs/deploy.job.js b/server/jobs/deploy.job.js
new file mode 100644
index 0000000..248c9f3
--- /dev/null
+++ b/server/jobs/deploy.job.js
@@ -0,0 +1,72 @@
+Job.processJobs('projectDeployerJobQueue', 'create_repository',
+ function(job, callback) {
+ var deployment = DeploymentService.get(job.data.deploymentId),
+ project = ProjectService.get(deployment.project_id);
+
+ DeploymentService.update_status( deployment._id, 'pending', function() {
+ CommandRunner.run(
+ {
+ script: SCRIPTS.CREATE,
+ deployment: deployment,
+ project: project,
+ stdout: function(data) {
+ DeploymentService.appendLog(job.data.deploymentId, data, false);
+ },
+ stderr: function(data) {
+ DeploymentService.appendLog(job.data.deploymentId, data, true);
+ }
+ },
+ function() {
+ if( callback ) {
+ callback();
+ }
+ }
+ );
+ });
+ }
+);
+
+Job.processJobs('projectDeployerJobQueue', 'delete_repository',
+ function(job, callback) {
+ CommandRunner.run(
+ {
+ script: SCRIPTS.DELETE,
+ project: job.data.project
+ },
+ function() {
+ if( callback ) {
+ callback();
+ }
+ }
+ );
+ }
+);
+
+Job.processJobs('projectDeployerJobQueue', 'update_repository',
+ function(job, callback) {
+ var deployment = DeploymentService.get(job.data.deploymentId),
+ project = ProjectService.get(deployment.project_id);
+
+ DeploymentService.update_status( deployment._id, 'pending', function() {
+ CommandRunner.run(
+ {
+ script: SCRIPTS.UPDATE,
+ deployment: deployment,
+ project: project,
+ stdout: function(data) {
+ DeploymentService.appendLog(job.data.deploymentId, data, false);
+ },
+ stderr: function(data) {
+ DeploymentService.appendLog(job.data.deploymentId, data, true);
+ }
+ },
+ function() {
+ if( callback ) {
+ callback();
+ }
+ }
+ );
+ });
+
+ }
+);
\ No newline at end of file
diff --git a/server/lib/command_runner.js b/server/lib/command_runner.js
index 0b5b7ad..1e6c891 100644
--- a/server/lib/command_runner.js
+++ b/server/lib/command_runner.js
@@ -1,35 +1,83 @@
var exec = Npm.require('child_process').exec,
- execSync = function(cmd, options, stdoutHandler, stderrHandler) {
+ execSync = function(cmd, options, stdoutHandler, stderrHandler, callback) {
+ stdoutHandler('$ ' + cmd);
exec(cmd,
options,
Meteor.bindEnvironment(
function(error, stdout, stderr) {
- if( stdout != '' ) {
+ if( stdout !== '' ) {
stdoutHandler(stdout);
}
if( stderr != '' ) {
stderrHandler(stderr);
}
+ callback();
}
)
);
+ },
+ replace = function(string, customs = {}) {
+ var globals = {'%ROOT_CWD%': DEPLOYMENT_FOLDER};
+ for(var key in globals) {
+ string = string.replace(key, globals[key]);
+ }
+ for(var key in customs) {
+ string = string.replace(key, customs[key]);
+ }
+
+ return string;
};
-var CommandRunner = {
- run: function( script, deployment, stdout, stderr, counter, callback ) {
- var command = script[command].cmd.replace('%ROOT_CWD%', DEPLOYMENT_FOLDER).replace('%CWD%', deployment._id),
- options = script[command].options;
- options.cwd.replace('%ROOT_CWD%', DEPLOYMENT_FOLDER).replace('%CWD%', deployment._id);
+CommandRunner = {
+ run: function( data, callback = undefined) {
+ var bundle = _.extend({deployment: {}, project:{}, stdout: console.log, stderr: console.error, counter: 0, deploy_script: true}, data),
+ customs = {'%CWD%': bundle.project._id, '%GIT%': bundle.project.git_url};
+
+ var line = bundle.script[bundle.counter],
+ command = replace(line.cmd, customs ),
+ options = line.options;
+
+ options.cwd = replace(options.cwd, customs);
- execSync(command, options, stdout, stderr, function() {
- counter++;
- if( counter > script.length ) {
- if( callback ) {
+ execSync(command, options, bundle.stdout, bundle.stderr, function() {
+ 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');
+ bundle.counter = 0;
+ CommandRunner.commands(bundle, callback);
+ } else if( callback ) {
+ if( bundle.deployment ) {
+ DeploymentService.update_status(bundle.deployment._id, 'closed', callback);
+ } else {
+ callback();
+ }
+ }
+ } else {
+ CommandRunner.run(bundle, callback);
+ }
+ });
+ },
+
+ commands: function(bundle, callback = undefined) {
+ var command = bundle.script[bundle.counter],
+ customs = {'%CWD%': bundle.project._id},
+ options = {
+ cwd: replace('%ROOT_CWD%/%CWD%', customs)
+ };
+
+ execSync(command, options, bundle.stdout, bundle.stderr, function() {
+ bundle.counter++;
+ if( bundle.counter >= bundle.script.length ) {
+ if( bundle.deployment ) {
+ DeploymentService.update_status(bundle.deployment._id, 'closed', callback);
+ } else {
callback();
}
} else {
- CommandRunner.run(script, deployment, stdout, stderr, counter, callback);
+ CommandRunner.commands(bundle, callback);
}
});
}
diff --git a/server/lib/deployment.service.js b/server/lib/deployment.service.js
index 6005586..a41b9d1 100644
--- a/server/lib/deployment.service.js
+++ b/server/lib/deployment.service.js
@@ -2,30 +2,65 @@ Deployments = new Mongo.Collection('deployments');
DeploymentService = {
get: function(id) {
- return Deployments.find({_id: id}, {date: 1});
+ return Deployments.findOne({_id: id});
},
appendLog: function(id, data, error) {
+ var deployment = DeploymentService.get(id),
+ project = ProjectService.get(deployment.project_id);
+
Deployments.update({ _id: id },{ $push: {
output: {
timestamp : new Date().getTime(),
- data : data
+ data : data.replace(new RegExp(project._id, 'g'), project.label),
+ error: error
}
}});
},
- create: function(project, callback) {
- return Deployment.insert({
- project_id: projet._id,
+
+ create: function(project) {
+ return Deployments.insert({
+ project_id: project._id,
+ timestamp: new Date().getTime(),
+ output: [],
+ status: 'opened'
+ }, function(errors, deploymentId) {
+ JobService.create_repository(deploymentId);
+ });
+ },
+
+ delete: function(projectId) {
+ Deployments.remove({project_id: projectId}, function(errors) {
+ if( !errors ) {
+ JobService.delete_repository({_id: projectId});
+ }
+ });
+ },
+
+ update: function(projectId) {
+ Deployments.insert({
+ project_id: projectId,
timestamp: new Date().getTime(),
output: []
}, function(errors, deploymentId) {
- _execSync(cmd, function(data) {
- DeploymentService.appendLog(deploymentId, data, false);
- }, function(data) {
- DeploymentService.appendLog(deploymentId, data, true);
- });
+ JobService.update_repository(deploymentId);
});
- },
+ },
+
+ update_status: function(id, status, callback) {
+ Deployments.update(
+ id,
+ { $set: {
+ status: status
+ }
+ },
+ callback
+ );
+ },
+
+ list: function(projectId) {
+ return Deployments.find({project_id: projectId}, {sort: {timestamp: -1}});
+ },
deploy: function(project) {
diff --git a/server/lib/jobs.service.js b/server/lib/jobs.service.js
new file mode 100644
index 0000000..3ef0a77
--- /dev/null
+++ b/server/lib/jobs.service.js
@@ -0,0 +1,51 @@
+var jobs = JobCollection('projectDeployerJobQueue');
+ jobs.allow({
+ // Grant full permission to any authenticated user
+ admin: function (userId, method, params) {
+ return true;
+ }
+ });
+
+jobs.startJobServer();
+
+JobService = {
+ create_repository : function(deploymentId) {
+ Job(jobs, 'create_repository',
+ {
+ deploymentId: deploymentId
+ })
+ .priority('normal')
+ .retry({
+ retries: 5,
+ wait: 10 * 1000
+ })
+ .save();
+ },
+
+ update_repository : function(deploymentId) {
+ Job(jobs, 'update_repository',
+ {
+ deploymentId: deploymentId
+ })
+ .priority('normal')
+ .retry({
+ retries: 5,
+ wait: 10 * 1000
+ })
+ .save();
+ },
+
+ delete_repository: function(project) {
+ Job(jobs, 'delete_repository',
+ {
+ project: project
+ })
+ .priority('normal')
+ .retry({
+ retries: 5,
+ wait: 10 * 1000
+ })
+ .save();
+ }
+}
+
diff --git a/server/lib/projects.methods.js b/server/lib/projects.methods.js
index e59d288..036eab5 100644
--- a/server/lib/projects.methods.js
+++ b/server/lib/projects.methods.js
@@ -10,18 +10,24 @@ Meteor.methods({
addProject: function(label, git_url, public_url ,commands) {
return ProjectService.insert(label, git_url, public_url ,commands, function(errors, id) {
if( id ) {
- /*DeploymentService.deploy(ProjectService.get(id), function(errors, deploymentId) {
-
- });*/
+ DeploymentService.create(ProjectService.get(id));
}
});
},
editProject: function(id, label, git_url, public_url ,commands) {
- ProjectService.update(id, label, git_url, public_url ,commands);
+ ProjectService.update(id, label, git_url, public_url ,commands, function(errors, updated_count) {
+ if( updated_count ) {
+ DeploymentService.update(id);
+ }
+ });
},
deleteProject: function(id) {
- ProjectService.delete(id);
+ ProjectService.delete(id, function(errors) {
+ if( ! errors ) {
+ DeploymentService.delete(id);
+ }
+ });
}
});
diff --git a/server/lib/projects.service.js b/server/lib/projects.service.js
index 950b412..1ba47a5 100644
--- a/server/lib/projects.service.js
+++ b/server/lib/projects.service.js
@@ -10,7 +10,7 @@ ProjectService = {
}, callback);
},
- update: function(id, label, git_url, public_url ,commands) {
+ update: function(id, label, git_url, public_url ,commands, callback) {
Projects.update(
id,
{ $set: {
@@ -19,12 +19,13 @@ ProjectService = {
public_url: public_url,
commands: commands
}
- }
+ },
+ callback
);
},
- delete: function(id) {
- Projects.remove(id);
+ delete: function(id, callback) {
+ Projects.remove(id, callback);
},
get: function(id) {
diff --git a/server/publications.js b/server/publications.js
index d6fa922..008efe8 100644
--- a/server/publications.js
+++ b/server/publications.js
@@ -3,5 +3,9 @@ Meteor.publish('projects', function() {
});
Meteor.publish('deployment', function(id) {
- return DeploymentService.get(id);
+ return DeploymentService.get(id);
+});
+
+Meteor.publish('deployments', function(project_id) {
+ return DeploymentService.list(project_id);
});
\ No newline at end of file