diff --git a/.github/workflows/electron-linux.yml b/.github/workflows/electron-linux.yml new file mode 100644 index 000000000..5f1b0d793 --- /dev/null +++ b/.github/workflows/electron-linux.yml @@ -0,0 +1,45 @@ +name: Electron Rebuild CI - Linux (x32 & x64) + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + electron: + - 5 + - 6 + - 7 + - 8 + - 9 + include: + # includes a new variable for each electron (essentially a switch statement) + - electron: 5 + nodeVersion: 70 + - electron: 6 + nodeVersion: 73 + - electron: 7 + nodeVersion: 75 + - electron: 8 + nodeVersion: 76 + - electron: 9 + nodeVersion: 80 + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + - name: Install packages + run: npm install --unsafe-perm + env: + SKIP_SASS_BINARY_DOWNLOAD_FOR_CI: true + - name: Run build (electron force) + run: node ./scripts/build --electron-version=${{ matrix.electron }}.0.0 + - name: Check success by getting binary + uses: actions/upload-artifact@v1 + with: + name: linux-x64-${{ matrix.nodeVersion }}_binding.node + path: vendor/linux-x64-${{ matrix.nodeVersion }}/binding.node diff --git a/.github/workflows/electron-osx.yml b/.github/workflows/electron-osx.yml new file mode 100644 index 000000000..a5e4eec4a --- /dev/null +++ b/.github/workflows/electron-osx.yml @@ -0,0 +1,45 @@ +name: Electron Rebuild CI - OSX (x64) + +on: [push, pull_request] + +jobs: + build: + + runs-on: macos-latest + + strategy: + matrix: + electron: + - 5 + - 6 + - 7 + - 8 + - 9 + include: + # includes a new variable for each electron (essentially a switch statement) + - electron: 5 + nodeVersion: 70 + - electron: 6 + nodeVersion: 73 + - electron: 7 + nodeVersion: 75 + - electron: 8 + nodeVersion: 76 + - electron: 9 + nodeVersion: 80 + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + - name: Install packages + run: npm install --unsafe-perm + env: + SKIP_SASS_BINARY_DOWNLOAD_FOR_CI: true + - name: Run build (electron force) + run: node ./scripts/build --electron-version=${{ matrix.electron }}.0.0 + - name: Check success by getting binary + uses: actions/upload-artifact@v1 + with: + name: darwin-x64-${{ matrix.nodeVersion }}_binding.node + path: vendor/darwin-x64-${{ matrix.nodeVersion }}/binding.node diff --git a/.github/workflows/electron-win.yml b/.github/workflows/electron-win.yml new file mode 100644 index 000000000..625237ed2 --- /dev/null +++ b/.github/workflows/electron-win.yml @@ -0,0 +1,50 @@ +name: Electron Rebuild CI - Windows (x32 & x64) + +on: [push, pull_request] + +jobs: + build: + + runs-on: windows-latest + + strategy: + matrix: + electron: + - 5 + - 6 + - 7 + - 8 + - 9 + include: + # includes a new variable for each electron (essentially a switch statement) + - electron: 5 + nodeVersion: 70 + - electron: 6 + nodeVersion: 73 + - electron: 7 + nodeVersion: 75 + - electron: 8 + nodeVersion: 76 + - electron: 9 + nodeVersion: 80 + arch: + - ia32 + - x64 + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + with: + os: ${{ matrix.os }} + - name: Install packages + run: npm install --unsafe-perm + env: + SKIP_SASS_BINARY_DOWNLOAD_FOR_CI: true + - name: Run build (electron force) + run: node ./scripts/build --electron-version=${{ matrix.electron }}.0.0 --target_arch=${{ matrix.arch }} + - name: Check success by getting binary + uses: actions/upload-artifact@v1 + with: + name: win32-${{ matrix.arch }}-${{ matrix.nodeVersion }}_binding.pdb + path: vendor/win32-${{ matrix.arch }}-${{ matrix.nodeVersion }}/binding.node diff --git a/lib/extensions.js b/lib/extensions.js index 4f6d334ad..10173a33a 100644 --- a/lib/extensions.js +++ b/lib/extensions.js @@ -59,7 +59,7 @@ function getHumanArchitecture(arch) { * @api public */ function getHumanNodeVersion(abi) { - switch (parseInt(abi || process.versions.modules, 10)) { + switch (parseInt(abi || getModuleVersion(), 10)) { case 11: return 'Node 0.10.x'; case 14: return 'Node 0.12.x'; case 42: return 'io.js 1.x'; @@ -77,8 +77,13 @@ function getHumanNodeVersion(abi) { case 59: return 'Node.js 9.x'; case 64: return 'Node.js 10.x'; case 67: return 'Node.js 11.x'; + case 70: return 'Electron 5.x'; case 72: return 'Node.js 12.x'; + case 73: return 'Electron 6.x'; + case 75: return 'Electron 7.x'; + case 76: return 'Electron 8.x'; case 79: return 'Node.js 13.x'; + case 80: return 'Electron 9.x'; default: return false; } } @@ -181,7 +186,7 @@ function getArgument(name, args) { * @api public */ -function getBinaryName() { +function getBinaryName(arch) { var binaryName, variant, platform = process.platform; @@ -202,8 +207,8 @@ function getBinaryName() { binaryName = [ platform, '-', - process.arch, '-', - process.versions.modules + arch || process.arch, '-', + getModuleVersion() ].join(''); } @@ -240,10 +245,10 @@ function getBinaryName() { function getBinaryUrl() { var site = getArgument('--sass-binary-site') || - process.env.SASS_BINARY_SITE || - process.env.npm_config_sass_binary_site || - (pkg.nodeSassConfig && pkg.nodeSassConfig.binarySite) || - 'https://github.com/sass/node-sass/releases/download'; + process.env.SASS_BINARY_SITE || + process.env.npm_config_sass_binary_site || + (pkg.nodeSassConfig && pkg.nodeSassConfig.binarySite) || + 'https://github.com/sass/node-sass/releases/download'; return [site, 'v' + pkg.version, getBinaryName()].join('/'); } @@ -294,7 +299,7 @@ function getBinaryDir() { * @api public */ -function getBinaryPath() { +function getBinaryPath(arch) { var binaryPath; if (getArgument('--sass-binary-path')) { @@ -306,7 +311,7 @@ function getBinaryPath() { } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryPath) { binaryPath = pkg.nodeSassConfig.binaryPath; } else { - binaryPath = path.join(getBinaryDir(), getBinaryName().replace(/_(?=binding\.node)/, '/')); + binaryPath = path.join(getBinaryDir(), getBinaryName(arch).replace(/_(?=binding\.node)/, '/')); } try { @@ -326,7 +331,7 @@ function getCachePathCandidates() { return [ process.env.npm_config_sass_binary_cache, process.env.npm_config_cache, - ].filter(function(_) { return _; }); + ].filter(function (_) { return _; }); } /** @@ -437,6 +442,29 @@ function getPlatformVariant() { return ''; } +/** + * Gets the module version based on possible argument + * + * @api private + */ + +function getModuleVersion() { + const electronVersion = process.argv.slice(2).filter(function (item) { return item.substring(0, 18) === '--electron-version'; }); + if (electronVersion.length) { + switch (electronVersion[0].substring(19).split('.')[0]) { + case '5': return 70; + case '6': return 73; + case '7': return 75; + case '8': return 76; + case '9': return 80; + default: + throw new Error('We can only target electron versions 5-9'); + } + } + + return process.versions.modules; +} + module.exports.hasBinary = hasBinary; module.exports.getBinaryUrl = getBinaryUrl; module.exports.getBinaryName = getBinaryName; diff --git a/scripts/build.js b/scripts/build.js index 163c864f9..03a6db105 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -16,11 +16,11 @@ var fs = require('fs'), */ function afterBuild(options) { - var install = sass.getBinaryPath(); + var install = sass.getBinaryPath(options.arch); var target = path.join(__dirname, '..', 'build', options.debug ? 'Debug' : process.config.target_defaults - ? process.config.target_defaults.default_configuration + ? process.config.target_defaults.default_configuration : 'Release', 'binding.node'); @@ -58,23 +58,27 @@ function afterBuild(options) { function build(options) { var args = [require.resolve(path.join('node-gyp', 'bin', 'node-gyp.js')), 'rebuild', '--verbose'].concat( - ['libsass_ext', 'libsass_cflags', 'libsass_ldflags', 'libsass_library'].map(function(subject) { + ['libsass_ext', 'libsass_cflags', 'libsass_ldflags', 'libsass_library'].map(function (subject) { return ['--', subject, '=', process.env[subject.toUpperCase()] || ''].join(''); })).concat(options.args); + if (process.versions.electron || options.electronVersion) { + args.push('--target=' + (process.versions.electron || options.electronVersion), '--dist-url=https://electronjs.org/headers'); + } + console.log('Building:', [process.execPath].concat(args).join(' ')); var proc = spawn(process.execPath, args, { stdio: [0, 1, 2] }); - proc.on('exit', function(errorCode) { + proc.on('exit', function (errorCode) { if (!errorCode) { afterBuild(options); return; } - if (errorCode === 127 ) { + if (errorCode === 127) { console.error('node-gyp not found!'); } else { console.error('Build failed with error code:', errorCode); @@ -98,7 +102,7 @@ function parseArgs(args) { force: process.env.npm_config_force === 'true', }; - options.args = args.filter(function(arg) { + options.args = args.filter(function (arg) { if (arg === '-f' || arg === '--force') { options.force = true; return false; @@ -108,6 +112,9 @@ function parseArgs(args) { options.debug = true; } else if (arg.substring(0, 13) === '--libsass_ext' && arg.substring(14) !== 'no') { options.libsassExt = true; + } else if (arg.substring(0, 18) === '--electron-version') { + options.electronVersion = arg.substring(19); + return false; } return true;