Run prettier, convert to standard eslint, add CI (#138)
* Run prettier and convert to standard eslint * Add CI, fix broken test * Update package.json Co-authored-by: Lee Robinson <me@leerob.io> * switch to single quote * remove tests for now Co-authored-by: Lee Robinson <me@leerob.io>
This commit is contained in:
parent
93431471c6
commit
f7a75173f9
20
.eslintrc
Normal file
20
.eslintrc
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": ["airbnb-base", "prettier"],
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"wrap-iife": "off",
|
||||
"no-bitwise": "off",
|
||||
"no-continue": "off",
|
||||
"class-methods-use-this": "off",
|
||||
"no-await-in-loop": "off",
|
||||
"no-constant-condition": "off",
|
||||
"no-param-reassign": "off",
|
||||
"consistent-return": "off",
|
||||
"no-restricted-syntax": "off",
|
||||
"import/prefer-default-export": "off",
|
||||
"camelcase": "off"
|
||||
}
|
||||
}
|
||||
39
.github/workflows/ci.yml
vendored
Normal file
39
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
fail-fast: false # prevent test to stop if one fails
|
||||
matrix:
|
||||
node-version: [10.x, 12.x, 14.x]
|
||||
os: [ubuntu-latest] # Skip macos-latest, windows-latest for now
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2.1.5
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.pkg-cache/
|
||||
key: ${{ matrix.os }}-${{ matrix.node-version }}
|
||||
|
||||
- name: Install deps
|
||||
run: yarn install
|
||||
|
||||
- name: Lint
|
||||
if: matrix['node-version'] == '14.x' && matrix['os'] == 'ubuntu-latest'
|
||||
run: yarn lint
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
1
.prettierignore
Normal file
1
.prettierignore
Normal file
@ -0,0 +1 @@
|
||||
lib-es5
|
||||
19
lib/bin.js
19
lib/bin.js
@ -1,21 +1,26 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { log } from './log.js';
|
||||
import minimist from 'minimist';
|
||||
import { need } from './index.js';
|
||||
import { log } from './log';
|
||||
import { need } from './index';
|
||||
|
||||
async function main () {
|
||||
async function main() {
|
||||
const argv = minimist(process.argv.slice(2), {
|
||||
boolean: [ 'f', 'b' ],
|
||||
string: [ 'n', 'p', 'a' ]
|
||||
boolean: ['f', 'b'],
|
||||
string: ['n', 'p', 'a'],
|
||||
});
|
||||
const nodeRange = argv.n || argv._.shift();
|
||||
const platform = argv.p || argv._.shift();
|
||||
const arch = argv.a || argv._.shift();
|
||||
const forceFetch = argv.f;
|
||||
const forceBuild = argv.b;
|
||||
const local = await need({ nodeRange, platform,
|
||||
arch, forceFetch, forceBuild });
|
||||
const local = await need({
|
||||
nodeRange,
|
||||
platform,
|
||||
arch,
|
||||
forceFetch,
|
||||
forceBuild,
|
||||
});
|
||||
log.info(local);
|
||||
}
|
||||
|
||||
|
||||
69
lib/build.js
69
lib/build.js
@ -1,12 +1,13 @@
|
||||
import os from 'os';
|
||||
import { mkdirp, remove } from 'fs-extra';
|
||||
import { progress, spawn } from './spawn.js';
|
||||
import { copyFile } from './copy-file.js';
|
||||
import { hostPlatform } from './system.js';
|
||||
import { log } from './log.js';
|
||||
import patchesJson from '../patches/patches.json';
|
||||
import path from 'path';
|
||||
import { tempPath } from './temp-path.js';
|
||||
import thresholds from './thresholds.js';
|
||||
import { progress, spawn } from './spawn';
|
||||
import { copyFile } from './copy-file';
|
||||
import { hostPlatform } from './system';
|
||||
import { log } from './log';
|
||||
import patchesJson from '../patches/patches.json';
|
||||
import { tempPath } from './temp-path';
|
||||
import thresholds from './thresholds';
|
||||
|
||||
let buildPath;
|
||||
if (process.env.GITHUB_USERNAME) {
|
||||
@ -19,35 +20,46 @@ const nodePath = path.join(buildPath, 'node');
|
||||
const patchesPath = path.resolve(__dirname, '../patches');
|
||||
const nodeRepo = 'https://github.com/nodejs/node';
|
||||
|
||||
async function gitClone (nodeVersion) {
|
||||
async function gitClone(nodeVersion) {
|
||||
log.info('Cloning Node.js repository from GitHub...');
|
||||
const args = [ 'clone', '-b', nodeVersion, '--depth', '1', '--single-branch', '--bare', '--progress', nodeRepo, 'node/.git' ];
|
||||
const args = [
|
||||
'clone',
|
||||
'-b',
|
||||
nodeVersion,
|
||||
'--depth',
|
||||
'1',
|
||||
'--single-branch',
|
||||
'--bare',
|
||||
'--progress',
|
||||
nodeRepo,
|
||||
'node/.git',
|
||||
];
|
||||
const promise = spawn('git', args, { cwd: buildPath });
|
||||
progress(promise, thresholds('clone'));
|
||||
await promise;
|
||||
}
|
||||
|
||||
async function gitResetHard (nodeVersion) {
|
||||
async function gitResetHard(nodeVersion) {
|
||||
log.info(`Checking out ${nodeVersion}`);
|
||||
const patches = patchesJson[nodeVersion];
|
||||
const commit = patches.commit || nodeVersion;
|
||||
const args = [ '--work-tree', '.', 'reset', '--hard', commit ];
|
||||
const args = ['--work-tree', '.', 'reset', '--hard', commit];
|
||||
await spawn('git', args, { cwd: nodePath });
|
||||
}
|
||||
|
||||
async function applyPatches (nodeVersion) {
|
||||
async function applyPatches(nodeVersion) {
|
||||
log.info('Applying patches');
|
||||
let patches = patchesJson[nodeVersion];
|
||||
patches = patches.patches || patches;
|
||||
if (patches.sameAs) patches = patchesJson[patches.sameAs];
|
||||
for (const patch of patches) {
|
||||
const patchPath = path.join(patchesPath, patch);
|
||||
const args = [ '-p1', '-i', patchPath ];
|
||||
const args = ['-p1', '-i', patchPath];
|
||||
await spawn('patch', args, { cwd: nodePath });
|
||||
}
|
||||
}
|
||||
|
||||
async function compileOnWindows (nodeVersion, targetArch) {
|
||||
async function compileOnWindows(nodeVersion, targetArch) {
|
||||
const args = [];
|
||||
args.push('/c', 'vcbuild.bat', targetArch, 'noetw');
|
||||
const major = nodeVersion.match(/^v?(\d+)/)[1] | 0;
|
||||
@ -59,12 +71,19 @@ async function compileOnWindows (nodeVersion, targetArch) {
|
||||
return path.join(nodePath, 'out/Release/node.exe');
|
||||
}
|
||||
|
||||
const { MAKE_JOB_COUNT = require('os').cpus().length } = process.env;
|
||||
const { MAKE_JOB_COUNT = os.cpus().length } = process.env;
|
||||
|
||||
async function compileOnUnix (nodeVersion, targetArch) {
|
||||
async function compileOnUnix(nodeVersion, targetArch) {
|
||||
const args = [];
|
||||
const cpu = { x86: 'ia32', x64: 'x64',
|
||||
armv6: 'arm', armv7: 'arm', arm64: 'arm64', ppc64: 'ppc64', s390x: 's390x' }[targetArch];
|
||||
const cpu = {
|
||||
x86: 'ia32',
|
||||
x64: 'x64',
|
||||
armv6: 'arm',
|
||||
armv7: 'arm',
|
||||
arm64: 'arm64',
|
||||
ppc64: 'ppc64',
|
||||
s390x: 's390x',
|
||||
}[targetArch];
|
||||
args.push('--dest-cpu', cpu);
|
||||
// first of all v8_inspector introduces the use
|
||||
// of `prime_rehash_policy` symbol that requires
|
||||
@ -78,25 +97,23 @@ async function compileOnUnix (nodeVersion, targetArch) {
|
||||
// TODO same for windows?
|
||||
await spawn('./configure', args, { cwd: nodePath });
|
||||
const make = hostPlatform === 'freebsd' ? 'gmake' : 'make';
|
||||
const promise = spawn(make, [ '-j', MAKE_JOB_COUNT ], { cwd: nodePath });
|
||||
const promise = spawn(make, ['-j', MAKE_JOB_COUNT], { cwd: nodePath });
|
||||
progress(promise, thresholds('make', nodeVersion));
|
||||
await promise;
|
||||
const output = path.join(nodePath, 'out/Release/node');
|
||||
// https://github.com/mhart/alpine-node/blob/base-7.4.0/Dockerfile#L36
|
||||
if (hostPlatform === 'alpine') await spawn('paxctl', [ '-cm', output ]);
|
||||
if (hostPlatform === 'alpine') await spawn('paxctl', ['-cm', output]);
|
||||
return output;
|
||||
}
|
||||
|
||||
async function compile (nodeVersion, targetArch) {
|
||||
async function compile(nodeVersion, targetArch) {
|
||||
log.info('Compiling Node.js from sources...');
|
||||
const win = hostPlatform === 'win';
|
||||
if (win) return await compileOnWindows(nodeVersion, targetArch);
|
||||
return await compileOnUnix(nodeVersion, targetArch);
|
||||
if (win) return compileOnWindows(nodeVersion, targetArch);
|
||||
return compileOnUnix(nodeVersion, targetArch);
|
||||
}
|
||||
|
||||
export default async function build (
|
||||
nodeVersion, targetArch, local
|
||||
) {
|
||||
export default async function build(nodeVersion, targetArch, local) {
|
||||
await remove(buildPath);
|
||||
await mkdirp(buildPath);
|
||||
await gitClone(nodeVersion);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { chmod, stat } from 'fs-extra';
|
||||
|
||||
export async function plusx (file) {
|
||||
export async function plusx(file) {
|
||||
const s = await stat(file);
|
||||
const newMode = s.mode | 64 | 8 | 1;
|
||||
if (s.mode === newMode) return;
|
||||
|
||||
30
lib/cloud.js
30
lib/cloud.js
@ -1,10 +1,12 @@
|
||||
import { mkdirp, remove } from 'fs-extra';
|
||||
import { GitHub } from './github.js';
|
||||
import assert from 'assert';
|
||||
import { moveFile } from './copy-file.js';
|
||||
import path from 'path';
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
|
||||
function uniqueName (name, names) {
|
||||
import { mkdirp, remove } from 'fs-extra';
|
||||
import assert from 'assert';
|
||||
import path from 'path';
|
||||
import { GitHub } from './github';
|
||||
import { moveFile } from './copy-file';
|
||||
|
||||
function uniqueName(name, names) {
|
||||
if (names.indexOf(name) < 0) return name;
|
||||
let newName;
|
||||
let counter = 0;
|
||||
@ -16,18 +18,18 @@ function uniqueName (name, names) {
|
||||
}
|
||||
|
||||
export class Cloud {
|
||||
constructor ({ owner, repo }) {
|
||||
constructor({ owner, repo }) {
|
||||
this.gh = new GitHub({ owner, repo });
|
||||
}
|
||||
|
||||
async _findRelease (tag) {
|
||||
async _findRelease(tag) {
|
||||
let release = await this.gh.getRelease(tag);
|
||||
if (!release) release = await this.gh.getReleaseDraft(tag);
|
||||
if (!release) release = await this.gh.createRelease(tag);
|
||||
return release;
|
||||
}
|
||||
|
||||
async alreadyUploaded (remote) {
|
||||
async alreadyUploaded(remote) {
|
||||
const release = await this._findRelease(remote.tag);
|
||||
return release.assets.some(({ name }) => {
|
||||
assert(name);
|
||||
@ -35,7 +37,7 @@ export class Cloud {
|
||||
});
|
||||
}
|
||||
|
||||
async upload (local, remote) {
|
||||
async upload(local, remote) {
|
||||
const release = await this._findRelease(remote.tag);
|
||||
const names = release.assets.map(({ name }) => {
|
||||
assert(name);
|
||||
@ -45,16 +47,16 @@ export class Cloud {
|
||||
await this.gh.uploadAsset(local, release, name);
|
||||
}
|
||||
|
||||
async uploadMany (items) {
|
||||
async uploadMany(items) {
|
||||
for (const item of items) {
|
||||
const { local, remote } = item;
|
||||
await this.upload(local, remote);
|
||||
}
|
||||
}
|
||||
|
||||
async download (remote, local) {
|
||||
async download(remote, local) {
|
||||
const { tag } = remote;
|
||||
const tempFile = local + '.downloading';
|
||||
const tempFile = `${local}.downloading`;
|
||||
await mkdirp(path.dirname(tempFile));
|
||||
const short = path.basename(local);
|
||||
const ok = await this.gh.tryDirectly(tag, remote.name, tempFile, short);
|
||||
@ -77,7 +79,7 @@ export class Cloud {
|
||||
return true;
|
||||
}
|
||||
|
||||
async downloadMany (items) {
|
||||
async downloadMany(items) {
|
||||
for (const item of items) {
|
||||
const { remote, local } = item;
|
||||
await this.download(remote, local);
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import fs from 'fs-extra';
|
||||
|
||||
export function copyFile (src, dest) {
|
||||
export function copyFile(src, dest) {
|
||||
return fs.copy(src, dest);
|
||||
}
|
||||
|
||||
export function moveFile (src, dest) {
|
||||
export function moveFile(src, dest) {
|
||||
return fs.move(src, dest);
|
||||
}
|
||||
|
||||
@ -1,25 +1,27 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
import { log, wasReported } from './log.js';
|
||||
import assert from 'assert';
|
||||
import fs from 'fs';
|
||||
import progress from 'request-progress';
|
||||
import request from 'request';
|
||||
import { log, wasReported } from './log';
|
||||
|
||||
export class GitHub {
|
||||
constructor ({ owner, repo }) {
|
||||
constructor({ owner, repo }) {
|
||||
this.owner = owner;
|
||||
this.repo = repo;
|
||||
const { GITHUB_USERNAME, GITHUB_PASSWORD } = process.env;
|
||||
const auth = { user: GITHUB_USERNAME, pass: GITHUB_PASSWORD };
|
||||
this.request = request.defaults({
|
||||
auth: auth.user ? auth : undefined,
|
||||
headers: { 'User-Agent': `${this.owner}/${this.repo}/${GITHUB_USERNAME}` },
|
||||
timeout: 30 * 1000
|
||||
headers: {
|
||||
'User-Agent': `${this.owner}/${this.repo}/${GITHUB_USERNAME}`,
|
||||
},
|
||||
timeout: 30 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
getRelease (tag) {
|
||||
getRelease(tag) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `https://api.github.com/repos/${this.owner}/${this.repo}/releases/tags/${tag}`;
|
||||
this.request(url, (error, response, body) => {
|
||||
@ -33,7 +35,7 @@ export class GitHub {
|
||||
});
|
||||
}
|
||||
|
||||
getReleaseDraft (tag) {
|
||||
getReleaseDraft(tag) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `https://api.github.com/repos/${this.owner}/${this.repo}/releases`;
|
||||
this.request(url, (error, response, body) => {
|
||||
@ -52,14 +54,14 @@ export class GitHub {
|
||||
});
|
||||
}
|
||||
|
||||
createRelease (tag) {
|
||||
createRelease(tag) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const form = JSON.stringify({
|
||||
tag_name: tag,
|
||||
target_commitish: 'master', // TODO maybe git rev-parse HEAD
|
||||
name: tag,
|
||||
draft: true,
|
||||
prerelease: true
|
||||
prerelease: true,
|
||||
});
|
||||
const url = `https://api.github.com/repos/${this.owner}/${this.repo}/releases`;
|
||||
this.request.post(url, { form }, (error, response, body) => {
|
||||
@ -71,54 +73,65 @@ export class GitHub {
|
||||
});
|
||||
}
|
||||
|
||||
uploadAsset (file, release, name) {
|
||||
assert(!(/[\\/]/.test(name)));
|
||||
uploadAsset(file, release, name) {
|
||||
assert(!/[\\/]/.test(name));
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.stat(file, (error, stat) => {
|
||||
if (error) return reject(error);
|
||||
const headers = {
|
||||
'Content-Length': stat.size,
|
||||
'Content-Type': 'application/octet-stream'
|
||||
'Content-Type': 'application/octet-stream',
|
||||
};
|
||||
const rs = fs.createReadStream(file);
|
||||
const subst = `?name=${name}`;
|
||||
const url = release.upload_url.replace(/\{\?name,label\}/, subst);
|
||||
const req = this.request.post(url, {
|
||||
headers, timeout: 30 * 60 * 1000
|
||||
}, (error2, response, body) => {
|
||||
if (error2) return reject(wasReported(error2.message));
|
||||
const asset = JSON.parse(body);
|
||||
const { errors } = asset;
|
||||
if (errors && errors[0]) return reject(wasReported(errors[0].code));
|
||||
if (asset.message) return reject(wasReported(asset.message));
|
||||
resolve(asset);
|
||||
});
|
||||
const req = this.request.post(
|
||||
url,
|
||||
{
|
||||
headers,
|
||||
timeout: 30 * 60 * 1000,
|
||||
},
|
||||
(error2, response, body) => {
|
||||
if (error2) return reject(wasReported(error2.message));
|
||||
const asset = JSON.parse(body);
|
||||
const { errors } = asset;
|
||||
if (errors && errors[0]) return reject(wasReported(errors[0].code));
|
||||
if (asset.message) return reject(wasReported(asset.message));
|
||||
resolve(asset);
|
||||
}
|
||||
);
|
||||
rs.pipe(req);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
downloadUrl (url, file, short) {
|
||||
downloadUrl(url, file, short) {
|
||||
log.enableProgress(short);
|
||||
log.showProgress(0);
|
||||
return new Promise((resolve, reject) => {
|
||||
const headers = { Accept: 'application/octet-stream' };
|
||||
const ws = fs.createWriteStream(file);
|
||||
let result;
|
||||
const req = progress(this.request.get(url, {
|
||||
headers
|
||||
}, (error, response) => {
|
||||
if (error) {
|
||||
log.disableProgress();
|
||||
return reject(wasReported(error.message));
|
||||
}
|
||||
if (response.statusCode !== 200) {
|
||||
log.disableProgress();
|
||||
const message = `${response.statusCode} ${response.body}`;
|
||||
return reject(wasReported(message, url));
|
||||
}
|
||||
result = response;
|
||||
}));
|
||||
const req = progress(
|
||||
this.request.get(
|
||||
url,
|
||||
{
|
||||
headers,
|
||||
},
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
log.disableProgress();
|
||||
return reject(wasReported(error.message));
|
||||
}
|
||||
if (response.statusCode !== 200) {
|
||||
log.disableProgress();
|
||||
const message = `${response.statusCode} ${response.body}`;
|
||||
return reject(wasReported(message, url));
|
||||
}
|
||||
result = response;
|
||||
}
|
||||
)
|
||||
);
|
||||
req.on('progress', (state) => {
|
||||
let p;
|
||||
if (state.size && state.size.transferred && state.size.total) {
|
||||
@ -140,13 +153,16 @@ export class GitHub {
|
||||
});
|
||||
}
|
||||
|
||||
async tryDirectly (tag, name, file, short) {
|
||||
async tryDirectly(tag, name, file, short) {
|
||||
try {
|
||||
const url = `https://github.com/${this.owner}/${this.repo}/releases/download/${tag}/${name}`;
|
||||
await this.downloadUrl(url, file, short);
|
||||
return true;
|
||||
} catch (error) {
|
||||
log.info('Asset not found by direct link:', JSON.stringify({ tag, name }));
|
||||
log.info(
|
||||
'Asset not found by direct link:',
|
||||
JSON.stringify({ tag, name })
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
70
lib/index.js
70
lib/index.js
@ -1,50 +1,72 @@
|
||||
import * as system from './system.js';
|
||||
import { abiToNodeRange, hostArch, hostPlatform, // eslint-disable-line no-duplicate-imports
|
||||
isValidNodeRange, knownArchs, toFancyArch, toFancyPlatform } from './system.js';
|
||||
import { localPlace, remotePlace } from './places.js';
|
||||
import { log, wasReported } from './log.js';
|
||||
import { Cloud } from './cloud.js';
|
||||
import build from './build.js';
|
||||
import { exists } from 'fs-extra';
|
||||
import patchesJson from '../patches/patches.json';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
import {
|
||||
abiToNodeRange,
|
||||
hostArch,
|
||||
hostPlatform, // eslint-disable-line no-duplicate-imports
|
||||
isValidNodeRange,
|
||||
knownArchs,
|
||||
toFancyArch,
|
||||
toFancyPlatform,
|
||||
} from './system';
|
||||
import * as system from './system';
|
||||
import { localPlace, remotePlace } from './places';
|
||||
import { log, wasReported } from './log';
|
||||
import { Cloud } from './cloud';
|
||||
import build from './build';
|
||||
import patchesJson from '../patches/patches.json';
|
||||
import { version } from '../package.json';
|
||||
|
||||
const cloud = new Cloud({ owner: 'zeit', repo: 'pkg-fetch' });
|
||||
|
||||
export async function need (opts = {}) { // eslint-disable-line complexity
|
||||
let { nodeRange, platform, arch, forceFetch, forceBuild, dryRun } = opts;
|
||||
export async function need(opts = {}) {
|
||||
// eslint-disable-line complexity
|
||||
const { forceFetch, forceBuild, dryRun } = opts;
|
||||
let { nodeRange, platform, arch } = opts;
|
||||
if (!nodeRange) throw wasReported('nodeRange not specified');
|
||||
if (!platform) throw wasReported('platform not specified');
|
||||
if (!arch) throw wasReported('arch not specified');
|
||||
|
||||
nodeRange = abiToNodeRange(nodeRange); // 'm48' -> 'node6'
|
||||
if (!isValidNodeRange(nodeRange)) {
|
||||
throw wasReported('nodeRange must start with \'node\'');
|
||||
throw wasReported("nodeRange must start with 'node'");
|
||||
}
|
||||
if (nodeRange !== 'latest') {
|
||||
nodeRange = 'v' + nodeRange.slice(4); // 'node6' -> 'v6' for semver
|
||||
nodeRange = `v${nodeRange.slice(4)}`; // 'node6' -> 'v6' for semver
|
||||
}
|
||||
|
||||
platform = toFancyPlatform(platform); // win32 -> win
|
||||
arch = toFancyArch(arch); // ia32 -> x86
|
||||
|
||||
function satisfyingNodeVersion () {
|
||||
function satisfyingNodeVersion() {
|
||||
const versions = Object.keys(patchesJson)
|
||||
.filter((nv) => semver.satisfies(nv, nodeRange) ||
|
||||
nodeRange === 'latest')
|
||||
.filter((nv) => semver.satisfies(nv, nodeRange) || nodeRange === 'latest')
|
||||
.sort((nv1, nv2) => (semver.gt(nv1, nv2) ? 1 : -1));
|
||||
return versions.pop();
|
||||
}
|
||||
|
||||
const nodeVersion = satisfyingNodeVersion();
|
||||
if (!nodeVersion) {
|
||||
throw wasReported(`No available node version satisfies '${opts.nodeRange}'`);
|
||||
throw wasReported(
|
||||
`No available node version satisfies '${opts.nodeRange}'`
|
||||
);
|
||||
}
|
||||
|
||||
const fetched = localPlace({ from: 'fetched', arch, nodeVersion, platform, version });
|
||||
const built = localPlace({ from: 'built', arch, nodeVersion, platform, version });
|
||||
const fetched = localPlace({
|
||||
from: 'fetched',
|
||||
arch,
|
||||
nodeVersion,
|
||||
platform,
|
||||
version,
|
||||
});
|
||||
const built = localPlace({
|
||||
from: 'built',
|
||||
arch,
|
||||
nodeVersion,
|
||||
platform,
|
||||
version,
|
||||
});
|
||||
const remote = remotePlace({ arch, nodeVersion, platform, version });
|
||||
|
||||
let fetchFailed;
|
||||
@ -73,13 +95,19 @@ export async function need (opts = {}) { // eslint-disable-line complexity
|
||||
log.info('Building base binary from source:', path.basename(built));
|
||||
}
|
||||
if (hostPlatform !== platform) {
|
||||
throw wasReported(`Not able to build for '${opts.platform}' here, only for '${hostPlatform}'`);
|
||||
throw wasReported(
|
||||
`Not able to build for '${opts.platform}' here, only for '${hostPlatform}'`
|
||||
);
|
||||
}
|
||||
if (hostArch !== arch) {
|
||||
throw wasReported(`Not able to build for '${opts.arch}' here, only for '${hostArch}'`);
|
||||
throw wasReported(
|
||||
`Not able to build for '${opts.arch}' here, only for '${hostArch}'`
|
||||
);
|
||||
}
|
||||
if (knownArchs.indexOf(arch) < 0) {
|
||||
throw wasReported(`Unknown arch '${opts.arch}'. Specify ${knownArchs.join(', ')}`);
|
||||
throw wasReported(
|
||||
`Unknown arch '${opts.arch}'. Specify ${knownArchs.join(', ')}`
|
||||
);
|
||||
}
|
||||
|
||||
if (dryRun) return 'built';
|
||||
|
||||
25
lib/log.js
25
lib/log.js
@ -1,9 +1,11 @@
|
||||
/* eslint-disable no-underscore-dangle, no-console */
|
||||
|
||||
import Progress from 'progress';
|
||||
import assert from 'assert';
|
||||
import chalk from 'chalk';
|
||||
|
||||
class Log {
|
||||
_lines (lines) {
|
||||
_lines(lines) {
|
||||
if (lines === undefined) return;
|
||||
if (!Array.isArray(lines)) {
|
||||
console.log(` ${lines}`);
|
||||
@ -14,29 +16,29 @@ class Log {
|
||||
}
|
||||
}
|
||||
|
||||
debug (text, lines) {
|
||||
debug(text, lines) {
|
||||
if (!this.debugMode) return;
|
||||
console.log(`> ${chalk.green('[debug]')} ${text}`);
|
||||
this._lines(lines);
|
||||
}
|
||||
|
||||
info (text, lines) {
|
||||
info(text, lines) {
|
||||
console.log(`> ${text}`);
|
||||
this._lines(lines);
|
||||
}
|
||||
|
||||
warn (text, lines) {
|
||||
warn(text, lines) {
|
||||
console.log(`> ${chalk.blue('Warning')} ${text}`);
|
||||
this._lines(lines);
|
||||
}
|
||||
|
||||
error (text, lines) {
|
||||
error(text, lines) {
|
||||
if (text.stack) text = text.stack;
|
||||
console.log(`> ${chalk.red('Error!')} ${text}`);
|
||||
this._lines(lines);
|
||||
}
|
||||
|
||||
enableProgress (text) {
|
||||
enableProgress(text) {
|
||||
assert(!this.bar);
|
||||
text += ' '.repeat(28 - text.length);
|
||||
this.bar = new Progress(` ${text} [:bar] :percent`, {
|
||||
@ -44,16 +46,16 @@ class Log {
|
||||
width: 20,
|
||||
complete: '=',
|
||||
incomplete: ' ',
|
||||
total: 100
|
||||
total: 100,
|
||||
});
|
||||
}
|
||||
|
||||
showProgress (percentage) {
|
||||
showProgress(percentage) {
|
||||
if (!this.bar) return;
|
||||
this.bar.update(percentage / 100);
|
||||
}
|
||||
|
||||
disableProgress () {
|
||||
disableProgress() {
|
||||
if (!this.bar) return;
|
||||
// avoid empty line
|
||||
if (!this.bar.complete) {
|
||||
@ -65,11 +67,10 @@ class Log {
|
||||
|
||||
export const log = new Log();
|
||||
|
||||
export function wasReported (error, lines) {
|
||||
export function wasReported(error, lines) {
|
||||
if (error === undefined) {
|
||||
error = new Error('No message');
|
||||
} else
|
||||
if (typeof error === 'string') {
|
||||
} else if (typeof error === 'string') {
|
||||
log.error(error, lines);
|
||||
error = new Error(error);
|
||||
}
|
||||
|
||||
@ -3,28 +3,30 @@ import expandTemplate from 'expand-template';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import placesJson from '../places.json';
|
||||
|
||||
const expand = expandTemplate();
|
||||
|
||||
const { PKG_CACHE_PATH } = process.env;
|
||||
const IGNORE_TAG = Boolean(process.env.PKG_IGNORE_TAG);
|
||||
|
||||
const cachePath = PKG_CACHE_PATH ||
|
||||
path.join(os.homedir(), '.pkg-cache');
|
||||
const cachePath = PKG_CACHE_PATH || path.join(os.homedir(), '.pkg-cache');
|
||||
|
||||
function tagFromVersion (version) {
|
||||
function tagFromVersion(version) {
|
||||
const mj = major(version);
|
||||
const mn = minor(version);
|
||||
return `v${mj}.${mn}`;
|
||||
}
|
||||
|
||||
export function localPlace (opts) {
|
||||
export function localPlace(opts) {
|
||||
const p = placesJson.localPlace;
|
||||
const { version } = opts;
|
||||
const atHome = IGNORE_TAG ? path.join(cachePath, p) : path.join(cachePath, tagFromVersion(version), p);
|
||||
const atHome = IGNORE_TAG
|
||||
? path.join(cachePath, p)
|
||||
: path.join(cachePath, tagFromVersion(version), p);
|
||||
return expand(path.resolve(atHome), opts);
|
||||
}
|
||||
|
||||
export function remotePlace (opts) {
|
||||
export function remotePlace(opts) {
|
||||
const p = placesJson.remotePlace;
|
||||
const { version } = opts;
|
||||
const tag = tagFromVersion(version);
|
||||
|
||||
43
lib/spawn.js
43
lib/spawn.js
@ -1,25 +1,27 @@
|
||||
import byline from 'byline';
|
||||
import chip from 'child_process';
|
||||
import fs from 'fs';
|
||||
import { log } from './log.js';
|
||||
import { log } from './log';
|
||||
|
||||
const MAX_LINES = 20;
|
||||
const DEBUG_THRESHOLDS = false;
|
||||
|
||||
function errorLines (lines) {
|
||||
return lines.slice(-MAX_LINES)
|
||||
.map((line) => line[1]).join('\n');
|
||||
function errorLines(lines) {
|
||||
return lines
|
||||
.slice(-MAX_LINES)
|
||||
.map((line) => line[1])
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
export function spawn (cmd, args, opts) {
|
||||
export function spawn(cmd, args, opts) {
|
||||
const child = chip.spawn(cmd, args, opts);
|
||||
const stdout = byline(child.stdout);
|
||||
const stderr = byline(child.stderr);
|
||||
const lines = [];
|
||||
|
||||
let onData = function (data) {
|
||||
const time = (new Date()).getTime();
|
||||
lines.push([ time, data.toString() ]); // TODO chalk stdout/stderr?
|
||||
let onData = (data) => {
|
||||
const time = new Date().getTime();
|
||||
lines.push([time, data.toString()]); // TODO chalk stdout/stderr?
|
||||
const { thresholds } = this; // eslint-disable-line no-invalid-this
|
||||
if (thresholds) {
|
||||
for (const key in thresholds) {
|
||||
@ -27,9 +29,9 @@ export function spawn (cmd, args, opts) {
|
||||
const p = thresholds[key];
|
||||
log.showProgress(p);
|
||||
if (DEBUG_THRESHOLDS) {
|
||||
lines.push([ time, '************' ]);
|
||||
lines.push([ time, p + ': ' + key ]);
|
||||
lines.push([ time, '************' ]);
|
||||
lines.push([time, '************']);
|
||||
lines.push([time, `${p}: ${key}`]);
|
||||
lines.push([time, '************']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -38,11 +40,13 @@ export function spawn (cmd, args, opts) {
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
child.on('error', (error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(errorLines(lines)); // dont use `log` here
|
||||
reject(error);
|
||||
});
|
||||
child.on('close', (code) => {
|
||||
if (code) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(errorLines(lines)); // dont use `log` here
|
||||
return reject(new Error(`${cmd} failed with code ${code}`));
|
||||
}
|
||||
@ -59,19 +63,22 @@ export function spawn (cmd, args, opts) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
export function progress (promise, thresholds) {
|
||||
export function progress(promise, thresholds) {
|
||||
promise.thresholds = thresholds;
|
||||
const { child, lines } = promise;
|
||||
log.enableProgress(promise.child.spawnfile);
|
||||
log.showProgress(0);
|
||||
const start = (new Date()).getTime();
|
||||
const start = new Date().getTime();
|
||||
child.on('close', () => {
|
||||
if (DEBUG_THRESHOLDS) {
|
||||
const finish = (new Date()).getTime();
|
||||
const content = lines.map((line) =>
|
||||
((100 * (line[0] - start) / (finish - start)) | 0) + ': ' + line[1]
|
||||
).join('\n');
|
||||
fs.writeFileSync(child.spawnfile + '.debug', content);
|
||||
const finish = new Date().getTime();
|
||||
const content = lines
|
||||
.map(
|
||||
(line) =>
|
||||
`${((100 * (line[0] - start)) / (finish - start)) | 0}: ${line[1]}`
|
||||
)
|
||||
.join('\n');
|
||||
fs.writeFileSync(`${child.spawnfile}.debug`, content);
|
||||
}
|
||||
log.showProgress(100);
|
||||
log.disableProgress();
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import fs from 'fs';
|
||||
import { spawnSync } from 'child_process';
|
||||
|
||||
function getHostAbi () {
|
||||
return 'm' + process.versions.modules;
|
||||
function getHostAbi() {
|
||||
return `m${process.versions.modules}`;
|
||||
}
|
||||
|
||||
export function abiToNodeRange (abi) {
|
||||
export function abiToNodeRange(abi) {
|
||||
if (/^m?14/.test(abi)) return 'node0.12';
|
||||
if (/^m?46/.test(abi)) return 'node4';
|
||||
if (/^m?47/.test(abi)) return 'node5';
|
||||
@ -21,13 +21,13 @@ export function abiToNodeRange (abi) {
|
||||
return abi;
|
||||
}
|
||||
|
||||
export function isValidNodeRange (nodeRange) {
|
||||
export function isValidNodeRange(nodeRange) {
|
||||
if (nodeRange === 'latest') return true;
|
||||
if (!(/^node/.test(nodeRange))) return false;
|
||||
if (!/^node/.test(nodeRange)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function toFancyPlatform (platform) {
|
||||
export function toFancyPlatform(platform) {
|
||||
if (platform === 'darwin') return 'macos';
|
||||
if (platform === 'lin') return 'linux';
|
||||
if (platform === 'mac') return 'macos';
|
||||
@ -37,36 +37,36 @@ export function toFancyPlatform (platform) {
|
||||
return platform;
|
||||
}
|
||||
|
||||
function detectAlpine () {
|
||||
function detectAlpine() {
|
||||
const { platform } = process;
|
||||
if (platform !== 'linux') return false;
|
||||
// https://github.com/sass/node-sass/issues/1589#issuecomment-265292579
|
||||
const ldd = spawnSync('ldd').stderr.toString();
|
||||
if (/\bmusl\b/.test(ldd)) return true;
|
||||
const lddNode = spawnSync('ldd', [ process.execPath ]).stdout.toString();
|
||||
const lddNode = spawnSync('ldd', [process.execPath]).stdout.toString();
|
||||
return /\bmusl\b/.test(lddNode);
|
||||
}
|
||||
|
||||
const isAlpine = detectAlpine();
|
||||
|
||||
function getHostPlatform () {
|
||||
function getHostPlatform() {
|
||||
const { platform } = process;
|
||||
if (isAlpine) return 'alpine';
|
||||
return toFancyPlatform(platform);
|
||||
}
|
||||
|
||||
function getKnownPlatforms () {
|
||||
return [ 'alpine', 'freebsd', 'linux', 'macos', 'win' ];
|
||||
function getKnownPlatforms() {
|
||||
return ['alpine', 'freebsd', 'linux', 'macos', 'win'];
|
||||
}
|
||||
|
||||
export function toFancyArch (arch) {
|
||||
export function toFancyArch(arch) {
|
||||
if (arch === 'ia32') return 'x86';
|
||||
if (arch === 'x86_64') return 'x64';
|
||||
return arch;
|
||||
}
|
||||
|
||||
function getArmUnameArch () {
|
||||
const uname = spawnSync('uname', [ '-a' ]);
|
||||
function getArmUnameArch() {
|
||||
const uname = spawnSync('uname', ['-a']);
|
||||
if (uname.error) return '';
|
||||
let unameOut = uname.stdout && uname.stdout.toString();
|
||||
unameOut = (unameOut || '').toLowerCase();
|
||||
@ -76,30 +76,30 @@ function getArmUnameArch () {
|
||||
return '';
|
||||
}
|
||||
|
||||
function getArmHostArch () {
|
||||
function getArmHostArch() {
|
||||
const cpu = fs.readFileSync('/proc/cpuinfo', 'utf8');
|
||||
if (cpu.indexOf('vfpv3') >= 0) return 'armv7';
|
||||
let name = cpu.split('model name')[1];
|
||||
if (name) name = name.split(':')[1];
|
||||
if (name) name = name.split('\n')[0];
|
||||
if (name) [, name] = name.split(':');
|
||||
if (name) [name] = name.split('\n');
|
||||
if (name && name.indexOf('ARMv7') >= 0) return 'armv7';
|
||||
return 'armv6';
|
||||
}
|
||||
|
||||
function getHostArch () {
|
||||
function getHostArch() {
|
||||
const { arch } = process;
|
||||
if (arch === 'arm') return getArmUnameArch() || getArmHostArch();
|
||||
return toFancyArch(arch);
|
||||
}
|
||||
|
||||
function getTargetArchs () {
|
||||
function getTargetArchs() {
|
||||
const arch = getHostArch();
|
||||
if (arch === 'x64') return [ 'x64', 'x86' ];
|
||||
return [ arch ];
|
||||
if (arch === 'x64') return ['x64', 'x86'];
|
||||
return [arch];
|
||||
}
|
||||
|
||||
function getKnownArchs () {
|
||||
return [ 'x64', 'x86', 'armv6', 'armv7', 'arm64', 'ppc64', 's390x' ];
|
||||
function getKnownArchs() {
|
||||
return ['x64', 'x86', 'armv6', 'armv7', 'arm64', 'ppc64', 's390x'];
|
||||
}
|
||||
|
||||
export const hostAbi = getHostAbi();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import uniqueTempDir from 'unique-temp-dir';
|
||||
|
||||
export function tempPath (...args) {
|
||||
export function tempPath(...args) {
|
||||
return uniqueTempDir(...args);
|
||||
}
|
||||
|
||||
@ -3,73 +3,108 @@
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
export default function thresholds (cmd, nodeVersion) {
|
||||
export default function thresholds(cmd, nodeVersion) {
|
||||
if (cmd === 'clone') {
|
||||
return {
|
||||
'ving objects: 0%': 0, 'ving objects: 1%': 1, 'ving objects: 6%': 5,
|
||||
'ving objects: 12%': 10, 'ving objects: 25%': 20, 'ving objects: 50%': 40,
|
||||
'ving objects: 75%': 60, 'deltas: 0%': 80, 'deltas: 50%': 90
|
||||
'ving objects: 0%': 0,
|
||||
'ving objects: 1%': 1,
|
||||
'ving objects: 6%': 5,
|
||||
'ving objects: 12%': 10,
|
||||
'ving objects: 25%': 20,
|
||||
'ving objects: 50%': 40,
|
||||
'ving objects: 75%': 60,
|
||||
'deltas: 0%': 80,
|
||||
'deltas: 50%': 90,
|
||||
};
|
||||
} else
|
||||
}
|
||||
|
||||
if (cmd === 'vcbuild') {
|
||||
if (/^v?0/.test(nodeVersion)) {
|
||||
return {
|
||||
'http_parser.vcxproj ->': 1, 'openssl.vcxproj ->': 9,
|
||||
'v8_base.vcxproj ->': 55, 'mksnapshot.vcxproj ->': 76,
|
||||
'node\\Release\\node.exp': 90
|
||||
'http_parser.vcxproj ->': 1,
|
||||
'openssl.vcxproj ->': 9,
|
||||
'v8_base.vcxproj ->': 55,
|
||||
'mksnapshot.vcxproj ->': 76,
|
||||
'node\\Release\\node.exp': 90,
|
||||
};
|
||||
} else
|
||||
}
|
||||
|
||||
if (/^v?4/.test(nodeVersion)) {
|
||||
return {
|
||||
'http_parser.vcxproj ->': 1, 'hydrogen-representation-changes.cc': 13,
|
||||
'openssl.vcxproj ->': 21, 'v8_base_0.vcxproj ->': 35,
|
||||
'build\\Release\\mksnapshot.lib': 57, 'mksnapshot.vcxproj ->': 67,
|
||||
'node\\Release\\node.exp': 85, 'cctest.vcxproj ->': 97
|
||||
'http_parser.vcxproj ->': 1,
|
||||
'hydrogen-representation-changes.cc': 13,
|
||||
'openssl.vcxproj ->': 21,
|
||||
'v8_base_0.vcxproj ->': 35,
|
||||
'build\\Release\\mksnapshot.lib': 57,
|
||||
'mksnapshot.vcxproj ->': 67,
|
||||
'node\\Release\\node.exp': 85,
|
||||
'cctest.vcxproj ->': 97,
|
||||
};
|
||||
} else
|
||||
}
|
||||
|
||||
if (/^v?6/.test(nodeVersion)) {
|
||||
return {
|
||||
'http_parser.vcxproj ->': 1, 'openssl.vcxproj ->': 4,
|
||||
'icudata.vcxproj ->': 10, 'hydrogen-representation-changes.cc': 15,
|
||||
'interface-descriptors-x64.cc': 27, 'v8_base_0.vcxproj ->': 41,
|
||||
'build\\Release\\mksnapshot.lib': 55, 'mksnapshot.vcxproj ->': 66,
|
||||
'node\\Release\\node.exp': 82, 'cctest.vcxproj ->': 95
|
||||
'http_parser.vcxproj ->': 1,
|
||||
'openssl.vcxproj ->': 4,
|
||||
'icudata.vcxproj ->': 10,
|
||||
'hydrogen-representation-changes.cc': 15,
|
||||
'interface-descriptors-x64.cc': 27,
|
||||
'v8_base_0.vcxproj ->': 41,
|
||||
'build\\Release\\mksnapshot.lib': 55,
|
||||
'mksnapshot.vcxproj ->': 66,
|
||||
'node\\Release\\node.exp': 82,
|
||||
'cctest.vcxproj ->': 95,
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (cmd === 'make') {
|
||||
if (/^v?0/.test(nodeVersion)) {
|
||||
return {
|
||||
'openssl/crypto/ex_data.o.d.raw': 10, 'v8/src/api.o.d.raw': 20,
|
||||
'v8/src/compiler/js-graph.o.d.raw': 30, 'v8/src/debug.o.d.raw': 40,
|
||||
'v8/src/heap/spaces.o.d.raw': 50, 'v8/src/hydrogen-sce.o.d.raw': 60,
|
||||
'v8/src/parser.o.d.raw': 70, 'v8/src/token.o.d.raw': 80,
|
||||
'v8/src/x64/stub-cache-x64.o.d.raw': 90
|
||||
'openssl/crypto/ex_data.o.d.raw': 10,
|
||||
'v8/src/api.o.d.raw': 20,
|
||||
'v8/src/compiler/js-graph.o.d.raw': 30,
|
||||
'v8/src/debug.o.d.raw': 40,
|
||||
'v8/src/heap/spaces.o.d.raw': 50,
|
||||
'v8/src/hydrogen-sce.o.d.raw': 60,
|
||||
'v8/src/parser.o.d.raw': 70,
|
||||
'v8/src/token.o.d.raw': 80,
|
||||
'v8/src/x64/stub-cache-x64.o.d.raw': 90,
|
||||
};
|
||||
} else
|
||||
}
|
||||
|
||||
if (/^v?4/.test(nodeVersion)) {
|
||||
return {
|
||||
'v8/src/compiler/code-generator.o.d.raw': 10, 'v8/src/compiler/operator.o.d.raw': 20,
|
||||
'v8/src/factory.o.d.raw': 30, 'v8/src/hydrogen.o.d.raw': 40,
|
||||
'v8/src/liveedit.o.d.raw': 50, 'v8/src/runtime/runtime-function.o.d.raw': 60,
|
||||
'v8/src/v8.o.d.raw': 70, 'v8_nosnapshot/gen/libraries.o.d.raw': 80,
|
||||
'openssl/crypto/ex_data.o.d.raw': 90
|
||||
'v8/src/compiler/code-generator.o.d.raw': 10,
|
||||
'v8/src/compiler/operator.o.d.raw': 20,
|
||||
'v8/src/factory.o.d.raw': 30,
|
||||
'v8/src/hydrogen.o.d.raw': 40,
|
||||
'v8/src/liveedit.o.d.raw': 50,
|
||||
'v8/src/runtime/runtime-function.o.d.raw': 60,
|
||||
'v8/src/v8.o.d.raw': 70,
|
||||
'v8_nosnapshot/gen/libraries.o.d.raw': 80,
|
||||
'openssl/crypto/ex_data.o.d.raw': 90,
|
||||
};
|
||||
} else
|
||||
}
|
||||
|
||||
if (/^v?6/.test(nodeVersion)) {
|
||||
return {
|
||||
'icuucx/deps/icu-small/source/common/parsepos.o.d.raw': 10, 'v8/src/api.o.d.raw': 20,
|
||||
'v8/src/compiler/graph-replay.o.d.raw': 30, 'v8/src/compiler.o.d.raw': 40,
|
||||
'v8/src/date.o.d.raw': 50, 'v8/src/isolate.o.d.raw': 60,
|
||||
'v8/src/runtime/runtime-function.o.d.raw': 70, 'v8/src/x64/assembler-x64.o.d.raw': 80,
|
||||
'icui18n/deps/icu-small/source/i18n/search.o.d.raw': 90
|
||||
'icuucx/deps/icu-small/source/common/parsepos.o.d.raw': 10,
|
||||
'v8/src/api.o.d.raw': 20,
|
||||
'v8/src/compiler/graph-replay.o.d.raw': 30,
|
||||
'v8/src/compiler.o.d.raw': 40,
|
||||
'v8/src/date.o.d.raw': 50,
|
||||
'v8/src/isolate.o.d.raw': 60,
|
||||
'v8/src/runtime/runtime-function.o.d.raw': 70,
|
||||
'v8/src/x64/assembler-x64.o.d.raw': 80,
|
||||
'icui18n/deps/icu-small/source/i18n/search.o.d.raw': 90,
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
import { hostPlatform, targetArchs } from './system.js';
|
||||
import { localPlace, remotePlace } from './places.js';
|
||||
import { log, wasReported } from './log.js';
|
||||
import { Cloud } from './cloud.js';
|
||||
import build from './build.js';
|
||||
import patchesJson from '../patches/patches.json';
|
||||
import path from 'path';
|
||||
import { verify } from './verify.js';
|
||||
import { hostPlatform, targetArchs } from './system';
|
||||
import { localPlace, remotePlace } from './places';
|
||||
import { log, wasReported } from './log';
|
||||
import { Cloud } from './cloud';
|
||||
import build from './build';
|
||||
import patchesJson from '../patches/patches.json';
|
||||
import { verify } from './verify';
|
||||
import { version } from '../package.json';
|
||||
|
||||
const cloud = new Cloud({ owner: 'zeit', repo: 'pkg-fetch' });
|
||||
|
||||
export function dontBuild (nodeVersion, targetPlatform, targetArch) {
|
||||
export function dontBuild(nodeVersion, targetPlatform, targetArch) {
|
||||
// binaries are not provided for x86 anymore
|
||||
if (targetPlatform !== 'win' && targetArch === 'x86') return true;
|
||||
// https://support.apple.com/en-us/HT201948
|
||||
@ -20,23 +20,36 @@ export function dontBuild (nodeVersion, targetPlatform, targetArch) {
|
||||
// node 0.12 does not compile on arm
|
||||
if (/^arm/.test(targetArch) && major === 0) return true;
|
||||
if (targetPlatform === 'freebsd' && major < 4) return true;
|
||||
if (targetPlatform === 'alpine' &&
|
||||
(targetArch !== 'x64' || major < 6)) return true;
|
||||
if (targetPlatform === 'alpine' && (targetArch !== 'x64' || major < 6))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function main () {
|
||||
export async function main() {
|
||||
if (!process.env.GITHUB_USERNAME) {
|
||||
throw wasReported('No github credentials. Upload will fail!');
|
||||
}
|
||||
|
||||
for (const nodeVersion in patchesJson) {
|
||||
if (!patchesJson[nodeVersion]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const targetArch of targetArchs) {
|
||||
if (dontBuild(nodeVersion, hostPlatform, targetArch)) continue;
|
||||
const local = localPlace({ from: 'built', arch: targetArch,
|
||||
nodeVersion, platform: hostPlatform, version });
|
||||
const remote = remotePlace({ arch: targetArch,
|
||||
nodeVersion, platform: hostPlatform, version });
|
||||
const local = localPlace({
|
||||
from: 'built',
|
||||
arch: targetArch,
|
||||
nodeVersion,
|
||||
platform: hostPlatform,
|
||||
version,
|
||||
});
|
||||
const remote = remotePlace({
|
||||
arch: targetArch,
|
||||
nodeVersion,
|
||||
platform: hostPlatform,
|
||||
version,
|
||||
});
|
||||
if (await cloud.alreadyUploaded(remote)) continue;
|
||||
const short = path.basename(local);
|
||||
log.info(`Building ${short}...`);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { plusx } from './chmod.js';
|
||||
import { spawn } from './spawn.js';
|
||||
import { plusx } from './chmod';
|
||||
import { spawn } from './spawn';
|
||||
|
||||
const script = `
|
||||
var vm = require('vm');
|
||||
@ -93,8 +93,9 @@ const script = `
|
||||
console.log('ok');
|
||||
`;
|
||||
|
||||
export async function verify (local) {
|
||||
export async function verify(local) {
|
||||
await plusx(local);
|
||||
await spawn(local, [ '-e', script ],
|
||||
{ env: { PKG_EXECPATH: 'PKG_INVOKE_NODEJS' } });
|
||||
await spawn(local, ['-e', script], {
|
||||
env: { PKG_EXECPATH: 'PKG_INVOKE_NODEJS' },
|
||||
});
|
||||
}
|
||||
|
||||
43
package.json
43
package.json
@ -43,30 +43,32 @@
|
||||
"unique-temp-dir": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.8.4",
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.9.0",
|
||||
"@babel/preset-env": "^7.9.0",
|
||||
"@babel/register": "^7.9.0",
|
||||
"@babel/cli": "^7.13.10",
|
||||
"@babel/core": "^7.13.10",
|
||||
"@babel/eslint-parser": "^7.13.10",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.13.0",
|
||||
"@babel/plugin-transform-runtime": "^7.13.10",
|
||||
"@babel/preset-env": "^7.13.12",
|
||||
"@babel/register": "^7.13.8",
|
||||
"ava": "^2.4.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-klopov": "^1.0.2"
|
||||
"eslint": "^7.22.0",
|
||||
"eslint-config-airbnb-base": "^14.2.1",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"lint-staged": ">=10",
|
||||
"prettier": "^2.2.1",
|
||||
"simple-git-hooks": ">=2.0.3"
|
||||
},
|
||||
"scripts": {
|
||||
"babel": "node test/rimraf-es5.js && babel lib --out-dir lib-es5",
|
||||
"build": "node test/rimraf-es5.js && babel lib --out-dir lib-es5",
|
||||
"bin": "node lib-es5/bin.js",
|
||||
"lint": "eslint-klopov . || true",
|
||||
"prepare": "npm run babel",
|
||||
"prepublishOnly": "eslint-klopov . && npm test",
|
||||
"lint": "eslint lib || true",
|
||||
"prepare": "npm run build",
|
||||
"prepublishOnly": "npm run lint",
|
||||
"start": "node lib-es5/upload.js",
|
||||
"test": "ava"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "klopov",
|
||||
"parser": "babel-eslint"
|
||||
},
|
||||
"ava": {
|
||||
"failFast": true,
|
||||
"files": [
|
||||
@ -75,5 +77,14 @@
|
||||
"require": [
|
||||
"@babel/register"
|
||||
]
|
||||
},
|
||||
"prettier": {
|
||||
"singleQuote": true
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "npx lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,css,md}": "prettier --write"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,52 +1,20 @@
|
||||
{
|
||||
"v14.16.0": [
|
||||
"node.v14.16.0.cpp.patch"
|
||||
],
|
||||
"v14.4.0": [
|
||||
"node.v14.4.0.cpp.patch"
|
||||
],
|
||||
"v14.0.0": [
|
||||
"node.v14.0.0.cpp.patch"
|
||||
],
|
||||
"v13.12.0": [
|
||||
"node.v13.12.0.cpp.patch"
|
||||
],
|
||||
"v12.21.0": [
|
||||
"node.v12.21.0.cpp.patch"
|
||||
],
|
||||
"v12.18.1": [
|
||||
"node.v12.18.1.cpp.patch"
|
||||
],
|
||||
"v12.16.1": [
|
||||
"node.v12.16.1.cpp.patch"
|
||||
],
|
||||
"v12.13.1": [
|
||||
"node.v12.13.1.cpp.patch"
|
||||
],
|
||||
"v12.2.0": [
|
||||
"node.v12.2.0.cpp.patch"
|
||||
],
|
||||
"v10.21.0": [
|
||||
"node.v10.21.0.cpp.patch"
|
||||
],
|
||||
"v10.17.0": [
|
||||
"node.v10.17.0.cpp.patch"
|
||||
],
|
||||
"v10.15.3": [
|
||||
"node.v10.15.3.cpp.patch"
|
||||
],
|
||||
"v8.17.0": [
|
||||
"node.v8.17.0.cpp.patch"
|
||||
],
|
||||
"v8.16.2": [
|
||||
"node.v8.16.2.cpp.patch"
|
||||
],
|
||||
"v8.16.0": [
|
||||
"node.v8.16.0.cpp.patch"
|
||||
],
|
||||
"v6.17.1": [
|
||||
"node.v6.17.1.cpp.patch"
|
||||
],
|
||||
"v14.16.0": ["node.v14.16.0.cpp.patch"],
|
||||
"v14.4.0": ["node.v14.4.0.cpp.patch"],
|
||||
"v14.0.0": ["node.v14.0.0.cpp.patch"],
|
||||
"v13.12.0": ["node.v13.12.0.cpp.patch"],
|
||||
"v12.21.0": ["node.v12.21.0.cpp.patch"],
|
||||
"v12.18.1": ["node.v12.18.1.cpp.patch"],
|
||||
"v12.16.1": ["node.v12.16.1.cpp.patch"],
|
||||
"v12.13.1": ["node.v12.13.1.cpp.patch"],
|
||||
"v12.2.0": ["node.v12.2.0.cpp.patch"],
|
||||
"v10.21.0": ["node.v10.21.0.cpp.patch"],
|
||||
"v10.17.0": ["node.v10.17.0.cpp.patch"],
|
||||
"v10.15.3": ["node.v10.15.3.cpp.patch"],
|
||||
"v8.17.0": ["node.v8.17.0.cpp.patch"],
|
||||
"v8.16.2": ["node.v8.16.2.cpp.patch"],
|
||||
"v8.16.0": ["node.v8.16.0.cpp.patch"],
|
||||
"v6.17.1": ["node.v6.17.1.cpp.patch"],
|
||||
"v4.9.1": [
|
||||
"backport.R32768.patch",
|
||||
"backport.PR4777.for.N4.patch",
|
||||
|
||||
@ -1,29 +1,26 @@
|
||||
class LogMock {
|
||||
constructor (actions) {
|
||||
constructor(actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
info (text) {
|
||||
info(text) {
|
||||
this.actions.push(`> ${text}`);
|
||||
}
|
||||
|
||||
warn (text) {
|
||||
warn(text) {
|
||||
this.actions.push(`> WARN ${text}`);
|
||||
}
|
||||
|
||||
error (text) {
|
||||
error(text) {
|
||||
if (text.message) text = text.message;
|
||||
this.actions.push(`> ERR! ${text}`);
|
||||
}
|
||||
|
||||
enableProgress () {
|
||||
}
|
||||
enableProgress() {}
|
||||
|
||||
showProgress () {
|
||||
}
|
||||
showProgress() {}
|
||||
|
||||
disableProgress () {
|
||||
}
|
||||
disableProgress() {}
|
||||
}
|
||||
|
||||
export default LogMock;
|
||||
|
||||
@ -16,11 +16,6 @@
|
||||
"backport.R25444.patch",
|
||||
"node.v0.12.15.patch"
|
||||
],
|
||||
"v4.4.7": [
|
||||
"backport.R32768.v8=4.5.patch",
|
||||
"node.v4.4.7.patch"
|
||||
],
|
||||
"v6.3.1": [
|
||||
"node.v6.3.1.patch"
|
||||
]
|
||||
"v4.4.7": ["backport.R32768.v8=4.5.patch", "node.v4.4.7.patch"],
|
||||
"v6.3.1": ["node.v6.3.1.patch"]
|
||||
}
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
import LogMock from './log-mock.js';
|
||||
import assert from 'assert';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import test from 'ava';
|
||||
import LogMock from './log-mock';
|
||||
|
||||
process.env.GITHUB_USERNAME = 'suppress upload error';
|
||||
|
||||
function relative (p) {
|
||||
function relative(p) {
|
||||
const p2 = path.relative(__dirname, p);
|
||||
return p2.replace(/\\/g, '/');
|
||||
}
|
||||
@ -23,16 +23,20 @@ const patchesJson = require('../patches/patches.json');
|
||||
const newPatchesJson = require('./patches.json');
|
||||
|
||||
for (const nodeVersion in patchesJson) {
|
||||
delete patchesJson[nodeVersion];
|
||||
if (patchesJson[nodeVersion]) {
|
||||
delete patchesJson[nodeVersion];
|
||||
}
|
||||
}
|
||||
|
||||
for (const nodeVersion in newPatchesJson) {
|
||||
patchesJson[nodeVersion] = newPatchesJson[nodeVersion];
|
||||
if (newPatchesJson[nodeVersion]) {
|
||||
patchesJson[nodeVersion] = newPatchesJson[nodeVersion];
|
||||
}
|
||||
}
|
||||
|
||||
require('../lib/log.js').log = new LogMock(actions);
|
||||
|
||||
require('../lib/spawn.js').spawn = function (cmd, args, opts) {
|
||||
require('../lib/spawn.js').spawn = (cmd, args, opts) => {
|
||||
assert(opts);
|
||||
assert(opts.cwd);
|
||||
if (cmd === 'git' && args[0] === 'clone') {
|
||||
@ -53,53 +57,56 @@ require('../lib/spawn.js').spawn = function (cmd, args, opts) {
|
||||
if (opts.cwd) {
|
||||
opts.cwd = relative(opts.cwd);
|
||||
}
|
||||
actions.push([ cmd, args.join(' '), JSON.stringify(opts) ].join(' '));
|
||||
actions.push([cmd, args.join(' '), JSON.stringify(opts)].join(' '));
|
||||
};
|
||||
|
||||
require('../lib/spawn.js').progress = function () {
|
||||
};
|
||||
require('../lib/spawn.js').progress = () => {};
|
||||
|
||||
require('../lib/verify.js').verify = function () {
|
||||
require('../lib/verify.js').verify = () => {
|
||||
actions.push('verify');
|
||||
};
|
||||
|
||||
require('../lib/copy-file.js').copyFile = function (src, dest) {
|
||||
require('../lib/copy-file.js').copyFile = (src, dest) => {
|
||||
src = relative(src);
|
||||
const shortDest = path.basename(path.dirname(dest)) + '/' + path.basename(dest);
|
||||
actions.push([ 'copyFile', src, shortDest ].join(' ')); // full dest is flaky
|
||||
const shortDest = `${path.basename(path.dirname(dest))}/${path.basename(
|
||||
dest
|
||||
)}`;
|
||||
actions.push(['copyFile', src, shortDest].join(' ')); // full dest is flaky
|
||||
lastLocal = dest;
|
||||
};
|
||||
|
||||
require('../lib/github.js').GitHub = class {
|
||||
getRelease (tag) {
|
||||
actions.push([ 'getRelease', tag ].join(' '));
|
||||
getRelease(tag) {
|
||||
actions.push(['getRelease', tag].join(' '));
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getReleaseDraft (tag) {
|
||||
actions.push([ 'getReleaseDraft', tag ].join(' '));
|
||||
getReleaseDraft(tag) {
|
||||
actions.push(['getReleaseDraft', tag].join(' '));
|
||||
return undefined;
|
||||
}
|
||||
|
||||
createRelease (tag) {
|
||||
actions.push([ 'createRelease', tag ].join(' '));
|
||||
createRelease(tag) {
|
||||
actions.push(['createRelease', tag].join(' '));
|
||||
return { upload_url: 'https://example.com/assets{?name,label}', assets };
|
||||
}
|
||||
|
||||
uploadAsset (local, release, name) {
|
||||
uploadAsset(local, release, name) {
|
||||
assert(local === lastLocal); // test it here. too flaky to push to actions
|
||||
actions.push([ 'uploadAsset', JSON.stringify(release), name ].join(' '));
|
||||
actions.push(['uploadAsset', JSON.stringify(release), name].join(' '));
|
||||
assets.push({ name });
|
||||
}
|
||||
};
|
||||
|
||||
test('upload', async (t) => {
|
||||
if (process.platform !== 'darwin' ||
|
||||
process.arch !== 'x64') {
|
||||
if (process.platform !== 'darwin' || process.arch !== 'x64') {
|
||||
throw new Error('RUN THE TEST ONLY ON MACOS-X64');
|
||||
}
|
||||
|
||||
const { main } = require('../lib/upload.js');
|
||||
process.env.MAKE_JOB_COUNT = 1;
|
||||
// eslint-disable-next-line global-require
|
||||
const { main } = require('../lib/upload');
|
||||
|
||||
await main();
|
||||
const mustBe = [
|
||||
'getRelease v1337.2',
|
||||
@ -179,10 +186,10 @@ test('upload', async (t) => {
|
||||
'getRelease v1337.2',
|
||||
'getReleaseDraft v1337.2',
|
||||
'createRelease v1337.2',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"uploaded-v1337.2-node-v0.12.15-macos-x64"},{"name":"uploaded-v1337.2-node-v4.4.7-macos-x64"}]} uploaded-v1337.2-node-v6.3.1-macos-x64'
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"uploaded-v1337.2-node-v0.12.15-macos-x64"},{"name":"uploaded-v1337.2-node-v4.4.7-macos-x64"}]} uploaded-v1337.2-node-v6.3.1-macos-x64',
|
||||
];
|
||||
for (let i = 0; i < actions.length; i += 1) {
|
||||
t.is(actions[i] + ` [[[${i}]]]`, mustBe[i] + ` [[[${i}]]]`);
|
||||
t.is(`${actions[i]} [[[${i}]]]`, `${mustBe[i]} [[[${i}]]]`);
|
||||
}
|
||||
t.is(actions.length, mustBe.length);
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user