Skip to content

Commit

Permalink
Task for displaying changes of update before preparing for release
Browse files Browse the repository at this point in the history
  • Loading branch information
frenic committed Apr 27, 2018
1 parent ec4ac8e commit a7fbd63
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 49 deletions.
27 changes: 11 additions & 16 deletions build.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import * as chokidar from 'chokidar';
import * as path from 'path';
import * as prettier from 'prettier';
import { spawnPromise, writeFilePromise } from './utils';
import { FLOW_FILENAME, spawnAsync, TYPESCRIPT_FILENAME, writeFileAsync } from './utils';

const ROOT_DIR = __dirname;
const TYPESCRIPT_FILENAME = 'index.d.ts';
const FLOW_FILENAME = 'index.js.flow';
const TEST_FILENAME = 'typecheck.ts';

if (process.argv.indexOf('--watch') !== -1) {
if (process.argv.includes('--start')) {
trigger().catch(e => {
console.error(e);
process.exit(1);
});
} else if (process.argv.includes('--watch')) {
trigger()
.catch(e => {
console.error(e);
Expand All @@ -27,20 +30,15 @@ if (process.argv.indexOf('--watch') !== -1) {
);
});
});
} else {
trigger().catch(e => {
console.error(e);
process.exit(1);
});
}

async function trigger() {
export default async function trigger() {
console.info('Generating...');
const output = await create();
console.info('Formatting...');
const [flow, typescript] = await Promise.all([format(output.flow, 'flow'), format(output.typescript, 'typescript')]);
console.info(`Writing files...`);
await Promise.all([writeFilePromise(FLOW_FILENAME, flow), writeFilePromise(TYPESCRIPT_FILENAME, typescript)]);
await Promise.all([writeFileAsync(FLOW_FILENAME, flow), writeFileAsync(TYPESCRIPT_FILENAME, typescript)]);
console.info('Type checking...');
await typecheck();
}
Expand Down Expand Up @@ -72,15 +70,12 @@ async function format(output: string, parser: prettier.BuiltInParserName) {

function typecheck() {
return Promise.all([
spawnPromise(
spawnAsync(
path.join(ROOT_DIR, `node_modules/.bin/${process.platform === 'win32' ? 'tsc.cmd' : 'tsc'}`),
path.join(ROOT_DIR, TYPESCRIPT_FILENAME),
path.join(ROOT_DIR, TEST_FILENAME),
'--noEmit',
),
spawnPromise(
path.join(ROOT_DIR, `node_modules/.bin/${process.platform === 'win32' ? 'flow.cmd' : 'flow'}`),
'check',
),
spawnAsync(path.join(ROOT_DIR, `node_modules/.bin/${process.platform === 'win32' ? 'flow.cmd' : 'flow'}`), 'check'),
]);
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"scripts": {
"update": "ts-node update.ts",
"build": "ts-node build.ts",
"build": "ts-node build.ts --start",
"watch": "ts-node build.ts --watch",
"lint": "tslint --exclude node_modules/**/* --exclude **/*.d.ts --fix **/*.ts",
"pretty": "prettier --write build.ts **/*.{ts,js,json}",
Expand Down
98 changes: 74 additions & 24 deletions update.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import build from './build';
// @ts-ignore
import * as packageJson from './package.json';
import { getJson, spawnPromise, writeFilePromise } from './utils';
import { FLOW_FILENAME, getJsonAsync, questionAsync, spawnAsync, TYPESCRIPT_FILENAME, writeFileAsync } from './utils';

(async () => {
if ((await spawnPromise('git', 'status', '--porcelain')) !== '') {
if ((await spawnAsync('git', 'status', '--porcelain')) !== '') {
console.error('Your working directory needs to be clean!');
process.exit(1);
}

console.info('Checks for updates...');
console.info('Check for updates...');

const MDN_DATA = 'mdn-data';
const MDN_COMPAT = 'mdn-browser-compat-data';
Expand All @@ -17,12 +18,12 @@ import { getJson, spawnPromise, writeFilePromise } from './utils';
const [mdnCompatRepo, currentMdnCompatCommit] = packageJson.devDependencies[MDN_COMPAT].split('#');

const [mdnDataMaster, mdnCompatMaster] = [
await getJson({
await getJsonAsync({
hostname: 'api.github.com',
path: '/repos/mdn/data/branches/master',
headers: { 'User-Agent': 'NodeJS' },
}),
await getJson({
await getJsonAsync({
hostname: 'api.github.com',
path: '/repos/mdn/browser-compat-data/branches/master',
headers: { 'User-Agent': 'NodeJS' },
Expand All @@ -33,44 +34,93 @@ import { getJson, spawnPromise, writeFilePromise } from './utils';
const latestMdnCompatCommit = mdnCompatMaster.commit.sha;

if (latestMdnDataCommit !== currentMdnDataCommit || latestMdnCompatCommit !== currentMdnCompatCommit) {
console.info('Update found, upgrading and building...');
console.info('Update found!');
console.info('Upgrading...');

packageJson.devDependencies[MDN_DATA] = `${mdnDataRepo}#${latestMdnDataCommit}`;
packageJson.devDependencies[MDN_COMPAT] = `${mdnCompatRepo}#${latestMdnCompatCommit}`;

await writeFilePromise('./package.json', JSON.stringify(packageJson, null, 2) + '\n');
await writeFileAsync('./package.json', JSON.stringify(packageJson, null, 2) + '\n');
await upgrade();

try {
await spawnPromise('yarn.cmd', '--silent', '--no-progress');
await build();
} catch (e) {
console.error(e);
process.exit(1);
throw new Error(e);
}

const [indexDtsDiff, indexFlowDiff] = [
await spawnPromise('git', '--no-pager', 'diff', 'index.d.ts'),
await spawnPromise('git', '--no-pager', 'diff', 'index.js.flow'),
await spawnAsync('git', '--no-pager', 'diff', '--color', TYPESCRIPT_FILENAME),
await spawnAsync('git', '--no-pager', 'diff', '--color', FLOW_FILENAME),
];

if (indexDtsDiff !== '' || indexFlowDiff !== '') {
await spawnPromise('git', 'commit', '-am', 'Bump MDN');
console.info("Changes detected! Here's the diff:");
console.info(indexDtsDiff);
console.info(indexFlowDiff);

const [major, minor, patch] = packageJson.version.split('.');
const version = `${major}.${minor}.${Number(patch) + 1}`;
const doPrepare = await questionAsync('Do you want to prepare a release for this? (y/n) ');

packageJson.version = version;
await writeFilePromise('./package.json', JSON.stringify(packageJson, null, 2) + '\n');
await spawnPromise('git', 'commit', '-am', `v${version}`);
await spawnPromise('git', 'tag', `v${version}`);
if (doPrepare === 'y') {
await spawnAsync('git', 'commit', '-am', 'Bump MDN');

console.info('Changes detected! The changes are committed and tagged. You just need to:');
console.info('- `git push origin HEAD --tags`');
console.info('- `npm publish`');
const [major, minor, patch] = packageJson.version.split('.');
const version = `${major}.${minor}.${Number(patch) + 1}`;

const tag = `v${version}`;

packageJson.version = version;
await writeFileAsync('./package.json', JSON.stringify(packageJson, null, 2) + '\n');
await spawnAsync('git', 'commit', '-am', tag);
await spawnAsync('git', 'tag', tag);

console.info(`The changes are committed and tagged with: ${tag}`);

const doPush = await questionAsync('Do you want to push now? (y/n) ');

if (doPush === 'y') {
console.info('Pushing...');
await spawnAsync('git', 'push', 'origin', 'HEAD', '--tags');
}
} else {
console.info('Maybe next time!');
console.info('Resetting...');
await reset();
console.info('Downgrading...');
await upgrade();
}
} else {
console.info('No changes detected, resetting...');
await spawnPromise('git', 'reset', '--hard');
console.info('No changes detected!');
console.info('Resetting...');
await reset();
console.info('Downgrading...');
await upgrade();
}

process.exit(0);
} else {
console.info('Nothing to update!');
}
})();

async function reset() {
try {
await spawnAsync('git', 'reset', '--hard');
} catch (e) {
throw new Error(e);
}
}

async function upgrade() {
try {
await spawnAsync(
process.platform === 'win32' ? 'yarn.cmd' : 'yarn',
{ stdio: 'inherit' },
'--silent',
'--no-progress',
'--ignore-scripts',
);
} catch (e) {
throw new Error(e);
}
}
42 changes: 34 additions & 8 deletions utils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { spawn } from 'child_process';
import { spawn, SpawnOptions } from 'child_process';
import { writeFile } from 'fs';
import { get, RequestOptions } from 'https';
import { createInterface } from 'readline';

const ROOT_DIR = __dirname;
export const ROOT_DIR = __dirname;
export const TYPESCRIPT_FILENAME = 'index.d.ts';
export const FLOW_FILENAME = 'index.js.flow';

export function writeFilePromise(filename: string, content: string) {
export function writeFileAsync(filename: string, content: string) {
return new Promise((resolve, reject) => {
writeFile(filename, content, 'utf-8', error => {
if (error) {
Expand All @@ -16,19 +19,34 @@ export function writeFilePromise(filename: string, content: string) {
});
}

export function spawnPromise(command: string, ...args: string[]) {
export function spawnAsync(command: string, optionsOrArg: SpawnOptions | string, ...args: string[]): Promise<string> {
let options: SpawnOptions | undefined;

if (typeof optionsOrArg === 'string') {
args.unshift(optionsOrArg);
} else {
options = optionsOrArg;
}

return new Promise((resolve, reject) => {
const cp = spawn(command, args, {
cwd: ROOT_DIR,
...options,
});
let data = '';
cp.stdout.on('data', chunk => (data += chunk));
cp.on('close', code => (code === 0 ? resolve(data) : reject(data)));

if (cp.stdout) {
let data = '';
cp.stdout.on('data', chunk => (data += chunk));
cp.on('close', code => (code === 0 ? resolve(data) : reject(data)));
} else {
cp.on('close', code => (code === 0 ? resolve() : reject()));
}

cp.on('error', reject);
});
}

export function getJson(url: RequestOptions): Promise<any> {
export function getJsonAsync(url: RequestOptions): Promise<any> {
return new Promise((resolve, reject) => {
const req = get(url, res => {
let data = '';
Expand All @@ -46,3 +64,11 @@ export function getJson(url: RequestOptions): Promise<any> {
req.end();
});
}

const readline = createInterface(process.stdin, process.stdout);

export function questionAsync(message: string): Promise<string> {
return new Promise(resolve => {
readline.question(message, resolve);
});
}

0 comments on commit a7fbd63

Please sign in to comment.