* refactor: fix source file name misspelling

* refactor: rename and split up locateElectronModule

* refactor: resolve package.json instead of module folder

* chore: add CFA support

* test: do not save changes from running npm in tests

* test: ensure the electron package doesn't exist

* build: replace AppVeyor with CircleCI's Windows support

* Replace ref/ffi which don't work on Node 12

* chore(deps): upgrade node-abi to ^2.11.0

* Replace benchr/microtime with deasync-promise/deasync

* Replace deasync-promise/deasync with asyncawait/fibers

* Replace srand with deasync

* Replace deasync with serialport

* @serialport/bindings, not serialport

* Replace @serialport/bindings with snappy

* Replace asyncawait/fibers with poutchdb/leveldown

* Remove only

* Replace pouchdb with level

* Replace level/leveldown with electron-markdown/cmark-gfm

* Electron 1.6 probably doesn't have node_api.h

* Replace sodium-native with farmhash

* Back to ffi/ref + move to Electron 6

* test: do not save changes from running npm in tests

* Remove .only

* Fix prebuild tests

* Set the environment variable

* Update modules yet again

* Add @types/node for running prebuild via ts-node

* Fix more tests

* Fix bcrypt

* Use a for loop instead of forEach & skip over the napi_versions key

* Remove AppVeyor config

* Remove Travis CI badge

* Revert test stdio change
This commit is contained in:
Mark Lee 2019-11-15 12:22:53 -08:00 коммит произвёл Samuel Attard
Родитель 9d669233c7
Коммит 11cb8d9e37
13 изменённых файлов: 6026 добавлений и 135 удалений

85
.circleci/config.yml Normal file
Просмотреть файл

@ -0,0 +1,85 @@
step-restore-cache: &step-restore-cache
restore_cache:
keys:
- v1-dependencies-{{ arch }}-{{ checksum "package-lock.json" }}
- v1-dependencies-{{ arch }}
steps-test: &steps-test
steps:
- checkout
- *step-restore-cache
- run:
name: Install Node
command: |
case "$(uname -s)" in
Darwin)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install 8
nvm alias default 8
echo 'export NVM_DIR=${HOME}/.nvm' >> $BASH_ENV
echo "[ -s '${NVM_DIR}/nvm.sh' ] && . '${NVM_DIR}/nvm.sh'" >> $BASH_ENV
;;
Windows*|CYGWIN*|MINGW*|MSYS*)
nvm install 12.8.0
nvm use 12.8.0
;;
esac
- run: npm install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ arch }}-{{ checksum "package-lock.json" }}
- run: npm test
version: 2.1
orbs:
win: circleci/windows@1.0.0
jobs:
test-linux-8:
docker:
- image: circleci/node:8
<<: *steps-test
test-linux-10:
docker:
- image: circleci/node:10
<<: *steps-test
test-mac:
macos:
xcode: "10.2.0"
<<: *steps-test
test-windows:
executor:
name: win/vs2019
shell: bash.exe
<<: *steps-test
release:
docker:
- image: circleci/node:10.15
steps:
- checkout
- *step-restore-cache
- run: npm install
- run: npx semantic-release
workflows:
version: 2
test_and_release:
# Run the test jobs first, then the release only when all the test jobs are successful
jobs:
- test-linux-8
- test-linux-10
- test-mac
- test-windows
- release:
requires:
- test-linux-8
- test-linux-10
- test-mac
- test-windows
filters:
branches:
only:
- master

8
.releaserc.json Normal file
Просмотреть файл

@ -0,0 +1,8 @@
{
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@continuous-auth/semantic-release-npm",
"@semantic-release/github"
]
}

Просмотреть файл

@ -1,34 +0,0 @@
language: node_js
node_js: '8'
cache: npm
os:
- linux
- osx
- windows
dist: xenial
env:
global:
- CC=clang CXX=clang++ npm_config_clang=1
branches:
only:
- master
- /^v\d+\.\d+\.\d+/
before_install:
- |
if [[ "$TRAVIS_OS_NAME" = "windows" ]]; then
choco install vcbuildtools
export NPM_CONFIG_PREFIX=c:\\custom_npm PATH="/c/custom_npm:$PATH" VCTargetsPath="C:\\Program Files (x86)\\MSBuild\\Microsoft.cpp\\v4.0\\v140"
npm install -g npm@6
npm config set msvs_version 2015 --global
fi
before_script:
# remove "electron" folder for electron-locater tests
- |
if [[ "$TRAVIS_REPO_SLUG" = "electron/electron-rebuild" ]]; then
cd ../../ && mv ./$TRAVIS_REPO_SLUG ./electron-rebuild && rm -rf ./electron && cd ./electron-rebuild/
fi

