Skip to content

Commit

Permalink
Merge branch 'main' into Test-Python-v3.12-beta
Browse files Browse the repository at this point in the history
  • Loading branch information
cclauss authored Jun 13, 2023
2 parents 52199b3 + 33391db commit ef769b8
Show file tree
Hide file tree
Showing 16 changed files with 1,902 additions and 1,917 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ jobs:
fail-fast: false
max-parallel: 15
matrix:
node: [14.x, 16.x, 18.x]
python: ["3.7", "3.9", "3.11", "3.12-dev"]
node: [16.x, 18.x, 20.x]
python: ["3.8", "3.11", "3.12-dev"]
os: [macos-latest, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand Down
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# Changelog

## [9.4.0](https://www.github.com/nodejs/node-gyp/compare/v9.3.1...v9.4.0) (2023-06-12)


### Features

* add support for native windows arm64 build tools ([bb76021](https://www.github.com/nodejs/node-gyp/commit/bb76021d35964d2bb125bc6214286f35ae4e6cad))
* Upgrade Python linting from flake8 to ruff ([#2815](https://www.github.com/nodejs/node-gyp/issues/2815)) ([fc0ddc6](https://www.github.com/nodejs/node-gyp/commit/fc0ddc6523c62b10e5ca1257500b3ceac01450a7))


### Bug Fixes

* extract tarball to temp directory on Windows ([#2846](https://www.github.com/nodejs/node-gyp/issues/2846)) ([aaa117c](https://www.github.com/nodejs/node-gyp/commit/aaa117c514430aa2c1e568b95df1b6ed1c1fd3b6))
* log statement is for devDir not nodedir ([#2840](https://www.github.com/nodejs/node-gyp/issues/2840)) ([55048f8](https://www.github.com/nodejs/node-gyp/commit/55048f8be5707c295fb0876306aded75638a8b63))


### Miscellaneous

* get update-gyp.py to work with Python >= v3.5 ([#2826](https://www.github.com/nodejs/node-gyp/issues/2826)) ([337e8e6](https://www.github.com/nodejs/node-gyp/commit/337e8e68209bd2481cbb11dacce61234dc5c9419))


### Doc

* docs/README.md add advise about deprecated node-sass ([#2828](https://www.github.com/nodejs/node-gyp/issues/2828)) ([6f3c2d3](https://www.github.com/nodejs/node-gyp/commit/6f3c2d3c6c0de0dbf8c7245f34c2e0b3eea53812))
* Update README.md ([#2822](https://www.github.com/nodejs/node-gyp/issues/2822)) ([c7927e2](https://www.github.com/nodejs/node-gyp/commit/c7927e228dfde059c93e08c26b54dd8026144583))


### Tests

* remove deprecated Node.js and Python ([#2868](https://www.github.com/nodejs/node-gyp/issues/2868)) ([a0b3d1c](https://www.github.com/nodejs/node-gyp/commit/a0b3d1c3afed71a74501476fcbc6ee3fface4d13))

### [9.3.1](https://www.github.com/nodejs/node-gyp/compare/v9.3.0...v9.3.1) (2022-12-16)


Expand Down
173 changes: 95 additions & 78 deletions lib/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const streamPipeline = util.promisify(stream.pipeline)

async function install (fs, gyp, argv) {
const release = processRelease(argv, gyp, process.version, process.release)
// Detecting target_arch based on logic from create-cnfig-gyp.js. Used on Windows only.
const arch = win ? (gyp.opts.target_arch || gyp.opts.arch || process.arch || 'ia32') : ''
// Used to prevent downloading tarball if only new node.lib is required on Windows.
let shouldDownloadTarball = true

// Determine which node dev files version we are installing
log.verbose('install', 'input version string %j', release.version)
Expand Down Expand Up @@ -92,6 +96,26 @@ async function install (fs, gyp, argv) {
}
}
log.verbose('install', 'version is good')
if (win) {
log.verbose('on Windows; need to check node.lib')
const nodeLibPath = path.resolve(devDir, arch, 'node.lib')
try {
await fs.promises.stat(nodeLibPath)
} catch (err) {
if (err.code === 'ENOENT') {
log.verbose('install', `version not already installed for ${arch}, continuing with install`, release.version)
try {
shouldDownloadTarball = false
return await go()
} catch (err) {
return rollback(err)
}
} else if (err.code === 'EACCES') {
return eaccesFallback(err)
}
throw err
}
}
} else {
try {
return await go()
Expand Down Expand Up @@ -135,14 +159,14 @@ async function install (fs, gyp, argv) {
}

async function go () {
log.verbose('ensuring nodedir is created', devDir)
log.verbose('ensuring devDir is created', devDir)

// first create the dir for the node dev files
try {
const created = await fs.promises.mkdir(devDir, { recursive: true })

if (created) {
log.verbose('created nodedir', created)
log.verbose('created devDir', created)
}
} catch (err) {
if (err.code === 'EACCES') {
Expand Down Expand Up @@ -179,66 +203,69 @@ async function install (fs, gyp, argv) {
}

// download the tarball and extract!
// Ommited on Windows if only new node.lib is required

// on Windows there can be file errors from tar if parallel installs
// are happening (not uncommon with multiple native modules) so
// extract the tarball to a temp directory first and then copy over
const tarExtractDir = win ? await fs.promises.mkdtemp(path.join(os.tmpdir(), 'node-gyp-tmp-')) : devDir

try {
if (tarPath) {
await tar.extract({
file: tarPath,
strip: 1,
filter: isValid,
onwarn,
cwd: tarExtractDir
})
} else {
try {
const res = await download(gyp, release.tarballUrl)
if (shouldDownloadTarball) {
if (tarPath) {
await tar.extract({
file: tarPath,
strip: 1,
filter: isValid,
onwarn,
cwd: tarExtractDir
})
} else {
try {
const res = await download(gyp, release.tarballUrl)

if (res.status !== 200) {
throw new Error(`${res.status} response downloading ${release.tarballUrl}`)
}
if (res.status !== 200) {
throw new Error(`${res.status} response downloading ${release.tarballUrl}`)
}

await streamPipeline(
res.body,
// content checksum
new ShaSum((_, checksum) => {
const filename = path.basename(release.tarballUrl).trim()
contentShasums[filename] = checksum
log.verbose('content checksum', filename, checksum)
}),
tar.extract({
strip: 1,
cwd: tarExtractDir,
filter: isValid,
onwarn
})
)
} catch (err) {
await streamPipeline(
res.body,
// content checksum
new ShaSum((_, checksum) => {
const filename = path.basename(release.tarballUrl).trim()
contentShasums[filename] = checksum
log.verbose('content checksum', filename, checksum)
}),
tar.extract({
strip: 1,
cwd: tarExtractDir,
filter: isValid,
onwarn
})
)
} catch (err) {
// something went wrong downloading the tarball?
if (err.code === 'ENOTFOUND') {
throw new Error('This is most likely not a problem with node-gyp or the package itself and\n' +
if (err.code === 'ENOTFOUND') {
throw new Error('This is most likely not a problem with node-gyp or the package itself and\n' +
'is related to network connectivity. In most cases you are behind a proxy or have bad \n' +
'network settings.')
}
throw err
}
throw err
}
}

// invoked after the tarball has finished being extracted
if (extractErrors || extractCount === 0) {
throw new Error('There was a fatal problem while downloading/extracting the tarball')
}
// invoked after the tarball has finished being extracted
if (extractErrors || extractCount === 0) {
throw new Error('There was a fatal problem while downloading/extracting the tarball')
}

log.verbose('tarball', 'done parsing tarball')
log.verbose('tarball', 'done parsing tarball')
}

const installVersionPath = path.resolve(tarExtractDir, 'installVersion')
await Promise.all([
// need to download node.lib
...(win ? downloadNodeLib() : []),
// need to download node.lib
...(win ? [downloadNodeLib()] : []),
// write the "installVersion" file
fs.promises.writeFile(installVersionPath, gyp.package.installVersion + '\n'),
// Only download SHASUMS.txt if we downloaded something in need of SHA verification
Expand Down Expand Up @@ -293,43 +320,33 @@ async function install (fs, gyp, argv) {
log.verbose('checksum data', JSON.stringify(expectShasums))
}

function downloadNodeLib () {
async function downloadNodeLib () {
log.verbose('on Windows; need to download `' + release.name + '.lib`...')
const archs = ['ia32', 'x64', 'arm64']
return archs.map(async (arch) => {
const dir = path.resolve(tarExtractDir, arch)
const targetLibPath = path.resolve(dir, release.name + '.lib')
const { libUrl, libPath } = release[arch]
const name = `${arch} ${release.name}.lib`
log.verbose(name, 'dir', dir)
log.verbose(name, 'url', libUrl)

await fs.promises.mkdir(dir, { recursive: true })
log.verbose('streaming', name, 'to:', targetLibPath)

const res = await download(gyp, libUrl)

if (res.status === 403 || res.status === 404) {
if (arch === 'arm64') {
// Arm64 is a newer platform on Windows and not all node distributions provide it.
log.verbose(`${name} was not found in ${libUrl}`)
} else {
log.warn(`${name} was not found in ${libUrl}`)
}
return
} else if (res.status !== 200) {
throw new Error(`${res.status} status code downloading ${name}`)
}
const dir = path.resolve(tarExtractDir, arch)
const targetLibPath = path.resolve(dir, release.name + '.lib')
const { libUrl, libPath } = release[arch]
const name = `${arch} ${release.name}.lib`
log.verbose(name, 'dir', dir)
log.verbose(name, 'url', libUrl)

await fs.promises.mkdir(dir, { recursive: true })
log.verbose('streaming', name, 'to:', targetLibPath)

const res = await download(gyp, libUrl)

// Since only required node.lib is downloaded throw error if it is not fetched
if (res.status !== 200) {
throw new Error(`${res.status} status code downloading ${name}`)
}

return streamPipeline(
res.body,
new ShaSum((_, checksum) => {
contentShasums[libPath] = checksum
log.verbose('content checksum', libPath, checksum)
}),
fs.createWriteStream(targetLibPath)
)
})
return streamPipeline(
res.body,
new ShaSum((_, checksum) => {
contentShasums[libPath] = checksum
log.verbose('content checksum', libPath, checksum)
}),
fs.createWriteStream(targetLibPath)
)
} // downloadNodeLib()
} // go()

Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"bindings",
"gyp"
],
"version": "9.3.1",
"installVersion": 10,
"version": "9.4.0",
"installVersion": 11,
"author": "Nathan Rajlich <[email protected]> (http://tootallnate.net)",
"repository": {
"type": "git",
Expand All @@ -39,13 +39,13 @@
},
"devDependencies": {
"bindings": "^1.5.0",
"mocha": "^10.2.0",
"nan": "^2.14.2",
"require-inject": "^1.4.4",
"standard": "^14.3.4",
"tap": "^12.7.0"
"standard": "^14.3.4"
},
"scripts": {
"lint": "standard */*.js test/**/*.js",
"test": "npm run lint && tap --timeout=1200 test/test-*"
"test": "npm run lint && mocha --reporter=test/reporter.js test/test-download.js test/test-*"
}
}
75 changes: 75 additions & 0 deletions test/reporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const Mocha = require('mocha')

class Reporter {
constructor (runner) {
this.failedTests = []

runner.on(Mocha.Runner.constants.EVENT_RUN_BEGIN, () => {
console.log('Starting tests')
})

runner.on(Mocha.Runner.constants.EVENT_RUN_END, () => {
console.log('Tests finished')
console.log()
console.log('****************')
console.log('* TESTS REPORT *')
console.log('****************')
console.log()
console.log(`Executed ${runner.stats.suites} suites with ${runner.stats.tests} tests in ${runner.stats.duration} ms`)
console.log(` Passed: ${runner.stats.passes}`)
console.log(` Skipped: ${runner.stats.pending}`)
console.log(` Failed: ${runner.stats.failures}`)
if (this.failedTests.length > 0) {
console.log()
console.log(' Failed test details')
this.failedTests.forEach((failedTest, index) => {
console.log()
console.log(` ${index + 1}.'${failedTest.test.fullTitle()}'`)
console.log(` Name: ${failedTest.error.name}`)
console.log(` Message: ${failedTest.error.message}`)
console.log(` Code: ${failedTest.error.code}`)
console.log(` Stack: ${failedTest.error.stack}`)
})
}
console.log()
})

runner.on(Mocha.Runner.constants.EVENT_SUITE_BEGIN, (suite) => {
if (suite.root) {
return
}
console.log(`Starting suite '${suite.title}'`)
})

runner.on(Mocha.Runner.constants.EVENT_SUITE_END, (suite) => {
if (suite.root) {
return
}
console.log(`Suite '${suite.title}' finished`)
console.log()
})

runner.on(Mocha.Runner.constants.EVENT_TEST_BEGIN, (test) => {
console.log(`Starting test '${test.title}'`)
})

runner.on(Mocha.Runner.constants.EVENT_TEST_PASS, (test) => {
console.log(`Test '${test.title}' passed in ${test.duration} ms`)
})

runner.on(Mocha.Runner.constants.EVENT_TEST_PENDING, (test) => {
console.log(`Test '${test.title}' skipped in ${test.duration} ms`)
})

runner.on(Mocha.Runner.constants.EVENT_TEST_FAIL, (test, error) => {
this.failedTests.push({ test, error })
console.log(`Test '${test.title}' failed in ${test.duration} ms with ${error}`)
})

runner.on(Mocha.Runner.constants.EVENT_TEST_END, (test) => {
console.log()
})
}
}

module.exports = Reporter
Loading

0 comments on commit ef769b8

Please sign in to comment.