UNPKG

8.52 kBJavaScriptView Raw
1// Generated by CoffeeScript 1.6.3
2/*
3CLI to automatically deploy stuff, kind of like heroku.
4Ubuntu only! (upstart)
5
6TODO remember last command again
7TODO multiple services
8TODO multiple cron
9*/
10
11
12(function() {
13 var COMMIT_HISTORY, CONFIG, LOGS_LINES, Layer, MainConfig, VERSION, exec, finish, fs, getConfigRepo, getLayer, init, list, mainConfigPath, parseTargetAndProcessName, path, program, reponame, runProcessSpecificCommandOnLayer;
14
15 CONFIG = "ggg";
16
17 LOGS_LINES = 40;
18
19 COMMIT_HISTORY = 5;
20
21 VERSION = require("./package.json").version;
22
23 exec = require("child_process").exec;
24
25 fs = require('fs');
26
27 path = require('path');
28
29 program = require('commander');
30
31 MainConfig = require("./lib/MainConfig");
32
33 Layer = require("./lib/Layer");
34
35 parseTargetAndProcessName = function(arg) {
36 var processName, target, _ref;
37 _ref = arg.split(':'), target = _ref[0], processName = _ref[1];
38 return {
39 target: target,
40 processName: processName
41 };
42 };
43
44 program.version(VERSION).option("-l, --local <user>", "deploy locally for bootstrapping").option("-n, --noPlugin", "disable plugins");
45
46 program.command("init").description("creates a ggg.js config file for you").action(function() {
47 return init(finish);
48 });
49
50 program.command("deploy <name> [branch]").description("deploys a branch (defaults to origin/master) to named target").action(function(name, branch) {
51 return getLayer(name, function(err, layer) {
52 if (err != null) {
53 return finish(err);
54 }
55 branch = branch || "origin/master";
56 return layer.deploy(branch, finish);
57 });
58 });
59
60 runProcessSpecificCommandOnLayer = function(command) {
61 return function(name) {
62 var processName, target, _ref;
63 _ref = parseTargetAndProcessName(name), target = _ref.target, processName = _ref.processName;
64 return getLayer(target, function(err, layer) {
65 if (err != null) {
66 return finish(err);
67 }
68 if (processName) {
69 return layer[command](processName, finish);
70 } else {
71 return layer[command](finish);
72 }
73 });
74 };
75 };
76
77 program.command("restart <name:process>").description("restarts all processes associated with target.\nIf process is provided, restarts only the named process.\n`ggg restart prod` would restart all processes under the prod target\n`ggg restart prod:web` would restart only the `web` process in the `prod` target.").action(runProcessSpecificCommandOnLayer('restart'));
78
79 program.command("start <name:process>").description("starts all processes associated with target. if process is provided, starts only the named process").action(runProcessSpecificCommandOnLayer('start'));
80
81 program.command("stop <name:process>").description("stops all processes associated with name. if process is provided, stops only the named process").action(runProcessSpecificCommandOnLayer('stop'));
82
83 program.command("logs <name:process>").description("Logs " + LOGS_LINES + " lines from target and process. When no process is supplied, defaults to the first process.").option("-l, --lines <num>", "the number of lines to log").action(function(name) {
84 var processName, target, _ref;
85 _ref = parseTargetAndProcessName(name), target = _ref.target, processName = _ref.processName;
86 return getLayer(target, function(err, layer) {
87 var lines;
88 if (err != null) {
89 return finish(err);
90 }
91 lines = program.lines || LOGS_LINES;
92 if (processName) {
93 return layer.serverLogs(lines, processName, finish);
94 } else {
95 return layer.serverLogs(lines, finish);
96 }
97 });
98 });
99
100 program.command("history <name>").description("Shows a history of " + COMMIT_HISTORY + " last commits deployed").option("-r, --revisions <num>", "the number of commits to show").action(function(name) {
101 return getLayer(name, function(err, layer) {
102 var revisions;
103 if (err != null) {
104 return finish(err);
105 }
106 revisions = program.args.revisions || COMMIT_HISTORY;
107 return layer.commitHistory(revisions, finish);
108 });
109 });
110
111 program.command("command <name> <command>").description("run a command over ssh in the root of your project directory").action(function(name, command) {
112 return getLayer(name, function(err, layer) {
113 if (err != null) {
114 return finish(err);
115 }
116 return layer.runCommand(command, finish);
117 });
118 });
119
120 program.command("list").description("lists all deploy targets").action(function() {
121 return getConfigRepo(function(err, repoName, mainConfig) {
122 if (err != null) {
123 return finish(err);
124 }
125 return list(mainConfig, finish);
126 });
127 });
128
129 program.command("servers <name>").description("lists deploy server locations").action(function(name) {
130 return getLayer(name, finish);
131 });
132
133 program.command("help").description("display this help").action(function() {
134 console.log(program.helpInformation());
135 return finish();
136 });
137
138 program.command("*").action(function() {
139 return finish(new Error("bad command!"));
140 });
141
142 init = function(cb) {
143 var initConfigContent;
144 initConfigContent = "// example ggg.js. Delete what you don't need\nmodule.exports = {\n\n // services\n // can either be a string or an object with mutiple processes to start up\n start: \"node app.js\",\n /* or\n start: {\n web: 'node app.js',\n worker 'node worker.js',\n montior: 'node monitor.js'\n },\n */\n\n // install\n install: \"npm install\",\n\n // cron jobs (from your app folder)\n cron: {\n someTask: { time: \"0 3 * * *\", command: \"node sometask.js\"},\n },\n\n // servers to deploy to\n servers: {\n dev: \"deploy@dev.mycompany.com\",\n staging: [\"deploy@staging.mycompany.com\", \"deploy@staging2.mycompany.com\"],\n prod: {\n hosts: [\"deploy@mycompany.com\", \"deploy@backup.mycompany.com\"],\n cron: {\n someTask: {time: \"0 3 * * *\", command: \"node sometask.js\"},\n anotherTask: {time: \"0 3 * * *\", command: \"node secondTask.js\"}\n },\n start: \"prodstart app.js\"\n }\n }\n}";
145 console.log("GOGOGO INITIALIZING!");
146 console.log("*** Written to ggg.js ***");
147 console.log(initConfigContent);
148 return fs.writeFile(mainConfigPath() + ".js", initConfigContent, cb);
149 };
150
151 list = function(mainConfig, cb) {
152 console.log("GOGOGO servers (see ggg.js)");
153 return console.log(" - " + mainConfig.getLayerNames().join("\n - "));
154 };
155
156 reponame = function(dir, cb) {
157 return exec("git config --get remote.origin.url", {
158 cwd: dir
159 }, function(err, stdout, stderr) {
160 var url;
161 if (err != null) {
162 return cb(null, path.basename(dir));
163 } else {
164 url = stdout.replace("\n", "");
165 return cb(null, path.basename(url).replace(".git", ""));
166 }
167 });
168 };
169
170 mainConfigPath = function() {
171 return path.join(process.cwd(), CONFIG);
172 };
173
174 getConfigRepo = function(cb) {
175 return reponame(process.cwd(), function(err, repoName) {
176 if (err != null) {
177 return cb(err);
178 }
179 return MainConfig.loadFromFile(mainConfigPath(), function(err, mainConfig) {
180 var errString;
181 if (err) {
182 errString = "Bad gogogo config file, ggg.js. Run 'gogogo init' to" + (" create one. Err=" + err.message);
183 return cb(new Error(errString));
184 }
185 return cb(null, repoName, mainConfig);
186 });
187 });
188 };
189
190 getLayer = function(name, cb) {
191 return getConfigRepo(function(err, repoName, mainConfig) {
192 var layer, layerConfig;
193 if (err != null) {
194 return cb(err);
195 }
196 layerConfig = mainConfig.getLayerByName(name);
197 if (!layerConfig) {
198 return cb(new Error("Invalid layer Name: " + name));
199 }
200 if (program.noPlugin) {
201 layerConfig.plugins = null;
202 mainConfig.disablePlugins();
203 }
204 if (program.local) {
205 layerConfig.hosts = ["" + program.local + "@localhost"];
206 }
207 layer = new Layer(name, layerConfig, repoName, mainConfig, program.local);
208 layer.on("error", function(err) {
209 return cb(err);
210 });
211 return layer.on("ready", function() {
212 return cb(null, layer);
213 });
214 });
215 };
216
217 finish = function(err) {
218 if (err != null) {
219 console.log("!!! " + err.message);
220 console.log("stack follows:\n\n " + err.stack);
221 process.exit(1);
222 }
223 return console.log("OK");
224 };
225
226 module.exports = program;
227
228}).call(this);