-
-
Notifications
You must be signed in to change notification settings - Fork 170
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ci/cd: Fix macOS Docker build reliability issues
This commit addresses intermittent failures in macOS Docker builds within the GitHub Actions environment, attributed to slow agent responses. By adjusting the retry logic, it aims to reduce build failures caused by delayed Docker service readiness. The enhancements increase the robustness and clarity of the build process, especially for macOS, while maintaining functionality across other operating systems. Key changes: - Increase max retries for the server check script from 30 to 90 for macOS, accommodating slower startup times. - Refine retry logic to prevent unnecessary retries after receiving a definitive HTTP status code, enabling faster feedback and efficient failure handling. Other supporting changes: - Introduce a `--max-retries` parameter in the server status check script for dynamic adjustment based on the operating system. - Add emojis to log messages to enhance the visibility of request attempts in logs. - Shift from `http.get` to the `fetch` API for server status checks, utilizing its modern syntax, standardization, enriched feature set, and better error handling. - Standardize error output to `stderr`. - Add a Node.js shebang in the server check script to improve usability.
- Loading branch information
1 parent
79183d6
commit 8a5592f
Showing
2 changed files
with
63 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,87 @@ | ||
#!/usr/bin/env node | ||
|
||
/** | ||
* Description: | ||
* This script checks if a server, provided as a CLI argument, is up | ||
* and returns an HTTP 200 status code. | ||
* It is designed to provide easy verification of server availability | ||
* and will retry a specified number of times. | ||
* This script checks if a server, provided as a CLI argument, is up | ||
* and returns an HTTP 200 status code. | ||
* It is designed to provide easy verification of server availability | ||
* and will retry a specified number of times. | ||
* | ||
* Usage: | ||
* node ./scripts/verify-web-server-status.js --url [URL] | ||
* node ./scripts/verify-web-server-status.js --url [URL] [--max-retries NUMBER] | ||
* | ||
* Options: | ||
* --url URL of the server to check | ||
* --url URL of the server to check | ||
* --max-retries Maximum number of retry attempts (default: 30) | ||
*/ | ||
|
||
import { get } from 'http'; | ||
|
||
const MAX_RETRIES = 30; | ||
const DEFAULT_MAX_RETRIES = 30; | ||
const RETRY_DELAY_IN_SECONDS = 3; | ||
const URL_PARAMETER_NAME = '--url'; | ||
const PARAMETER_NAME_URL = '--url'; | ||
const PARAMETER_NAME_MAX_RETRIES = '--max-retries'; | ||
|
||
function checkServer(currentRetryCount = 1) { | ||
const serverUrl = getServerUrl(); | ||
console.log(`Requesting ${serverUrl}...`); | ||
get(serverUrl, (res) => { | ||
if (res.statusCode === 200) { | ||
async function checkServer(currentRetryCount = 1) { | ||
const serverUrl = readRequiredParameterValue(PARAMETER_NAME_URL); | ||
const maxRetries = parseNumber( | ||
readOptionalParameterValue(PARAMETER_NAME_MAX_RETRIES, DEFAULT_MAX_RETRIES), | ||
); | ||
console.log(`🌐 Requesting ${serverUrl}...`); | ||
try { | ||
const response = await fetch(serverUrl); | ||
if (response.status === 200) { | ||
console.log('🎊 Success: The server is up and returned HTTP 200.'); | ||
process.exit(0); | ||
} else { | ||
console.log(`Server returned HTTP status code ${res.statusCode}.`); | ||
retry(currentRetryCount); | ||
exitWithError(`Server returned unexpected HTTP status code ${response.statusCode}.`); | ||
} | ||
}).on('error', (err) => { | ||
console.error('Error making the request:', err); | ||
retry(currentRetryCount); | ||
}); | ||
} catch (error) { | ||
console.error('Error making the request:', error); | ||
scheduleNextRetry(maxRetries, currentRetryCount); | ||
} | ||
} | ||
|
||
function retry(currentRetryCount) { | ||
console.log(`Attempt ${currentRetryCount}/${MAX_RETRIES}:`); | ||
function scheduleNextRetry(maxRetries, currentRetryCount) { | ||
console.log(`Attempt ${currentRetryCount}/${maxRetries}:`); | ||
console.log(`Retrying in ${RETRY_DELAY_IN_SECONDS} seconds.`); | ||
|
||
const remainingTime = (MAX_RETRIES - currentRetryCount) * RETRY_DELAY_IN_SECONDS; | ||
const remainingTime = (maxRetries - currentRetryCount) * RETRY_DELAY_IN_SECONDS; | ||
console.log(`Time remaining before timeout: ${remainingTime}s`); | ||
|
||
if (currentRetryCount < MAX_RETRIES) { | ||
if (currentRetryCount < maxRetries) { | ||
setTimeout(() => checkServer(currentRetryCount + 1), RETRY_DELAY_IN_SECONDS * 1000); | ||
} else { | ||
console.log('Failure: The server at did not return HTTP 200 within the allocated time. Exiting.'); | ||
process.exit(1); | ||
exitWithError('The server at did not return HTTP 200 within the allocated time.'); | ||
} | ||
} | ||
|
||
function readRequiredParameterValue(parameterName) { | ||
const parameterValue = readOptionalParameterValue(parameterName); | ||
if (parameterValue === undefined) { | ||
exitWithError(`Parameter "${parameterName}" is required but not provided.`); | ||
} | ||
return parameterValue; | ||
} | ||
|
||
function getServerUrl() { | ||
const urlIndex = process.argv.indexOf(URL_PARAMETER_NAME); | ||
if (urlIndex === -1 || urlIndex === process.argv.length - 1) { | ||
console.error(`Parameter "${URL_PARAMETER_NAME}" is not provided.`); | ||
process.exit(1); | ||
function readOptionalParameterValue(parameterName, defaultValue) { | ||
const index = process.argv.indexOf(parameterName); | ||
if (index === -1 || index === process.argv.length - 1) { | ||
return defaultValue; | ||
} | ||
return process.argv[urlIndex + 1]; | ||
return process.argv[index + 1]; | ||
} | ||
|
||
function parseNumber(numberLike) { | ||
const number = parseInt(numberLike, 10); | ||
if (Number.isNaN(number)) { | ||
exitWithError(`Invalid number: ${numberLike}`); | ||
} | ||
return number; | ||
} | ||
|
||
function exitWithError(message) { | ||
console.error(`Failure: ${message}`); | ||
console.log('Exiting'); | ||
process.exit(1); | ||
} | ||
|
||
checkServer(); | ||
await checkServer(); |