Skip to content

Commit

Permalink
Make the build / run / test process Windows-compatible by adding NPM …
Browse files Browse the repository at this point in the history
…scripts for all the tasks. (#13536)

* Make the build / run / test process Windows-compatible by adding NPM scripts for all the tasks.

This PR keeps the Makefile and all its tasks intact. So now, both systems
(NPM and make) work, but NPM is used everywhere (CircleCI, Dockerfile, css-hot-loader).

To keep the PR reasonably small, I've ommited any documentation changes.

cc/ @blowery @gziolo @gwwar @stephanethomas

* Updated check-node-version and globby to the latest version

* Reverted the Dockerfile to use the old, Makefile-based build system

* Fixed the build (broken with the merge of the "notifications panel" stuff).

* Updated shrinkwrap.
  • Loading branch information
DanReyLop authored May 24, 2017
1 parent b7fda62 commit 45dcdae
Show file tree
Hide file tree
Showing 20 changed files with 647 additions and 160 deletions.
27 changes: 27 additions & 0 deletions bin/eslint-branch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env node

/**
* Runs `eslint` only on the files the current branch modified.
* Note that this has file-level granularity, so if you modified a
* small bit of a big fail, you may get errors that weren't caused by you.
*/

const path = require( 'path' );
const child_process = require( 'child_process' );

const eslintBin = path.join( '.', 'node_modules', '.bin', 'eslint' );

const branchName = child_process.execSync( 'git rev-parse --abbrev-ref HEAD' ).toString().trim();
const rev = child_process.execSync( 'git merge-base ' + branchName + ' master' ).toString().trim();
const files = child_process.execSync( 'git diff --name-only ' + rev + '..HEAD' )
.toString()
.split( '\n' )
.map( ( name ) => name.trim() )
.filter( ( name ) => name.endsWith( '.js' ) || name.endsWith( '.jsx' ) );

const lintResult = child_process.spawnSync( eslintBin, [ '--cache', ...files ], {
shell: true,
stdio: 'inherit',
} );

process.exit( lintResult.status );
32 changes: 32 additions & 0 deletions bin/install-if-needed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env node

/**
* Performs an `npm install`. Since that's a costly operation,
* it will only perform it if needed, that is, if the packages
* installed at `node_modules` aren't in sync over what
* `npm-shrinkwrap.json` has. For that, modification times of both
* files will be compared. If the shrinkwrap is newer, it means that
* the packages at node_modules may be outdated. That will happen,
* for example, when switching branches.
*/

const fs = require( 'fs' );
const spawnSync = require( 'child_process' ).spawnSync;

const needsInstall = () => {
try {
const shrinkwrapTime = fs.statSync( 'npm-shrinkwrap.json' ).mtime;
const nodeModulesTime = fs.statSync( 'node_modules' ).mtime;
return shrinkwrapTime - nodeModulesTime > 1000; // In Windows, directory mtime has less precision than file mtime
} catch ( e ) {
return true;
}
};

if ( needsInstall() ) {
const installResult = spawnSync( 'npm', [ 'install' ], {
shell: true,
stdio: 'inherit',
});
process.exit( installResult.status );
}
30 changes: 30 additions & 0 deletions bin/pre-commit-hook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env node

const execSync = require( 'child_process' ).execSync;
const spawnSync = require( 'child_process' ).spawnSync;
const chalk = require( 'chalk' );

console.log( '\nBy contributing to this project, you license the materials you contribute ' +
'under the GNU General Public License v2 (or later). All materials must have ' +
'GPLv2 compatible licenses — see .github/CONTRIBUTING.md for details.\n\n' );

// Make quick pass over config files on every change
require( '../server/config/validate-config-keys' );

const files = execSync( 'git diff --cached --name-only' )
.toString()
.split( '\n' )
.map( ( name ) => name.trim() )
.filter( ( name ) => name.endsWith( '.js' ) || name.endsWith( '.jsx' ) );

const lintResult = spawnSync( 'node', [ 'bin/run-lint', ...files, '--', '--diff=index' ], {
shell: true,
stdio: 'inherit',
} );

if ( lintResult.status ) {
console.log( chalk.red( 'COMMIT ABORTED:' ), 'The linter reported some problems. ' +
'If you are aware of them and it is OK, ' +
'repeat the commit command with --no-verify to avoid this check.' );
process.exit( 1 );
}
16 changes: 16 additions & 0 deletions bin/pre-push-hook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env node

const execSync = require( 'child_process' ).execSync;
const readline = require( 'readline-sync' );

console.log( '\nBy contributing to this project, you license the materials you contribute ' +
'under the GNU General Public License v2 (or later). All materials must have ' +
'GPLv2 compatible licenses — see .github/CONTRIBUTING.md for details.\n\n' );

const currentBranch = execSync( 'git rev-parse --abbrev-ref HEAD' ).toString().trim();

if ( 'master' === currentBranch ) {
if ( ! readline.keyInYN( "You're about to push !!![ master ]!!!, is that what you intended?" ) ) {
process.exit( 1 );
}
}
58 changes: 58 additions & 0 deletions bin/rm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env node

/**
* Simple script to remove files. Since this will be use to clean node_modules,
* it can't have any dependency (except for the Node standard lib).
*
* Usage:
* rm.js folder
* Will delete "folder" and its contents, or do nothing if it doesn't exist
* rm.js file.ext
* Will delete the file, or do nothing if it doesn't exist
* rm.js folder .ext1 .ext2
* Will delete all the files inside "folder" that end in the given extensions
*/

const fs = require( 'fs' );

if ( process.argv.length < 3 ) {
process.exit( 1 );
}

const target = process.argv[ 2 ];
const extensions = process.argv.slice( 3 );

const deleteFolderRecursive = ( path ) => {
fs.readdirSync( path ).forEach( ( file ) => {
const curPath = path + '/' + file;
if( fs.lstatSync( curPath ).isDirectory() ) {
deleteFolderRecursive( curPath );
} else {
fs.unlinkSync( curPath );
}
} );
fs.rmdirSync( path );
};

const deleteFiles = ( path, extensions ) => {
fs.readdirSync( path ).forEach( ( file ) => {
if ( extensions
.map( ( ext ) => file.endsWith( ext ) )
.filter( Boolean )
.length ) {
fs.unlinkSync( path + '/' + file );
}
} );
};

if( fs.existsSync( target ) ) {
if( fs.lstatSync( target ).isDirectory() ) {
if ( extensions.length ) {
deleteFiles( target, extensions );
} else {
deleteFolderRecursive( target );
}
} else {
fs.unlinkSync( target );
}
}
6 changes: 3 additions & 3 deletions bin/run-lint
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var argsESLint = [ '--cache', '--quiet', '--ext=.js,.jsx', '--format=json' ];
var argsESLines = [ '--quiet' ];

const markerIndex = process.argv.indexOf('--');
if ( process.argv.length > 2 ) {
if ( process.argv.length > 2 && ( -1 === markerIndex || 2 < markerIndex ) ) {
// use -- as a marker for end of options,
// so any value that follows the marker is considered an option for ESLines.
if ( markerIndex > -1 ) {
Expand All @@ -21,8 +21,8 @@ if ( process.argv.length > 2 ) {
process.exit( 0 );
}

const eslint = child_process.spawn( path.join( '.', 'node_modules', '.bin', 'eslint' ), argsESLint );
const eslines = child_process.spawn( path.join( '.', 'node_modules', '.bin', 'eslines' ), argsESLines );
const eslint = child_process.spawn( path.join( '.', 'node_modules', '.bin', 'eslint' ), argsESLint, { shell: true } );
const eslines = child_process.spawn( path.join( '.', 'node_modules', '.bin', 'eslines' ), argsESLines, { shell: true } );

eslint.stdout.on( 'data', ( data ) => {
eslines.stdin.write( data );
Expand Down
28 changes: 28 additions & 0 deletions bin/trim-shrinkwrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env node

/**
* Removes the redundant fields on the npm-shrinkwrap.json file.
* Similar to `shonkwrap`, but rewritten to be multiplatform.
* It's plain JS with no external dependencies.
*/

const fs = require( 'fs' );
const shrinkwrap = require( '../npm-shrinkwrap.json' );

function isGitDep( rep ) {
return /^git/.test( rep );
}
function replacer( key, val ) {
if ( ! this.version ) {
return val;
}
if ( key === "from" && ! isGitDep( this.resolved ) ) {
return undefined;
}
if ( key === "resolved" && ! isGitDep( val ) && this.from !== val ) {
return undefined;
}
return val;
}

fs.writeFileSync( __dirname + '/../npm-shrinkwrap.json', JSON.stringify( shrinkwrap, replacer, 2 ) );
6 changes: 3 additions & 3 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ test:
pre:
- ? |
# make the build-server and i18n string data in parallel
if [[ "$CIRCLE_NODE_INDEX" == 0 ]]; then NODE_ENV=test make build-server; fi
if [[ "$CIRCLE_NODE_INDEX" == 0 ]]; then NODE_ENV=test npm run build-server; fi
if ( [[ "$CIRCLE_NODE_INDEX" == 1 ]] || [[ "$CIRCLE_NODE_TOTAL" == 1 ]] ) && [[ "$CIRCLE_BRANCH" == "master" ]]; then
make translate; mkdir -p $CIRCLE_ARTIFACTS/translate; mv calypso-strings.pot $CIRCLE_ARTIFACTS/translate
npm run translate; mkdir -p $CIRCLE_ARTIFACTS/translate; mv calypso-strings.pot $CIRCLE_ARTIFACTS/translate
elif [[ "$CIRCLE_NODE_INDEX" == 1 ]] || [[ "$CIRCLE_NODE_TOTAL" == 1 ]]; then
git clone https://github.com/Automattic/gp-localci-client.git
bash gp-localci-client/generate-new-strings-pot.sh $CIRCLE_BRANCH $CIRCLE_SHA1 $CIRCLE_ARTIFACTS/translate
Expand All @@ -17,7 +17,7 @@ test:
override:
- bin/run-integration :
parallel: true
- make config-defaults-lint
- npm run lint:config-defaults
- bin/run-lint :
parallel: true
files:
Expand Down
Loading

0 comments on commit 45dcdae

Please sign in to comment.