2018-01-17 09:49:38 +08:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2013-present, Facebook, Inc.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
|
|
|
*/
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
2018-02-12 03:43:29 +08:00
|
|
|
// Hi, if this is your first time editing/reading a Dangerfile, here's a summary:
|
|
|
|
// It's a JS runtime which helps you provide continuous feedback inside GitHub.
|
|
|
|
//
|
|
|
|
// You can see the docs here: http://danger.systems/js/
|
|
|
|
//
|
|
|
|
// If you want to test changes Danger, I'd recommend checking out an existing PR
|
|
|
|
// and then running the `danger pr` command.
|
|
|
|
//
|
|
|
|
// You'll need a GitHub token, you can re-use this one:
|
|
|
|
//
|
|
|
|
// e622517d9f1136ea8900 07c6373666312cdfaa69
|
|
|
|
//
|
|
|
|
// (Just remove the space)
|
|
|
|
//
|
|
|
|
// So, for example:
|
|
|
|
//
|
|
|
|
// `DANGER_GITHUB_API_TOKEN=[ENV_ABOVE] yarn danger pr https://github.com/facebook/react/pull/11865
|
|
|
|
|
2018-01-17 09:49:38 +08:00
|
|
|
const {markdown, danger} = require('danger');
|
|
|
|
const fetch = require('node-fetch');
|
|
|
|
|
|
|
|
const {generateResultsArray} = require('./scripts/rollup/stats');
|
|
|
|
const {readFileSync} = require('fs');
|
2018-02-12 03:43:29 +08:00
|
|
|
const {exec} = require('child_process');
|
2018-01-17 09:49:38 +08:00
|
|
|
|
|
|
|
const currentBuildResults = JSON.parse(
|
|
|
|
readFileSync('./scripts/rollup/results.json')
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a Markdown table
|
|
|
|
* @param {string[]} headers
|
|
|
|
* @param {string[][]} body
|
|
|
|
*/
|
|
|
|
function generateMDTable(headers, body) {
|
|
|
|
const tableHeaders = [
|
|
|
|
headers.join(' | '),
|
|
|
|
headers.map(() => ' --- ').join(' | '),
|
|
|
|
];
|
|
|
|
|
|
|
|
const tablebody = body.map(r => r.join(' | '));
|
|
|
|
return tableHeaders.join('\n') + '\n' + tablebody.join('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a user-readable string from a percentage change
|
|
|
|
* @param {string[]} headers
|
|
|
|
*/
|
2018-01-20 02:07:26 +08:00
|
|
|
function addPercent(change, includeEmoji) {
|
2018-02-22 07:48:37 +08:00
|
|
|
if (!isFinite(change)) {
|
|
|
|
// When a new package is created
|
|
|
|
return 'n/a';
|
|
|
|
}
|
|
|
|
const formatted = (change * 100).toFixed(1);
|
|
|
|
if (/^-|^0(?:\.0+)$/.test(formatted)) {
|
|
|
|
return `${formatted}%`;
|
2018-01-20 02:07:26 +08:00
|
|
|
} else {
|
2018-02-22 07:48:37 +08:00
|
|
|
if (includeEmoji) {
|
|
|
|
return `:small_red_triangle:+${formatted}%`;
|
|
|
|
} else {
|
|
|
|
return `+${formatted}%`;
|
|
|
|
}
|
2018-01-17 09:49:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-20 02:07:26 +08:00
|
|
|
function setBoldness(row, isBold) {
|
|
|
|
if (isBold) {
|
|
|
|
return row.map(element => `**${element}**`);
|
|
|
|
} else {
|
|
|
|
return row;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-12 03:43:29 +08:00
|
|
|
/**
|
|
|
|
* Gets the commit that represents the merge between the current branch
|
|
|
|
* and master.
|
|
|
|
*/
|
|
|
|
function git(args) {
|
|
|
|
return new Promise(res => {
|
|
|
|
exec('git ' + args, (err, stdout, stderr) => {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
} else {
|
|
|
|
res(stdout.trim());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
(async function() {
|
|
|
|
// Use git locally to grab the commit which represents the place
|
|
|
|
// where the branches differ
|
2018-02-15 20:19:31 +08:00
|
|
|
const upstreamRepo = danger.github.pr.base.repo.full_name;
|
|
|
|
const upstreamRef = danger.github.pr.base.ref;
|
|
|
|
await git(`remote add upstream https://github.com/${upstreamRepo}.git`);
|
|
|
|
await git('fetch upstream');
|
|
|
|
const mergeBaseCommit = await git(`merge-base HEAD upstream/${upstreamRef}`);
|
|
|
|
|
2018-02-12 03:43:29 +08:00
|
|
|
const commitURL = sha =>
|
|
|
|
`http://react.zpao.com/builds/master/_commits/${sha}/results.json`;
|
|
|
|
const response = await fetch(commitURL(mergeBaseCommit));
|
|
|
|
|
|
|
|
// Take the JSON of the build response and
|
|
|
|
// make an array comparing the results for printing
|
2018-01-17 09:49:38 +08:00
|
|
|
const previousBuildResults = await response.json();
|
|
|
|
const results = generateResultsArray(
|
|
|
|
currentBuildResults,
|
|
|
|
previousBuildResults
|
|
|
|
);
|
|
|
|
|
|
|
|
const percentToWarrentShowing = 1;
|
|
|
|
const packagesToShow = results
|
|
|
|
.filter(
|
|
|
|
r =>
|
2018-02-12 20:44:18 +08:00
|
|
|
Math.abs(r.prevFileSizeChange) >= percentToWarrentShowing ||
|
|
|
|
Math.abs(r.prevGzipSizeChange) >= percentToWarrentShowing
|
2018-01-17 09:49:38 +08:00
|
|
|
)
|
2018-02-12 03:43:29 +08:00
|
|
|
|
2018-01-17 09:49:38 +08:00
|
|
|
.map(r => r.packageName);
|
|
|
|
|
|
|
|
if (packagesToShow.length) {
|
|
|
|
let allTables = [];
|
|
|
|
|
|
|
|
// Highlight React and React DOM changes inline
|
|
|
|
// e.g. react: `react.production.min.js`: -3%, `react.development.js`: +4%
|
|
|
|
|
|
|
|
if (packagesToShow.includes('react')) {
|
|
|
|
const reactProd = results.find(
|
|
|
|
r => r.bundleType === 'UMD_PROD' && r.packageName === 'react'
|
|
|
|
);
|
|
|
|
if (
|
|
|
|
reactProd.prevFileSizeChange !== 0 ||
|
|
|
|
reactProd.prevGzipSizeChange !== 0
|
|
|
|
) {
|
2018-01-20 02:07:26 +08:00
|
|
|
const changeSize = addPercent(reactProd.prevFileSizeChange, true);
|
|
|
|
const changeGzip = addPercent(reactProd.prevGzipSizeChange, true);
|
2018-01-17 09:49:38 +08:00
|
|
|
markdown(`React: size: ${changeSize}, gzip: ${changeGzip}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (packagesToShow.includes('react-dom')) {
|
|
|
|
const reactDOMProd = results.find(
|
|
|
|
r => r.bundleType === 'UMD_PROD' && r.packageName === 'react-dom'
|
|
|
|
);
|
|
|
|
if (
|
|
|
|
reactDOMProd.prevFileSizeChange !== 0 ||
|
|
|
|
reactDOMProd.prevGzipSizeChange !== 0
|
|
|
|
) {
|
2018-01-20 02:07:26 +08:00
|
|
|
const changeSize = addPercent(reactDOMProd.prevFileSizeChange, true);
|
|
|
|
const changeGzip = addPercent(reactDOMProd.prevGzipSizeChange, true);
|
2018-01-17 09:49:38 +08:00
|
|
|
markdown(`ReactDOM: size: ${changeSize}, gzip: ${changeGzip}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show a hidden summary table for all diffs
|
|
|
|
|
2018-02-10 00:11:22 +08:00
|
|
|
// eslint-disable-next-line no-var,no-for-of-loops/no-for-of-loops
|
2018-01-17 09:49:38 +08:00
|
|
|
for (var name of new Set(packagesToShow)) {
|
|
|
|
const thisBundleResults = results.filter(r => r.packageName === name);
|
|
|
|
const changedFiles = thisBundleResults.filter(
|
2018-01-18 21:55:40 +08:00
|
|
|
r => r.prevFileSizeChange !== 0 || r.prevGzipSizeChange !== 0
|
2018-01-17 09:49:38 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
const mdHeaders = [
|
|
|
|
'File',
|
|
|
|
'Filesize Diff',
|
|
|
|
'Gzip Diff',
|
|
|
|
'Prev Size',
|
|
|
|
'Current Size',
|
|
|
|
'Prev Gzip',
|
|
|
|
'Current Gzip',
|
|
|
|
'ENV',
|
|
|
|
];
|
|
|
|
|
2018-01-20 02:07:26 +08:00
|
|
|
const mdRows = changedFiles.map(r => {
|
|
|
|
const isProd = r.bundleType.includes('PROD');
|
|
|
|
return setBoldness(
|
|
|
|
[
|
|
|
|
r.filename,
|
|
|
|
addPercent(r.prevFileSizeChange, isProd),
|
|
|
|
addPercent(r.prevGzipSizeChange, isProd),
|
|
|
|
r.prevSize,
|
|
|
|
r.prevFileSize,
|
|
|
|
r.prevGzip,
|
|
|
|
r.prevGzipSize,
|
|
|
|
r.bundleType,
|
|
|
|
],
|
|
|
|
isProd
|
|
|
|
);
|
|
|
|
});
|
2018-01-17 09:49:38 +08:00
|
|
|
|
|
|
|
allTables.push(`\n## ${name}`);
|
|
|
|
allTables.push(generateMDTable(mdHeaders, mdRows));
|
|
|
|
}
|
|
|
|
|
|
|
|
const summary = `
|
2018-02-12 03:43:29 +08:00
|
|
|
<details>
|
|
|
|
<summary>Details of bundled changes.</summary>
|
2018-01-17 09:49:38 +08:00
|
|
|
|
2018-02-12 03:43:29 +08:00
|
|
|
<p>Comparing: ${mergeBaseCommit}...${danger.github.pr.head.sha}</p>
|
2018-01-17 09:49:38 +08:00
|
|
|
|
|
|
|
|
2018-02-12 03:43:29 +08:00
|
|
|
${allTables.join('\n')}
|
2018-01-17 09:49:38 +08:00
|
|
|
|
2018-02-12 03:43:29 +08:00
|
|
|
</details>
|
|
|
|
`;
|
2018-01-17 09:49:38 +08:00
|
|
|
markdown(summary);
|
|
|
|
}
|
2018-02-12 03:43:29 +08:00
|
|
|
})();
|