1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
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);
|