Skip to content

Commit fbb3aa4

Browse files
committed
feat(core): improved wsl2 and docker support
1 parent 737a873 commit fbb3aa4

File tree

1 file changed

+50
-6
lines changed

1 file changed

+50
-6
lines changed

packages/core/src/resolveConfig.ts

+50-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import type { InstallOptions } from '@puppeteer/browsers'
22
import type { ResolvedUserConfig, UnlighthouseTabs, UserConfig } from './types'
33
import { Buffer } from 'node:buffer'
4-
import { existsSync } from 'node:fs'
4+
import { existsSync, readFileSync } from 'node:fs'
55
import { homedir } from 'node:os'
6-
import { join, resolve } from 'node:path'
7-
import { computeExecutablePath, install } from '@puppeteer/browsers'
6+
import path, { join, resolve } from 'node:path'
7+
import { computeExecutablePath, detectBrowserPlatform, install } from '@puppeteer/browsers'
88
import { Launcher } from 'chrome-launcher'
99
import { createDefu, defu } from 'defu'
1010
import { pathExists } from 'fs-extra'
1111
import { pick } from 'lodash-es'
1212
import { resolve as resolveModule } from 'mlly'
13-
import puppeteer from 'puppeteer-core'
13+
import puppeteer, { launch } from 'puppeteer-core'
1414
import { PUPPETEER_REVISIONS } from 'puppeteer-core/lib/cjs/puppeteer/revisions.js'
1515
import { defaultConfig } from './constants'
1616
import { useLogger } from './logger'
@@ -185,28 +185,41 @@ export const resolveUserConfig: (userConfig: UserConfig) => Promise<ResolvedUser
185185
// we'll try and resolve their local chrome
186186
const chromePath = Launcher.getFirstInstallation()
187187
if (chromePath) {
188-
logger.info(`Using system chrome located at: \`${chromePath}\`.`)
188+
logger.info(`Using system Chrome located at: \`${chromePath}\`.`)
189189
// set default to puppeteer core
190190
config.puppeteerClusterOptions.puppeteer = puppeteer
191191
// point to our pre-installed chrome version
192192
config.puppeteerOptions.executablePath = chromePath
193193
foundChrome = true
194194
}
195195
}
196+
if (foundChrome) {
197+
logger.debug('Testing system Chrome installation.')
198+
// mock the behavior of the custer so we can handle errors better
199+
const instance = await launch(config.puppeteerOptions).catch((e) => {
200+
logger.warn(`Failed to launch puppeteer instance using \`${config.puppeteerOptions?.executablePath}\`.`, e)
201+
foundChrome = false
202+
})
203+
// let the cluster do the work
204+
if (instance) {
205+
await instance.close()
206+
}
207+
}
196208
if (!foundChrome) {
197209
// if we can't find their local chrome, we just need to make sure they have puppeteer, this is a similar check
198210
// puppeteer-cluster will do, but we can provide a nicer error
199211
try {
200212
await resolveModule('puppeteer')
201213
foundChrome = true
202-
logger.info('Using puppeteer dependency for chrome.')
214+
logger.info('Using puppeteer dependency for Chrome.')
203215
}
204216
catch (e) {
205217
logger.debug('Puppeteer does not exist as a dependency.', e)
206218
}
207219
}
208220
if (config.chrome.useDownloadFallback && !foundChrome) {
209221
const browserOptions = {
222+
installDeps: process.getuid?.() === 0,
210223
cacheDir: config.chrome.downloadFallbackCacheDir,
211224
buildId: config.chrome.downloadFallbackVersion || PUPPETEER_REVISIONS.chrome,
212225
browser: 'chrome',
@@ -235,6 +248,37 @@ export const resolveUserConfig: (userConfig: UserConfig) => Promise<ResolvedUser
235248
if (!foundChrome)
236249
throw new Error('Failed to find chrome. Please ensure you have a valid chrome installed.')
237250

251+
// mock the behavior of the custer so we can handle errors better
252+
const instance = await launch(config.puppeteerOptions).catch((e) => {
253+
if (detectBrowserPlatform() === 'linux' && e.toString().includes('error while loading shared libraries')) {
254+
const depsPath = path.join(
255+
path.dirname(config.puppeteerOptions.executablePath),
256+
'deb.deps',
257+
)
258+
if (existsSync(depsPath)) {
259+
const data = readFileSync(depsPath, 'utf-8').trim().split('\n').map(d => `"${d}"`).join(',')
260+
logger.warn('Failed to start puppeteer, you may be missing dependencies.')
261+
logger.log('')
262+
const command = [
263+
'sudo',
264+
'apt-get',
265+
'satisfy',
266+
'-y',
267+
data,
268+
'--no-install-recommends',
269+
].join(' ')
270+
// eslint-disable-next-line no-console
271+
console.log(`\x1B[96m%s\x1B[0m`, `Run the following command:\n${command}`)
272+
logger.log('')
273+
}
274+
}
275+
throw e
276+
})
277+
// let the cluster do the work
278+
if (instance) {
279+
await instance.close()
280+
}
281+
238282
// resolve the output path
239283
config.outputPath = resolve(config.root!, config.outputPath!)
240284
return config as ResolvedUserConfig

0 commit comments

Comments
 (0)