ignore all rimraf errors to fix windows flakes

This commit is contained in:
Evan Wallace
2020-12-20 21:05:26 -08:00
parent 467124b71d
commit 9edbd8f0f0
8 changed files with 47 additions and 63 deletions

View File

@@ -13,8 +13,7 @@
} }
const childProcess = await import('child_process') const childProcess = await import('child_process')
const { default: { buildBinary, dirname } } = await import('./esbuild.js') const { default: { buildBinary, dirname, removeRecursiveSync } } = await import('./esbuild.js')
const { default: rimraf } = await import('rimraf')
const assert = await import('assert') const assert = await import('assert')
const path = await import('path') const path = await import('path')
const util = await import('util') const util = await import('util')
@@ -2147,7 +2146,7 @@
} }
// Clean up test output // Clean up test output
rimraf.sync(thisTestDir, { disableGlob: true }); removeRecursiveSync(thisTestDir)
} }
catch (e) { catch (e) {
@@ -2156,7 +2155,7 @@
assert.strictEqual(e.stderr, expectedStderr); assert.strictEqual(e.stderr, expectedStderr);
// Clean up test output // Clean up test output
rimraf.sync(thisTestDir, { disableGlob: true }); removeRecursiveSync(thisTestDir)
continue; continue;
} catch (e2) { } catch (e2) {
e = e2; e = e2;
@@ -2193,7 +2192,7 @@
}) })
// Clean up test output // Clean up test output
rimraf.sync(thisTestDir, { disableGlob: true }) removeRecursiveSync(thisTestDir)
} catch (e) { } catch (e) {
console.error(`❌ test failed: ${e && e.message || e} console.error(`❌ test failed: ${e && e.message || e}
dir: ${path.relative(dirname, thisTestDir)}`) dir: ${path.relative(dirname, thisTestDir)}`)
@@ -2205,7 +2204,7 @@
} }
// Create a fresh test directory // Create a fresh test directory
rimraf.sync(testDir, { disableGlob: true }) removeRecursiveSync(testDir)
await fs.mkdir(testDir, { recursive: true }) await fs.mkdir(testDir, { recursive: true })
// Run all tests concurrently // Run all tests concurrently
@@ -2216,8 +2215,6 @@
process.exit(1) process.exit(1)
} else { } else {
console.log(`✅ end-to-end tests passed`) console.log(`✅ end-to-end tests passed`)
removeRecursiveSync(testDir)
// Clean up test output
rimraf.sync(testDir, { disableGlob: true })
} }
})().catch(e => setTimeout(() => { throw e })) })().catch(e => setTimeout(() => { throw e }))

View File

@@ -16,8 +16,7 @@
return return
} }
const { default: { buildBinary, dirname } } = await import('./esbuild.js'); const { default: { buildBinary, dirname, removeRecursiveSync } } = await import('./esbuild.js');
const { default: rimraf } = await import('rimraf');
const childProcess = await import('child_process'); const childProcess = await import('child_process');
const util = await import('util'); const util = await import('util');
const path = await import('path'); const path = await import('path');
@@ -120,11 +119,11 @@
} }
// Remove data for successful tests // Remove data for successful tests
rimraf.sync(testDir, { disableGlob: true }); removeRecursiveSync(testDir);
} }
const parentDir = path.join(dirname, '.es6-fuzzer'); const parentDir = path.join(dirname, '.es6-fuzzer');
rimraf.sync(parentDir, { disableGlob: true }); removeRecursiveSync(parentDir);
fs.mkdirSync(parentDir); fs.mkdirSync(parentDir);
// Run a set number of tests in parallel // Run a set number of tests in parallel
@@ -140,6 +139,6 @@
// Remove everything if all tests passed // Remove everything if all tests passed
if (failureCount === 0) { if (failureCount === 0) {
rimraf.sync(parentDir, { disableGlob: true }); removeRecursiveSync(parentDir);
} }
})().catch(e => setTimeout(() => { throw e })); })().catch(e => setTimeout(() => { throw e }));

View File

