1
+#!/usr/bin/env node
2
+
3
+/**
4
+ * Copyright (c) 2013-present, Facebook, Inc.
5
+ * All rights reserved.
6
+ *
7
+ * This source code is licensed under the BSD-style license found in the
8
+ * LICENSE file in the root directory of this source tree. An additional grant
9
+ * of patent rights can be found in the PATENTS file in the same directory.
10
+ */
11
+
12
+'use strict';
13
+
14
+var fs = require('fs');
15
+var path = require('path');
16
+var execSync = require('child_process').execSync;
17
+
18
+function escape(value) {
19
+ return '\'' + value.replace(/'/g, "'\\''") + '\'';
20
+}
21
+
22
+var cwd = null;
23
+function exec(command) {
24
+ console.error('>', command.replace(process.env.GITHUB_TOKEN, '************'));
25
+ return execSync(command, cwd ? {cwd: cwd} : undefined).toString();
26
+}
27
+
28
+var isInsideOfTravis = !!process.env.TRAVIS_REPO_SLUG;
29
+
30
+if (isInsideOfTravis) {
31
+ if (process.env.TRAVIS_BRANCH !== 'master') {
32
+ console.error('facts-tracker: Branch is not master, exiting...');
33
+ process.exit(0);
34
+ }
35
+
36
+ if (process.env.TRAVIS_PULL_REQUEST !== 'false') {
37
+ console.error('facts-tracker: This is a pull request, exiting...');
38
+ process.exit(0);
39
+ }
40
+
41
+ if (!process.env.GITHUB_USER || !process.env.GITHUB_TOKEN) {
42
+ console.error(
43
+ 'In order to use facts-tracker, you need to configure a ' +
44
+ 'few environment variables in order to be able to commit to the ' +
45
+ 'repository. Follow those steps to get you setup:\n' +
46
+ '\n' +
47
+ 'Go to https://github.com/settings/tokens/new\n' +
48
+ ' - Fill "Token description" with "facts-tracker for ' +
49
+ process.env.TRAVIS_REPO_SLUG + '"\n' +
50
+ ' - Check "public_repo"\n' +
51
+ ' - Press "Generate Token"\n' +
52
+ '\n' +
53
+ 'In a different tab, go to https://travis-ci.org/' +
54
+ process.env.TRAVIS_REPO_SLUG + '/settings\n' +
55
+ ' - Make sure "Build only if .travis.yml is present" is ON\n' +
56
+ ' - Fill "Name" with "GITHUB_TOKEN" and "Value" with the token you ' +
57
+ 'just generated. Press "Add"\n' +
58
+ ' - Fill "Name" with "GITHUB_USER" and "Value" with the name of the ' +
59
+ 'account you generated the token with. Press "Add"\n' +
60
+ '\n' +
61
+ 'Once this is done, commit anything to the repository to restart ' +
62
+ 'Travis and it should work :)'
63
+ );
64
+ process.exit(1);
65
+ }
66
+
67
+ exec(
68
+ 'echo "machine github.com login $GITHUB_USER password $GITHUB_TOKEN"' +
69
+ '> ~/.netrc'
70
+ );
71
+ exec(
72
+ 'git config --global user.name ' +
73
+ escape(process.env.GITHUB_USER_NAME || 'facts-tracker')
74
+ );
75
+ exec(
76
+ 'git config --global user.email ' +
77
+ escape(process.env.GITHUB_USER_EMAIL || 'facts-tracker@no-reply.github.com')
78
+ );
79
+}
80
+
81
+if (process.argv.length <= 2) {
82
+ console.error('Usage: facts-tracker <name1> <value1> <name2> <value2>...');
83
+ process.exit(1);
84
+}
85
+
86
+function getRepoSlug() {
87
+ if (isInsideOfTravis) {
88
+ return process.env.TRAVIS_REPO_SLUG;
89
+ }
90
+
91
+ var remotes = exec('git remote -v').split('\n');
92
+ for (var i = 0; i < remotes.length; ++i) {
93
+ var match = remotes[i].match(/^origin\t[^:]+:([^\.]+).+\(fetch\)/);
94
+ if (match) {
95
+ return match[1];
96
+ }
97
+ }
98
+
99
+ console.error('Cannot find repository slug, sorry.');
100
+ process.exit(1);
101
+}
102
+
103
+var repoSlug = getRepoSlug();
104
+var currentCommitHash = exec('git rev-parse HEAD').trim();
105
+var currentTimestamp = new Date().toISOString()
106
+ .replace('T', ' ')
107
+ .replace(/\..+/, '');
108
+
109
+function checkoutFactsFolder() {
110
+ var factsFolder = '../' + repoSlug.split('/')[1] + '-facts';
111
+ if (!fs.existsSync(factsFolder)) {
112
+ var escapedRepoURL;
113
+ if (isInsideOfTravis) {
114
+ escapedRepoURL = 'https://$GITHUB_TOKEN@github.com/' + escape(repoSlug) + '.git';
115
+ } else {
116
+ escapedRepoURL = escape('git@github.com:' + repoSlug + '.git');
117
+ }
118
+
119
+ exec(
120
+ 'git clone ' +
121
+ '--branch facts ' +
122
+ '--depth=5 ' +
123
+ escapedRepoURL + ' ' +
124
+ escape(factsFolder)
125
+ );
126
+ }
127
+
128
+ cwd = path.resolve(factsFolder);
129
+ exec('git fetch');
130
+ if (exec('git status --porcelain')) {
131
+ console.error('facts-tracker: `git status` is not clean, aborting.');
132
+ process.exit(1);
133
+ }
134
+ exec('git rebase origin/facts');
135
+}
136
+checkoutFactsFolder();
137
+
138
+for (var i = 2; i < process.argv.length; i += 2) {
139
+ var name = process.argv[i].trim();
140
+ var value = process.argv[i + 1];
141
+ if (value.indexOf('\n') !== -1) {
142
+ console.error(
143
+ 'facts-tracker: skipping', name,
144
+ 'as the value contains new lines:', value
145
+ );
146
+ continue;
147
+ }
148
+
149
+ var filename = name + '.txt';
150
+ try {
151
+ var lastLine = exec('tail -n 1 ' + escape(filename));
152
+ } catch (e) {
153
+ // ignore error
154
+ }
155
+ var lastValue = lastLine && lastLine
156
+ .replace(/^[^\t]+\t[^\t]+\t/, '') // commit hash \t timestamp \t
157
+ .slice(0, -1); // trailing \n
158
+
159
+ if (value !== lastValue) {
160
+ fs.appendFileSync(
161
+ path.resolve(cwd, filename),
162
+ currentCommitHash + '\t' + currentTimestamp + '\t' + value + '\n'
163
+ );
164
+ }
165
+
166
+ console.log(name);
167
+ console.log(lastValue);
168
+ console.log(value);
169
+}
170
+
171
+if (exec('git status --porcelain')) {
172
+ exec('git add --all');
173
+ exec('git commit -m ' + escape('Adding facts for ' + currentCommitHash));
174
+ exec('git push origin facts');
175
+} else {
176
+ console.error('facts-tracker: nothing to update');
177
+}
178
+cwd = null;