@samitouri / QOS-React / commits / 14fd16b67b

[rrm] Improve init & config loading experience

Paul O’Shannessy committed Sep 6, 2016 at 15:22 UTC 14fd16b67bec7342ce6d3e0bda12e2b3c4c15ad4
6 files changed +63 -21
scripts/release-manager/Readme.md
+1 -1
@@ -3,7 +3,7 @@
3 This is a WIP tool that is being used to manage React releases.
4
5 General prereqs:
6 -- A separate clone of React, checked out to this branch (currently `release-manager`). This clone should be a sibling to your primary working copy of React. I have these 2 as siblings: `react/` & `react@release-manager`.
6 +- A separate clone of React, checked out to this branch (currently `release-manager`). This clone can be anywhere, so long as it is a separate working copy. Ideally this is where you are most comfortable working on React.
7 - Your `react` clone should have the latest commits fetched before running commands. You may need to rebase or reset & re-run commands if not.
8
9
scripts/release-manager/cli.js
+25 -10
@@ -5,9 +5,11 @@
5 const chalk = require('chalk');
6 const Vorpal = require('vorpal');
7 const GitHubAPI = require('github-api');
8 +const untildify = require('untildify');
9
10 const fs = require('fs');
11 const path = require('path');
12 +const os = require('os');
13
14 const child_process = require('child_process');
15 const execSync = child_process.execSync;
@@ -17,7 +19,14 @@ const vorpal = new Vorpal();
19 // Expects to be in a checkout of react that is a sibling of the react checkout you want to operate on
20 // eg ~/code/react@release-manager/scripts/release-manager & ~/code/react
21 // TODO: Make this an argument to the script
20 -const PATH_TO_REPO = path.resolve('../../../react');
22 +let PATH_TO_REPO = null;
23 +
24 +const PATH_TO_CONFIG = path.resolve(os.homedir(), '.react-release-manager.json');
25 +
26 +const DEFAULT_CONFIG = {
27 + githubToken: null,
28 + reactPath: path.resolve('../../../react'),
29 +};
30
31 // Quick dry run opt-in. This allows quick debugging of execInRepo without
32 // actually running the command, ensuring no accidental publishing.
@@ -92,24 +101,30 @@ const app = {
101 // TODO: write this. This should make it possible to start without a config
102 // and go through the init process to create one and then re-init the github
103 // setup.
104 + this.config = this.loadConfig();
105 },
106
97 - init() {
98 - // Config
107 + loadConfig() {
108 try {
100 - this.config = JSON.parse(fs.readFileSync('./.config.json', 'utf8'));
109 + // TODO: validate config
110 + let config = JSON.parse(fs.readFileSync(PATH_TO_CONFIG, 'utf8'));
111 + config.reactPath = path.normalize(untildify(config.reactPath));
112 + PATH_TO_REPO = config.reactPath;
113 + return config;
114 } catch (e) {
102 - this.config = {
103 - token: null,
104 - };
105 - console.error('Could not read .config.json. Rate limits are much stricter as a result. Run init to setup.');
115 + console.error('Attempt to load config file failed. Please run `init` command for initial setup or make sure ~/.react-release-manager.json is valid JSON. Using a default config which may not work properly.');
116 + return DEFAULT_CONFIG;
117 }
118 + },
119 +
120 + init() {
121 + this.config = this.loadConfig();
122
108 - this.PATH_TO_REPO = PATH_TO_REPO;
123 + this.PATH_TO_CONFIG = PATH_TO_CONFIG;
124
125 // GITHUB
126 this.github = new GitHubAPI({
112 - token: this.config.token,
127 + token: this.config.githubToken,
128 });
129 this.ghrepo = this.github.getRepo('facebook', 'react');
130 this.ghissues = this.github.getIssues('facebook', 'react');
scripts/release-manager/commands/init.js
+33 -7
@@ -7,15 +7,15 @@
7
8 const chalk = require('chalk');
9 const fs = require('fs');
10 +const path = require('path');
11 +const untildify = require('untildify');
12
11 -const FILENAME = '.config.json';
12 -
13 -module.exports = function(vorpal, options) {
13 +module.exports = function(vorpal, app) {
14 vorpal
15 .command('init')
16 .description('Initializes a .config.json file for use')
17 .action(function(args, cb) {
18 - fs.stat(FILENAME, (err, stats) => {
18 + fs.stat(app.PATH_TO_CONFIG, (err, stats) => {
19 if (stats) {
20 this.log('Config file exists, nothing to do.');
21 cb();
@@ -23,14 +23,40 @@ module.exports = function(vorpal, options) {
23
24 this.prompt([
25 {
26 - name: 'token',
26 + name: 'githubToken',
27 type: 'input',
28 message: `${chalk.bold('GitHub token?')} ${chalk.grey('(needs "repo" privs)')} `,
29 },
30 + {
31 + name: 'reactPath',
32 + type: 'input',
33 + message: `${chalk.bold('Location of local React checkout?')} `,
34 + validate: (input) => {
35 + let npath = path.normalize(untildify(input));
36 +
37 + if (npath === '.') {
38 + return 'Cannot be `.`';
39 + }
40 +
41 + let stats;
42 + try {
43 + stats = fs.statSync(npath);
44 + } catch (e) {
45 + return `Error: ${e}`;
46 + }
47 +
48 + if (!stats.isDirectory()) {
49 + return `${npath} is not a directory.`;
50 + }
51 +
52 + // TODO: Look for markers indicating this is a React checkout.
53 + return true;
54 + },
55 + },
56 ]).then((answers) => {
31 - fs.writeFile(FILENAME, JSON.stringify(answers, null, 2), (err) => {
57 + fs.writeFile(app.PATH_TO_CONFIG, JSON.stringify(answers, null, 2), (err) => {
58 if (err) {
33 - this.log('ERROR WRITING .config.json', err);
59 + this.log('Error writing config file.', err);
60 }
61 cb();
62 });
scripts/release-manager/commands/npm-publish.js
+1 -1
@@ -44,7 +44,7 @@ module.exports = function(vorpal, app) {
44 // just npm publish pkg1.tgz && npm publish pkg2.tgz. This
45 // avoided the need to cd and publish.
46 const tgz = glob.sync('build/packages/*.tgz', {
47 - cwd: app.PATH_TO_REPO,
47 + cwd: app.config.reactPath,
48 });
49
50 // Just in case they didn't actually prep this.
scripts/release-manager/commands/version.js
+2 -2
@@ -117,13 +117,13 @@ module.exports = function(vorpal, app) {
117 fields: ['version', 'peerDependencies.react'],
118 },
119 ].forEach((opts) => {
120 - updateJSON.apply(this, [path.join(app.PATH_TO_REPO, opts.file), opts.fields, newVersion]);
120 + updateJSON.apply(this, [path.join(app.config.reactPath, opts.file), opts.fields, newVersion]);
121 });
122
123 // We also need to update src/ReactVersion.js which has the version in
124 // string form in JS code. We'll just do a string replace.
125
126 - const PATH_TO_REACTVERSION = path.join(app.PATH_TO_REPO, 'src/ReactVersion.js');
126 + const PATH_TO_REACTVERSION = path.join(app.config.reactPath, 'src/ReactVersion.js');
127
128 let reactVersionContents = fs.readFileSync(PATH_TO_REACTVERSION, 'utf8');
129
scripts/release-manager/package.json
+1
@@ -11,6 +11,7 @@
11 "glob": "^7.0.5",
12 "opn": "^4.0.2",
13 "semver": "^5.3.0",
14 + "untildify": "^3.0.2",
15 "vorpal": "^1.10.10"
16 },
17 "devDependencies": {},