@@ -112,6 +112,26 @@ exports.buildBinary = () => {
return path.join(repoDir, process.platform === 'win32' ? 'esbuild.exe' : 'esbuild') return path.join(repoDir, process.platform === 'win32' ? 'esbuild.exe' : 'esbuild')
} }
exports.removeRecursiveSync = path => {
try {
// Strangely node doesn't have a function to remove a directory tree.
// Using "rm -fr" will never work on Windows because the "rm" command
// doesn't exist. Using the "rimraf" should be cross-platform and even
// works on Windows some of the time.
rimraf.sync(testDir, { disableGlob: true })
} catch (e) {
// Removing stuff on Windows is flaky and unreliable. Don't fail tests
// on CI if Windows is just being a pain. Common causes of flakes include
// random EPERM and ENOTEMPTY errors.
//
// The general "solution" to this is to try asking Windows to redo the
// failing operation repeatedly until eventually giving up after a
// timeout. But that doesn't guarantee that flakes will be fixed so we
// just give up instead. People that want reasonable file system
// behavior on Windows should use WSL instead.
}
}
exports.installForTests = () => { exports.installForTests = () => {
// Build the "esbuild" binary and library // Build the "esbuild" binary and library
const esbuildPath = exports.buildBinary() const esbuildPath = exports.buildBinary()

View File

@@ -1,6 +1,5 @@
const { installForTests } = require('./esbuild') const { installForTests, removeRecursiveSync } = require('./esbuild')
const { SourceMapConsumer } = require('source-map') const { SourceMapConsumer } = require('source-map')
const rimraf = require('rimraf')
const assert = require('assert') const assert = require('assert')
const path = require('path') const path = require('path')
const http = require('http') const http = require('http')
@@ -2299,7 +2298,7 @@ async function main() {
const esbuild = installForTests() const esbuild = installForTests()
// Create a fresh test directory // Create a fresh test directory
rimraf.sync(rootTestDir, { disableGlob: true }) removeRecursiveSync(rootTestDir)
fs.mkdirSync(rootTestDir) fs.mkdirSync(rootTestDir)
// Time out these tests after 5 minutes. This exists to help debug test hangs in CI. // Time out these tests after 5 minutes. This exists to help debug test hangs in CI.
@@ -2318,7 +2317,7 @@ async function main() {
try { try {
await mkdirAsync(testDir) await mkdirAsync(testDir)
await fn({ esbuild, service, testDir }) await fn({ esbuild, service, testDir })
rimraf.sync(testDir, { disableGlob: true }) removeRecursiveSync(testDir)
return true return true
} catch (e) { } catch (e) {
console.error(`${name}: ${e && e.message || e}`) console.error(`${name}: ${e && e.message || e}`)
@@ -2346,24 +2345,7 @@ async function main() {
process.exit(1) process.exit(1)
} else { } else {
console.log(`✅ js api tests passed`) console.log(`✅ js api tests passed`)
removeRecursiveSync(rootTestDir)
// This randomly fails with EPERM on Windows in CI (GitHub Actions):
//
// Error: EPERM: operation not permitted: unlink 'esbuild\scripts\.js-api-tests\node_modules\esbuild\esbuild.exe'
// at Object.unlinkSync (fs.js)
// at fixWinEPERMSync (esbuild\scripts\node_modules\rimraf\rimraf.js)
// at rimrafSync (esbuild\scripts\node_modules\rimraf\rimraf.js)
//
// From searching related issues on GitHub it looks like apparently this is
// just how Windows works? It's kind of hard to believe something as
// fundamental as file operations is broken on Windows. It sounds like the
// file system implementation on Windows has race conditions or something.
// Anyway, deleting this is not important for the success of the test so
// just ignore errors here.
try {
rimraf.sync(rootTestDir, { disableGlob: true })
} catch (e) {
}
} }
clearTimeout(timeout); clearTimeout(timeout);

View File

@@ -1,5 +1,4 @@
const { installForTests } = require('./esbuild') const { installForTests, removeRecursiveSync } = require('./esbuild')
const rimraf = require('rimraf')
const assert = require('assert') const assert = require('assert')
const path = require('path') const path = require('path')
const util = require('util') const util = require('util')
@@ -966,7 +965,7 @@ async function main() {
const esbuild = installForTests() const esbuild = installForTests()
// Create a fresh test directory // Create a fresh test directory
rimraf.sync(rootTestDir, { disableGlob: true }) removeRecursiveSync(rootTestDir)
fs.mkdirSync(rootTestDir) fs.mkdirSync(rootTestDir)
// Time out these tests after 5 minutes. This exists to help debug test hangs in CI. // Time out these tests after 5 minutes. This exists to help debug test hangs in CI.
@@ -985,7 +984,7 @@ async function main() {
try { try {
await mkdirAsync(testDir) await mkdirAsync(testDir)
await fn({ esbuild, service, testDir }) await fn({ esbuild, service, testDir })
rimraf.sync(testDir, { disableGlob: true }) removeRecursiveSync(testDir)
return true return true
} catch (e) { } catch (e) {
console.error(`${name}: ${e && e.message || e}`) console.error(`${name}: ${e && e.message || e}`)
@@ -1003,13 +1002,7 @@ async function main() {
process.exit(1) process.exit(1)
} else { } else {
console.log(`✅ plugin tests passed`) console.log(`✅ plugin tests passed`)
removeRecursiveSync(rootTestDir)
try {
rimraf.sync(rootTestDir, { disableGlob: true })
} catch (e) {
// This doesn't work on Windows due to "EPERM: operation not permitted"
// but that's ok for CI because the VM will just be thrown away anyway.
}
} }
clearTimeout(timeout); clearTimeout(timeout);

View File

@@ -1,14 +1,13 @@
const { installForTests } = require('./esbuild') const { installForTests, removeRecursiveSync } = require('./esbuild')
const child_process = require('child_process') const child_process = require('child_process')
const path = require('path') const path = require('path')
const fs = require('fs') const fs = require('fs')
const rimraf = require('rimraf')
const assert = require('assert') const assert = require('assert')
const esbuild = installForTests() const esbuild = installForTests()
// Create a fresh test directory // Create a fresh test directory
const rootTestDir = path.join(__dirname, '.register-test') const rootTestDir = path.join(__dirname, '.register-test')
rimraf.sync(rootTestDir, { disableGlob: true }) removeRecursiveSync(rootTestDir)
fs.mkdirSync(rootTestDir) fs.mkdirSync(rootTestDir)
const entry = path.join(rootTestDir, 'entry.ts') const entry = path.join(rootTestDir, 'entry.ts')
@@ -49,12 +48,7 @@ async function main() {
main().then( main().then(
() => { () => {
console.log(`✅ register test passed`) console.log(`✅ register test passed`)
try { removeRecursiveSync(rootTestDir)
rimraf.sync(rootTestDir, { disableGlob: true })
} catch (e) {
// This doesn't work on Windows due to "EPERM: operation not permitted"
// but that's ok for CI because the VM will just be thrown away anyway.
}
}, },
e => { e => {
console.error(`❌ register test failed: ${e && e.message || e}`) console.error(`❌ register test failed: ${e && e.message || e}`)

View File

@@ -1,5 +1,5 @@
const { removeRecursiveSync } = require('./esbuild')
const child_process = require('child_process') const child_process = require('child_process')
const rimraf = require('rimraf')
const path = require('path') const path = require('path')
const fs = require('fs') const fs = require('fs')
@@ -318,7 +318,7 @@ const tests = {
async function main() { async function main() {
let testDir = path.join(__dirname, '.ts-types-test') let testDir = path.join(__dirname, '.ts-types-test')
rimraf.sync(testDir, { disableGlob: true }) removeRecursiveSync(testDir)
fs.mkdirSync(testDir, { recursive: true }) fs.mkdirSync(testDir, { recursive: true })
fs.writeFileSync(path.join(testDir, 'tsconfig.json'), JSON.stringify(tsconfigJson)) fs.writeFileSync(path.join(testDir, 'tsconfig.json'), JSON.stringify(tsconfigJson))
@@ -349,7 +349,7 @@ async function main() {
process.exit(1) process.exit(1)
} else { } else {
console.log(`✅ typescript type tests passed`) console.log(`✅ typescript type tests passed`)
rimraf.sync(testDir, { disableGlob: true }) removeRecursiveSync(testDir)
} }
} }

View File

@@ -1,7 +1,6 @@
const { SourceMapConsumer } = require('source-map') const { SourceMapConsumer } = require('source-map')
const { buildBinary } = require('./esbuild') const { buildBinary, removeRecursiveSync } = require('./esbuild')
const childProcess = require('child_process') const childProcess = require('child_process')
const rimraf = require('rimraf')
const path = require('path') const path = require('path')
const util = require('util') const util = require('util')
const fs = require('fs').promises const fs = require('fs').promises
@@ -341,7 +340,7 @@ async function check(kind, testCase, toSearch, { flags, entryPoints, crlf }) {
checkMap(out2Js, out2Map, tempDir) checkMap(out2Js, out2Map, tempDir)
} }
if (!failed) rimraf.sync(tempDir, { disableGlob: true }) if (!failed) removeRecursiveSync(tempDir)
} }
catch (e) { catch (e) {
@@ -424,7 +423,7 @@ async function main() {
process.exit(1) process.exit(1)
} else { } else {
console.log(`✅ verify source map passed`) console.log(`✅ verify source map passed`)
rimraf.sync(testDir, { disableGlob: true }) removeRecursiveSync(testDir)
} }
} }