Просмотреть файл

@ -1,6 +1,6 @@
## Electron Rebuild
[![Build Status](https://travis-ci.org/electron/electron-rebuild.svg?branch=master)](https://travis-ci.org/electron/electron-rebuild)
[![CircleCI](https://circleci.com/gh/electron/electron-rebuild.svg?style=svg)](https://circleci.com/gh/electron/electron-rebuild)
[![NPM](https://img.shields.io/npm/v/electron-rebuild.svg?style=flat)](https://npm.im/electron-rebuild)
This executable rebuilds native Node.js modules against the version of Node.js

5826
package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -36,13 +36,14 @@
"debug": "^4.1.1",
"detect-libc": "^1.0.3",
"fs-extra": "^7.0.1",
"node-abi": "^2.9.0",
"node-abi": "^2.11.0",
"node-gyp": "^6.0.1",
"ora": "^3.4.0",
"spawn-rx": "^3.0.0",
"yargs": "^13.2.4"
},
"devDependencies": {
"@continuous-auth/semantic-release-npm": "^1.0.3",
"@types/chai": "^4.1.7",
"@types/chai-as-promised": "7.1.0",
"@types/debug": "^4.1.4",
@ -55,6 +56,7 @@
"cross-env": "^5.2.0",
"electron": "^2.0.18",
"mocha": "^6.1.4",
"semantic-release": "^15.13.12",
"ts-node": "^8.3.0",
"tslint": "^5.18.0",
"typescript": "^3.5.2"

Просмотреть файл

@ -7,7 +7,7 @@ import ora from 'ora';
import * as argParser from 'yargs';
import { rebuild, ModuleType } from './rebuild';
import { locateElectronPrebuilt } from './electron-locater';
import { locateElectronModule } from './electron-locator';
const yargs = argParser
.usage('Usage: electron-rebuild --version [version] --module-dir [path]')
@ -26,7 +26,7 @@ const yargs = argParser
.alias('w', 'which-module')
.describe('o', 'Only build specified module, or comma separated list of modules. All others are ignored.')
.alias('o', 'only')
.describe('e', 'The path to electron-prebuilt')
.describe('e', 'The path to prebuilt electron module')
.alias('e', 'electron-prebuilt-dir')
.describe('d', 'Custom header tarball URL')
.alias('d', 'dist-url')
@ -67,17 +67,17 @@ process.on('unhandledRejection', handler);
(async () => {
const electronPrebuiltPath = argv.e ? path.resolve(process.cwd(), (argv.e as string)) : locateElectronPrebuilt();
let electronPrebuiltVersion = argv.v as string;
const electronModulePath = argv.e ? path.resolve(process.cwd(), (argv.e as string)) : locateElectronModule();
let electronModuleVersion = argv.v as string;
if (!electronPrebuiltVersion) {
if (!electronModuleVersion) {
try {
if (!electronPrebuiltPath) throw new Error('electron-prebuilt not found');
const pkgJson = require(path.join(electronPrebuiltPath, 'package.json'));
if (!electronModulePath) throw new Error('Prebuilt electron module not found');
const pkgJson = require(path.join(electronModulePath, 'package.json'));
electronPrebuiltVersion = pkgJson.version;
electronModuleVersion = pkgJson.version;
} catch (e) {
throw new Error('Unable to find electron-prebuilt\'s version number, either install it or specify an explicit version');
throw new Error(`Unable to find electron's version number, either install it or specify an explicit version`);
}
}
@ -116,7 +116,7 @@ process.on('unhandledRejection', handler);
const rebuilder = rebuild({
buildPath: rootDirectory,
electronVersion: electronPrebuiltVersion,
electronVersion: electronModuleVersion,
arch: (argv.a as string) || process.arch,
extraModules: argv.w ? (argv.w as string).split(',') : [],
onlyModules: argv.o ? (argv.o as string).split(',') : null,

Просмотреть файл

@ -1,32 +0,0 @@
import * as fs from 'fs';
import * as path from 'path';
const possibleModuleNames = ['electron', 'electron-prebuilt', 'electron-prebuilt-compile'];
export function locateElectronPrebuilt() {
let electronPath: string | null = null;
// Attempt to locate modules by path
let foundModule = possibleModuleNames.some((moduleName) => {
electronPath = path.join(__dirname, '..', '..', '..', moduleName);
return fs.existsSync(electronPath);
});
// Return a path if we found one
if (foundModule) return electronPath;
// Attempt to locate modules by require
foundModule = possibleModuleNames.some((moduleName) => {
try {
electronPath = path.join(require.resolve(moduleName), '..');
} catch (e) {
return false;
}
return fs.existsSync(electronPath);
});
// Return a path if we found one
if (foundModule) return electronPath;
return null;
}

38
src/electron-locator.ts Normal file
Просмотреть файл

@ -0,0 +1,38 @@
import * as fs from 'fs';
import * as path from 'path';
const possibleModuleNames = ['electron', 'electron-prebuilt', 'electron-prebuilt-compile'];
const relativeNodeModulesDir = path.resolve(__dirname, '..', '..');
function locateModules(pathMapper: (moduleName: string) => string | null) {
const possibleModulePaths = possibleModuleNames.map(pathMapper);
return possibleModulePaths.filter((modulePath) => modulePath && fs.existsSync(path.join(modulePath, 'package.json')));
}
function locateSiblingModules() {
return locateModules((moduleName) => path.join(relativeNodeModulesDir, moduleName));
}
function locateModulesByRequire() {
return locateModules((moduleName) => {
try {
return path.resolve(require.resolve(path.join(moduleName, 'package.json')), '..');
} catch (error) {
return null;
}
});
}
export function locateElectronModule(): string | null {
let foundModules = locateSiblingModules();
if (foundModules.length > 0) {
return foundModules[0];
}
foundModules = locateModulesByRequire();
if (foundModules.length > 0) {
return foundModules[0];
}
return null;
}

Просмотреть файл

@ -277,11 +277,13 @@ class Rebuilder {
if (prebuildInstallPath) {
d(`triggering prebuild download step: ${path.basename(modulePath)}`);
let success = false;
const shimExt = process.env.ELECTRON_REBUILD_TESTS ? 'ts' : 'js';
const executable = process.env.ELECTRON_REBUILD_TESTS ? path.resolve(__dirname, '..', 'node_modules', '.bin', 'ts-node') : process.execPath;
try {
await spawnPromise(
process.execPath,
executable,
[
path.resolve(__dirname, 'prebuild-shim.js'),
path.resolve(__dirname, `prebuild-shim.${shimExt}`),
prebuildInstallPath,
`--arch=${this.arch}`,
`--platform=${process.platform}`,
@ -329,7 +331,11 @@ class Rebuilder {
rebuildArgs.push('--debug');
}
Object.keys(modulePackageJson.binary || {}).forEach((binaryKey) => {
for (const binaryKey of Object.keys(modulePackageJson.binary || {})) {
if (binaryKey === 'napi_versions') {
continue;
}
let value = modulePackageJson.binary[binaryKey];
if (binaryKey === 'module_path') {
@ -348,7 +354,7 @@ class Rebuilder {
});
rebuildArgs.push(`--${binaryKey}=${value}`);
});
}
if (process.env.GYP_MSVS_VERSION) {
rebuildArgs.push(`--msvs_version=${process.env.GYP_MSVS_VERSION}`);

Просмотреть файл

@ -1,12 +1,12 @@
import * as fs from 'fs';
import * as fs from 'fs-extra';
import * as path from 'path';
import { expect } from 'chai';
import { spawnPromise } from 'spawn-rx';
import { locateElectronPrebuilt } from '../src/electron-locater';
import { locateElectronModule } from '../src/electron-locator';
function packageCommand(command: string, packageName: string) {
return spawnPromise('npm', [command, packageName], {
return spawnPromise('npm', [command, '--no-save', packageName], {
cwd: path.resolve(__dirname, '..'),
stdio: 'ignore',
});
@ -17,19 +17,20 @@ const uninstall: ((s: string) => Promise<void>) = packageCommand.bind(null, 'uni
const testElectronCanBeFound = () => {
it('should return a valid path', () => {
const electronPath = locateElectronPrebuilt();
const electronPath = locateElectronModule();
expect(electronPath).to.be.a('string');
expect(fs.existsSync(electronPath!)).to.be.equal(true);
});
};
describe('locateElectronPrebuilt', function() {
describe('locateElectronModule', function() {
this.timeout(30 * 1000);
before(() => uninstall('electron'));
it('should return null when electron is not installed', () => {
expect(locateElectronPrebuilt()).to.be.equal(null);
it('should return null when electron is not installed', async () => {
await fs.remove(path.resolve(__dirname, '..', 'node_modules', 'electron'));
expect(locateElectronModule()).to.be.equal(null);
});
describe('with electron-prebuilt installed', () => {

Просмотреть файл

@ -14,15 +14,16 @@
"forge": "./forge.config.js"
},
"devDependencies": {
"ffi": "2.3.0"
"@types/node": "^12.0.10",
"ffi-napi": "2.4.5"
},
"dependencies": {
"ref": "1.3.5",
"benchr": "3.3.0",
"@newrelic/native-metrics": "4.0.0",
"sodium-native": "2.2.5"
"@nlv8/signun": "1.3.4",
"farmhash": "3.0.0",
"electron-markdown": "0.6.0",
"ref-napi": "1.4.2"
},
"optionalDependencies": {
"zipfile": "0.5.12"
"bcrypt": "3.0.6"
}
}

Просмотреть файл

@ -27,10 +27,10 @@ describe('rebuilder', () => {
name: string,
args: RebuildOptions | string[]
}[] = [
{ args: [testModulePath, '2.0.17', process.arch], name: 'sequential args' },
{ args: [testModulePath, '5.0.12', process.arch], name: 'sequential args' },
{ args: {
buildPath: testModulePath,
electronVersion: '2.0.17',
electronVersion: '5.0.12',
arch: process.arch
}, name: 'options object' }
];
@ -45,43 +45,45 @@ describe('rebuilder', () => {
if (!Array.isArray(args)) {
args = [args];
}
process.env.ELECTRON_REBUILD_TESTS = 'true';
await (<any>rebuild)(...args);
});
it('should have rebuilt top level prod dependencies', async () => {
const forgeMeta = path.resolve(testModulePath, 'node_modules', 'ref', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), 'ref build meta should exist').to.equal(true);
const forgeMeta = path.resolve(testModulePath, 'node_modules', 'ref-napi', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), 'ref-napi build meta should exist').to.equal(true);
});
it('should not have rebuild top level prod dependencies that are prebuilt', async () => {
const forgeMeta = path.resolve(testModulePath, 'node_modules', 'sodium-native', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), 'ref build meta should exist').to.equal(false);
it('should not have rebuilt top level prod dependencies that are prebuilt', async () => {
const forgeMeta = path.resolve(testModulePath, 'node_modules', 'farmhash', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), 'farmhash build meta should exist').to.equal(true);
});
it('should have rebuilt children of top level prod dependencies', async () => {
const forgeMetaGoodNPM = path.resolve(testModulePath, 'node_modules', 'microtime', 'build', 'Release', '.forge-meta');
const forgeMetaGoodNPM = path.resolve(testModulePath, 'node_modules', 'cmark-gfm', 'build', 'Release', '.forge-meta');
const forgeMetaBadNPM = path.resolve(
testModulePath, 'node_modules', 'benchr', 'node_modules', 'microtime', 'build', 'Release', '.forge-meta'
testModulePath, 'node_modules', 'electron-markdown', 'node_modules', 'cmark-gfm', 'build', 'Release', '.forge-meta'
);
expect(await fs.pathExists(forgeMetaGoodNPM) || await fs.pathExists(forgeMetaBadNPM), 'microtime build meta should exist').to.equal(true);
expect(await fs.pathExists(forgeMetaGoodNPM) || await fs.pathExists(forgeMetaBadNPM), 'cmark-gfm build meta should exist').to.equal(true);
});
it('should have rebuilt children of scoped top level prod dependencies', async () => {
const forgeMeta = path.resolve(testModulePath, 'node_modules', '@newrelic/native-metrics', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), '@newrelic/native-metrics build meta should exist').to.equal(true);
const forgeMeta = path.resolve(testModulePath, 'node_modules', '@nlv8/signun', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), '@nlv8/signun build meta should exist').to.equal(true);
});
it('should have rebuilt top level optional dependencies', async () => {
const forgeMeta = path.resolve(testModulePath, 'node_modules', 'zipfile', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), 'zipfile build meta should exist').to.equal(true);
const forgeMeta = path.resolve(testModulePath, 'node_modules', 'bcrypt', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), 'bcrypt build meta should exist').to.equal(true);
});
it('should not have rebuilt top level devDependencies', async () => {
const forgeMeta = path.resolve(testModulePath, 'node_modules', 'ffi', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), 'ffi build meta should not exist').to.equal(false);
const forgeMeta = path.resolve(testModulePath, 'node_modules', 'ffi-napi', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMeta), 'ffi-napi build meta should not exist').to.equal(false);
});
after(async () => {
delete process.env.ELECTRON_REBUILD_TESTS;
await fs.remove(testModulePath);
});
});
@ -93,19 +95,19 @@ describe('rebuilder', () => {
before(resetTestModule);
it('should skip the rebuild step when disabled', async () => {
await rebuild(testModulePath, '2.0.17', process.arch);
const rebuilder = rebuild(testModulePath, '2.0.17', process.arch, [], false);
await rebuild(testModulePath, '5.0.12', process.arch);
const rebuilder = rebuild(testModulePath, '5.0.12', process.arch, [], false);
let skipped = 0;
rebuilder.lifecycle.on('module-skip', () => {
skipped++;
});
await rebuilder;
expect(skipped).to.equal(4);
expect(skipped).to.equal(5);
});
it('should rebuild all modules again when disabled but the electron ABI bumped', async () => {
await rebuild(testModulePath, '2.0.17', process.arch);
const rebuilder = rebuild(testModulePath, '1.6.0', process.arch, [], false);
await rebuild(testModulePath, '5.0.12', process.arch);
const rebuilder = rebuild(testModulePath, '3.0.0', process.arch, [], false);
let skipped = 0;
rebuilder.lifecycle.on('module-skip', () => {
skipped++;
@ -115,8 +117,8 @@ describe('rebuilder', () => {
});
it('should rebuild all modules again when enabled', async () => {
await rebuild(testModulePath, '2.0.17', process.arch);
const rebuilder = rebuild(testModulePath, '2.0.17', process.arch, [], true);
await rebuild(testModulePath, '5.0.12', process.arch);
const rebuilder = rebuild(testModulePath, '5.0.12', process.arch, [], true);
let skipped = 0;
rebuilder.lifecycle.on('module-skip', () => {
skipped++;
@ -135,9 +137,9 @@ describe('rebuilder', () => {
it('should rebuild only specified modules', async () => {
const rebuilder = rebuild({
buildPath: testModulePath,
electronVersion: '2.0.17',
electronVersion: '5.0.12',
arch: process.arch,
onlyModules: ['ffi'],
onlyModules: ['ffi-napi'],
force: true
});
let built = 0;
@ -149,9 +151,9 @@ describe('rebuilder', () => {
it('should rebuild multiple specified modules via --only option', async () => {
const rebuilder = rebuild({
buildPath: testModulePath,
electronVersion: '2.0.17',
electronVersion: '5.0.12',
arch: process.arch,
onlyModules: ['ffi', 'ref'],
onlyModules: ['ffi-napi', 'ref-napi'], // TODO: check to see if there's a bug with scoped modules
force: true
});
let built = 0;
@ -167,20 +169,20 @@ describe('rebuilder', () => {
before(resetTestModule);
afterEach(async () => await fs.remove(testModulePath));
it('should have rebuilt ffi module in Debug mode', async () => {
it('should have rebuilt ffi-napi module in Debug mode', async () => {
const rebuilder = rebuild({
buildPath: testModulePath,
electronVersion: '2.0.17',
electronVersion: '5.0.12',
arch: process.arch,
onlyModules: ['ffi'],
onlyModules: ['ffi-napi'],
force: true,
debug: true
});
await rebuilder;
const forgeMetaDebug = path.resolve(testModulePath, 'node_modules', 'ffi', 'build', 'Debug', '.forge-meta');
expect(await fs.pathExists(forgeMetaDebug), 'ffi debug build meta should exist').to.equal(true);
const forgeMetaRelease = path.resolve(testModulePath, 'node_modules', 'ffi', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMetaRelease), 'ffi release build meta should not exist').to.equal(false);
const forgeMetaDebug = path.resolve(testModulePath, 'node_modules', 'ffi-napi', 'build', 'Debug', '.forge-meta');
expect(await fs.pathExists(forgeMetaDebug), 'ffi-napi debug build meta should exist').to.equal(true);
const forgeMetaRelease = path.resolve(testModulePath, 'node_modules', 'ffi-napi', 'build', 'Release', '.forge-meta');
expect(await fs.pathExists(forgeMetaRelease), 'ffi-napi release build meta should not exist').to.equal(false);
});
});
});