Skip to content

Commit

Permalink
fix: improve the ping code (#114)
Browse files Browse the repository at this point in the history
Now should work with Gatsby sites
  • Loading branch information
bahmutov authored Feb 9, 2021
1 parent fd778c8 commit 88d7e9e
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 39 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ Name | Description
[netlify-plugin-prebuild-example](https://github.com/cypress-io/netlify-plugin-prebuild-example) | Runs tests twice, first using the development version of the site, then after Netlify builds the production bundles, runs the tests again
[cypress-example-kitchensink](https://github.com/cypress-io/cypress-example-kitchensink) | Runs only a subset of all tests before publishing the folder to Netlify
[bahmutov/eleventyone](https://github.com/bahmutov/eleventyone) | Example used in [Test Sites Deployed To Netlify Using netlify-plugin-cypress](https://glebbahmutov.com/blog/test-netlify/) tutorial
[gatsby-starter-portfolio-cara](https://github.com/bahmutov/gatsby-starter-portfolio-cara) | A Gatsby site example

## Debugging

Expand Down
19 changes: 19 additions & 0 deletions src/ping-cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// a little CLI utility for testing pinging websites
// node ./src/ping-cli <url>

const { ping } = require('./utils')
const timeoutSeconds = 60
const url = process.argv[2]
console.log('pinging url %s for %d seconds', url, timeoutSeconds)
if (!url) {
console.error('Missing url to ping')
process.exit(1)
}
ping(url, timeoutSeconds * 1000).then(
() => {
console.log('all good')
},
(err) => {
console.error('a problem', err)
},
)
75 changes: 75 additions & 0 deletions src/ping.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const got = require('got')
const debug = require('debug')('netlify-plugin-cypress')
const debugVerbose = require('debug')('netlify-plugin-cypress:verbose')

/**
* A small utility for checking when an URL responds, kind of
* a poor man's https://www.npmjs.com/package/wait-on. This version
* is implemented using https://github.com/sindresorhus/got
*/
const ping = (url, timeout) => {
if (!timeout) {
throw new Error('Expected timeout in ms')
}

debug('pinging "%s" for %d ms max', url, timeout)

// make copy of the error codes that "got" retries on
const errorCodes = [...got.defaults.options.retry.errorCodes]
errorCodes.push('ESOCKETTIMEDOUT')

// we expect the server to respond within a time limit
// and if it does not - retry up to total "timeout" duration
const individualPingTimeout = Math.min(timeout, 30000)
const limit = Math.ceil(timeout / individualPingTimeout)

debug(`total ping timeout ${timeout}`)
debug(`individual ping timeout ${individualPingTimeout}ms`)
debug(`retries limit ${limit}`)

const start = +new Date()
return got(url, {
headers: {
Accept: 'text/html, application/json, text/plain, */*',
},
timeout: individualPingTimeout,
errorCodes,
retry: {
limit,
calculateDelay({ error, attemptCount }) {
if (error) {
debugVerbose(`got error ${JSON.stringify(error)}`)
}
const now = +new Date()
const elapsed = now - start
debugVerbose(
`${elapsed}ms ${error.method} ${error.host} ${error.code} attempt ${attemptCount}`,
)
if (elapsed > timeout) {
console.error(
'%s timed out on retry %d of %d',
url,
attemptCount,
limit,
)
return 0
}

// if the error code is ECONNREFUSED use shorter timeout
// because the server is probably starting
if (error.code === 'ECONNREFUSED') {
return 1000
}

// default "long" timeout
return individualPingTimeout
},
},
}).then(() => {
const now = +new Date()
const elapsed = now - start
debug(`pinging ${url} has finished ok after ${elapsed}ms`)
})
}

module.exports = { ping }
40 changes: 1 addition & 39 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,7 @@
// @ts-check
const puppeteer = require('puppeteer')
const got = require('got')
const debug = require('debug')('netlify-plugin-cypress')
const debugVerbose = require('debug')('netlify-plugin-cypress:verbose')

/**
* A small utility for checking when an URL responds, kind of
* a poor man's https://www.npmjs.com/package/wait-on
*/
const ping = (url, timeout) => {
debug('pinging "%s" for %d ms max', url, timeout)
const start = +new Date()

return got(url, {
retry: {
limit: 30,
calculateDelay({ attemptCount, retryOptions, error }) {
const now = +new Date()
const elapsed = now - start
debugVerbose(`attempt ${attemptCount} ${elapsed}ms ${error.message}`)

if (elapsed > timeout) {
debug(
'%s timed out after %dms, timeout was %dms',
url,
elapsed,
timeout,
)
console.error(
'%s timed out after %dms, timeout was %dms',
url,
elapsed,
timeout,
)
return 0
}
return 1000
},
},
})
}
const { ping } = require('./ping')

const getBrowserPath = async () => {
const browserFetcher = puppeteer.createBrowserFetcher()
Expand Down
1 change: 1 addition & 0 deletions tests/routing/netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ TERM = "xterm"
[plugins.inputs.preBuild]
start = 'npm start'
wait-on = 'http://localhost:3000'
wait-on-timeout = '45' # seconds

# and test the built site after
[plugins.inputs]
Expand Down

0 comments on commit 88d7e9e

Please sign in to comment.