Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions .github/workflows/reusable-phpunit-tests-v3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,21 +205,8 @@ jobs:
run: |
docker -v

- name: Pull Docker images (with retry)
run: |
for attempt in 1 2 3; do
if npm run env:pull; then
break
fi

if [ "$attempt" -eq 3 ]; then
echo "npm run env:pull failed after $attempt attempts."
exit 1
fi

echo "npm run env:pull failed (attempt $attempt); retrying..."
sleep $(( attempt * 10 ))
done
- name: Pull Docker images
run: npm run env:pull

- name: Start Docker environment
run: |
Expand Down
44 changes: 33 additions & 11 deletions tools/local-env/scripts/docker.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,39 @@ if ( dockerCommand.includes( 'cli' ) && dockerCommand.includes( 'db' ) && ! dock
dockerCommand.push( '--defaults' );
}

const composeArgs = [
'compose',
...composeFiles
.map( ( composeFile ) => [ '-f', composeFile ] )
.flat(),
...dockerCommand,
];

// Failures during image pulls are re-attempted to rule out registry rate limits and network issues.
const maxAttempts = 'pull' === dockerCommand[0] ? 3 : 1;

// Execute any Docker compose command passed to this script.
const returns = spawnSync(
'docker',
[
'compose',
...composeFiles
.map( ( composeFile ) => [ '-f', composeFile ] )
.flat(),
...dockerCommand,
],
{ stdio: 'inherit' }
);
let returns;
for ( let attempt = 1; attempt <= maxAttempts; attempt++ ) {
returns = spawnSync( 'docker', composeArgs, { stdio: 'inherit' } );

if ( 0 === returns.status ) {
break;
}

if ( attempt === maxAttempts ) {
if ( maxAttempts > 1 ) {
console.log( `\ndocker compose ${ dockerCommand[0] } failed after ${ attempt } attempts.` );
}

break;
}

const delay = attempt * 10;
console.log( `\ndocker compose ${ dockerCommand[0] } failed (attempt ${ attempt } of ${ maxAttempts }). Retrying in ${ delay } seconds...\n` );

// Sleep synchronously so the retry loop stays in order without going async.
Atomics.wait( new Int32Array( new SharedArrayBuffer( 4 ) ), 0, 0, delay * 1000 );
}

process.exit( returns.status );
Loading