Skip to content

Commit

Permalink
ci: generate diff for NPM package
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanGoncharov committed Jun 30, 2021
1 parent 4493ca3 commit 6cdc626
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 1 deletion.
23 changes: 23 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -209,6 +209,29 @@ jobs:
- name: Run Benchmark
run: 'npm run benchmark -- --revs HEAD HEAD~1'

diff-npm-package:
name: Diff context of NPM package
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
fetch-depth: 2

- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION_USED_FOR_DEVELOPMENT }}

- name: Generate report
run: 'node resources/diff-npm-package.js HEAD~1 HEAD'

- name: Upload generated report
uses: actions/upload-artifact@v2
with:
name: npm-dist-diff.html
path: ./npm-dist-diff.html

deploy-to-npm-branch:
name: Deploy to `npm` branch
runs-on: ubuntu-latest
Expand Down
106 changes: 106 additions & 0 deletions resources/diff-npm-package.js
@@ -0,0 +1,106 @@
'use strict';

const os = require('os');
const fs = require('fs');
const path = require('path');
const cp = require('child_process');

const LOCAL = 'local';
const localRepoDir = path.join(__dirname, '..');
const tmpDir = path.join(os.tmpdir(), 'graphql-js-npm-diff');
fs.rmSync(tmpDir, { recursive: true, force: true });
fs.mkdirSync(tmpDir);

const args = process.argv.slice(2);
const fromRevision = args.pop() ?? 'HEAD';
const toRevision = args.pop() ?? LOCAL;
if (args.length < 2) {
console.warn(`Assuming you meant: diff-npm-package ${fromRevision} ${toRevision}`);
}

console.log(`📦 Bulding NPM package for ${fromRevision}...`);
const fromPackage = prepareNPMPackage(fromRevision);

console.log(`📦 Bulding NPM package for ${toRevision}...`);
const toPackage = prepareNPMPackage(toRevision);

console.log(`➖➕ Generating diff...`);
const diff = exec(`npm diff --diff=${fromPackage} --diff=${toPackage}`);

if (diff === '') {
console.log('No changes found!');
} else {
const reportPath = path.join(localRepoDir, 'npm-dist-diff.html');
fs.writeFileSync(reportPath, generateReport(diff), 'utf-8');
console.log('Report saved to: ', reportPath);
}

function generateReport(diff) {
return `
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8" />
<!-- Make sure to load the highlight.js CSS file before the Diff2Html CSS file -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.1/styles/github.min.css" />
<link
rel="stylesheet"
type="text/css"
href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css"
/>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js"></script>
</head>
<script>
const diffString = ${JSON.stringify(diff)};
document.addEventListener('DOMContentLoaded', () => {
const targetElement = document.getElementById('myDiffElement');
const configuration = {
drawFileList: true,
fileListToggle: true,
fileListStartVisible: false,
fileContentToggle: true,
matching: 'lines',
outputFormat: 'side-by-side',
synchronisedScroll: true,
highlight: true,
renderNothingWhenEmpty: false,
};
const diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);
diff2htmlUi.draw();
diff2htmlUi.highlightCode();
});
</script>
<body>
<div id="myDiffElement"></div>
</body>
</html>
`;
}

function prepareNPMPackage(revision) {
if (revision === LOCAL) {
exec('npm --quiet run build:npm', { cwd: localRepoDir });
return path.join(localRepoDir, 'npmDist');
}

// Returns the complete git hash for a given git revision reference.
const hash = exec(`git rev-parse "${revision}"`);

const repoDir = path.join(tmpDir, hash);
fs.rmSync(repoDir, { recursive: true, force: true });
fs.mkdirSync(repoDir);
exec(`git archive "${hash}" | tar -xC "${repoDir}"`);
exec('npm --quiet ci', { cwd: repoDir });
exec('npm --quiet run build:npm', { cwd: repoDir });
return path.join(repoDir, 'npmDist');
}

function exec(command, options = {}) {
const result = cp.execSync(command, {
encoding: 'utf-8',
stdio: ['inherit', 'pipe', 'inherit'],
...options,
});
return result?.trimEnd();
}
2 changes: 1 addition & 1 deletion src/index.ts
Expand Up @@ -3,7 +3,7 @@
* but is also a useful utility for operating on GraphQL files and building
* sophisticated tools.
*
* This primary module exports a general purpose function for fulfilling all
* Ths primary module exports a general purpose function for fulfilling all
* steps of the GraphQL specification in a single operation, but also includes
* utilities for every part of the GraphQL specification:
*
Expand Down

0 comments on commit 6cdc626

Please sign in to comment.