UNPKG

8.99 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3/*
4Copyright (c) 2012, Yahoo! Inc. All rights reserved.
5Code licensed under the BSD License:
6http://yuilibrary.com/license/
7*/
8
9/*jshint maxlen: 300 */
10
11var which = require('which'),
12 spawn = require('child_process').spawn,
13 exec = require('child_process').exec,
14 chalk = require('chalk'),
15 https = require('https'),
16 prompt = require('prompt'),
17 Travis = require('travis-ci'),
18 travis,
19 good = chalk.green("✔"),
20 bad = chalk.red("✖"),
21 progress = chalk.yellow("♢");
22
23if (process.platform === 'win32') {
24 good = chalk.green('OK');
25 bad = chalk.red('X');
26 progress = chalk.yellow('O');
27}
28
29exports.good = good;
30exports.bad = bad;
31
32var getInfo = function(callback) {
33 which('git', function(err, git) {
34 if (err) {
35 console.error(err);
36 process.exit(1);
37 }
38 var child = spawn(git, ['remote', '-v']),
39 user, repo;
40 child.stdout.on('data', function(data) {
41 data = data.toString().split('\n');
42 data.forEach(function(line) {
43 if (line.indexOf('origin') === 0 && !user && !repo) {
44 line = line.replace(' (fetch)', '').replace(' (push)', '');
45 var origin = line.split('\t')[1];
46 if (origin.indexOf('git@') === 0) {
47 //private repo
48 origin = origin.replace('git@github.com:', '').replace('.git', '').split('/');
49 } else if (origin.indexOf('git://') === 0) {
50 origin = origin.replace('git://github.com/', '').replace('.git', '').split('/');
51 } else if (origin.indexOf('https://') === 0) {
52 origin = origin.replace('https://github.com/', '').replace('.git', '').split('/');
53 }
54 if (origin && origin.length) {
55 user = origin[0].trim();
56 repo = origin[1].trim();
57 if (!user || !repo) {
58 throw('failed to parse git remote');
59 }
60 exec(git + ' status', {
61 cwd: process.cwd()
62 }, function(err, stdout) {
63 var branch = stdout.trim().split('\n')[0];
64 branch = branch.replace('# On branch ', '').replace('On branch ', '') || 'master';
65 callback(user, repo, branch);
66 });
67 }
68 }
69 });
70 });
71 });
72};
73
74exports.info = getInfo;
75
76var fetch = function(user, repo, branch, callback) {
77 travis.repos(user, repo).builds().get(function(err, res) {
78 if (err) {
79 return callback(err);
80 }
81 var build = res.builds || res,
82 item, other, commit, msg = null;
83
84 if (build && !build.hasOwnProperty('length')) {
85 callback('failed to fetch info for ' +user + '/' + repo);
86 return;
87 }
88
89 if (Array.isArray(res)) {
90 res.some(function(i) {
91 var ret = (i.branch === branch);
92 if (ret) {
93 item = i;
94 }
95 return ret;
96 });
97 other = res[0];
98 } else {
99 res.commits.some(function(i) {
100 var ret = (i.branch === branch);
101 if (ret) {
102 commit = i;
103 }
104 return ret;
105 });
106
107 res.builds.some(function(i) {
108 var ret = (i.commit_id === commit.id);
109 if (ret) {
110 item = i;
111 }
112 return ret;
113 });
114
115 other = res.builds[0];
116 commit = res.commits[0];
117 }
118
119 if (!item) {
120 msg = 'no recent builds on ' + branch + ' showing latest';
121 item = other;
122 }
123
124 if (!item) {
125 return callback('no item found');
126 }
127
128 callback(null, {
129 msg: msg,
130 item: item,
131 commit: commit
132 });
133 });
134
135};
136
137exports.fetch = fetch;
138
139var isPublicRepository = function (user, repo, callback) {
140 https.request({
141 method: 'HEAD',
142 host: 'api.github.com',
143 path: '/repos/' + user + '/' + repo,
144 headers: {
145 'user-agent': 'git-travis cli tool'
146 }
147 }, function (res) {
148 //Empty Data listener
149 res.on('data', function() { });
150 if (res.statusCode === 200) {
151 return callback(null, true);
152 } else if (res.statusCode === 404) {
153 return callback(null, false);
154 } else {
155 return callback('unknown');
156 }
157 }).end();
158};
159
160exports.print = function(user, repo, branch, callback) {
161 console.log('Fetching build status for', user + '/' + repo + ':' + branch);
162
163 var onFetch = function(err, data) {
164 var status, commit, item;
165
166 if (err) {
167 if (callback) {
168 return callback(err);
169 } else {
170 throw err;
171 }
172 }
173
174 if (data.msg) {
175 console.log(' ', data.msg);
176 }
177
178 commit = data.commit;
179 item = data.item;
180
181 status = (item.result ? bad : good);
182
183 if (item.status === null) {
184 status = progress;
185 }
186
187 console.log(' ', status, user + '/' + repo);
188 travis.repos(user, repo).builds(item.id).get(function(err, res) {
189 if (err) {
190 console.log(' ', bad, 'failed to fetch info for', user + '/' + repo);
191 if (callback) {
192 callback();
193 }
194 return;
195 }
196 var json = res,
197 message = json.message || json.commit.message,
198 sha = json.commit.sha || json.commit,
199 url = json.commit.compare_url || json.compare_url,
200 branch = json.branch || json.commit.branch,
201 name = json.author_name || json.commit.author_name,
202 email = json.author_email || json.commit.author_email,
203 state = json.state || json.build.state,
204 jobs = json.matrix || json.jobs;
205
206 message = message.split('\n')[0];
207 sha = sha.substring(0, 7);
208
209 console.log(' ', 'Compare: ', url);
210 console.log(' ', ((state === 'failed') ? bad : ((state === 'passed') ? good: progress)), sha, '(' + branch + ')',
211 message, '(' + name + ' <' + email + '>)', chalk.white('(' + state + ')'));
212
213 jobs.forEach(function(m) {
214 var lang = m.config.language;
215 console.log(' ', ((m.state === 'failed') ? bad : ((m.finished_at === null) ? progress : good)),
216 m.number, lang, m.config[lang], chalk.white('(' + m.state + ')'));
217 });
218 if (callback) {
219 callback();
220 }
221 });
222 },
223 travisAuthWithUsernamePassword = function (callback) {
224 prompt.start();
225 prompt.get({
226 properties: {
227 username: {
228 required: true
229 },
230 password: {
231 required: true,
232 hidden: true
233 }
234 }
235 }, function (err, result) {
236 if (err) {
237 return callback(err);
238 }
239
240 var auth = {
241 username: result.username,
242 password: result.password
243 };
244 callback(null, auth);
245 });
246 },
247 getGHToken = function () {
248 return process.env.GITHUB_ACCESS_TOKEN;
249 },
250 travisAuthWithToken = function (callback) {
251 // https://www.npmjs.com/package/travis-ci#authentication
252 var auth = {
253 github_token: getGHToken()
254 };
255 callback(null, auth);
256 },
257 hasToken = !!getGHToken();
258
259 isPublicRepository(user, repo, function (err, repositoryIsPublic) {
260 if (err) {
261 return callback(err);
262 }
263
264 travis = new Travis({
265 version: '2.0.0',
266 pro: !repositoryIsPublic
267 });
268
269 if (repositoryIsPublic) {
270 fetch(user, repo, branch, onFetch);
271 } else {
272 var travisAuthMethod = hasToken ?
273 travisAuthWithToken :
274 travisAuthWithUsernamePassword;
275
276 travisAuthMethod(function (err, authMethod) {
277 if (err) {
278 return callback(err);
279 }
280
281 travis.authenticate(authMethod, function (err) {
282 if (err) {
283 return callback(err);
284 }
285
286 console.log();
287 fetch(user, repo, branch, onFetch);
288 });
289 });
290 }
291 });
292};
293