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
37 changes: 35 additions & 2 deletions .github/workflows/reusable-end-to-end-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,42 @@ jobs:
- name: Build WordPress
run: npm run build

- name: Start Docker environment
# Anonymous pulls share a Docker Hub quota across the whole runner IP pool, and transient
# registry errors are routine. Three attempts with a 10s/20s backoff clear the blips. Every
# failure is retried, so a deterministic one such as a bad tag costs 30s before it reports.
- name: Pull Docker images (with retry)
run: |
npm run env:start
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

# Retried for the same reason: `env:start` reaches the registry, and on branches where it
# also runs `composer update`, repo.packagist.org.
- name: Start Docker environment (with retry)
run: |
for attempt in 1 2 3; do
if npm run env:start; then
break
fi

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

echo "npm run env:start failed (attempt $attempt); retrying..."
sleep $(( attempt * 10 ))
done

- name: Log running Docker containers
run: docker ps -a
Expand Down
38 changes: 36 additions & 2 deletions .github/workflows/reusable-performance-test-v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,42 @@ jobs:
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium

- name: Start Docker environment
run: npm run env:start
# Anonymous pulls share a Docker Hub quota across the whole runner IP pool, and transient
# registry errors are routine. Three attempts with a 10s/20s backoff clear the blips. Every
# failure is retried, so a deterministic one such as a bad tag costs 30s before it reports.
- 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

# Retried for the same reason: `env:start` reaches the registry, and on branches where it
# also runs `composer update`, repo.packagist.org.
- name: Start Docker environment (with retry)
run: |
for attempt in 1 2 3; do
if npm run env:start; then
break
fi

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

echo "npm run env:start failed (attempt $attempt); retrying..."
sleep $(( attempt * 10 ))
done

- name: Build WordPress
run: npm run build
Expand Down
37 changes: 35 additions & 2 deletions .github/workflows/reusable-phpunit-tests-v1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,25 @@ jobs:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-php-${{ inputs.php }}-composer-${{ hashFiles('**/composer.lock') }}

# Anonymous pulls share a Docker Hub quota across the whole runner IP pool, and transient
# registry errors are routine. Three attempts with a 10s/20s backoff clear the blips. Every
# failure is retried, so a deterministic one such as a bad tag costs 30s before it reports.
- 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: Install Composer dependencies
if: ${{ env.COMPOSER_INSTALL == true }}
run: |
Expand All @@ -139,9 +158,23 @@ jobs:
docker -v
docker compose -v

- name: Start Docker environment
# Retried for the same reason: `env:start` reaches the registry, and on branches where it
# also runs `composer update`, repo.packagist.org.
- name: Start Docker environment (with retry)
run: |
npm run env:start
for attempt in 1 2 3; do
if npm run env:start; then
break
fi

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

echo "npm run env:start failed (attempt $attempt); retrying..."
sleep $(( attempt * 10 ))
done

# The memcached server needs to start after the Docker network has been set up with `npm run env:start`.
- name: Start the Memcached server.
Expand Down
39 changes: 37 additions & 2 deletions .github/workflows/reusable-phpunit-tests-v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,27 @@ jobs:
path: ${{ steps.composer-cache.outputs.composer_dir }}
key: ${{ runner.os }}-php-${{ inputs.php }}-composer-${{ hashFiles('**/composer.lock') }}

# Anonymous pulls share a Docker Hub quota across the whole runner IP pool, and transient
# registry errors are routine. Three attempts with a 10s/20s backoff clear the blips. Every
# failure is retried, so a deterministic one such as a bad tag costs 30s before it reports.
#
# This runs before the Composer step below, which is the first thing to pull the PHP image.
- 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: Install Composer dependencies
run: |
docker compose run --rm php composer --version
Expand All @@ -150,9 +171,23 @@ jobs:
docker -v
docker compose -v

- name: Start Docker environment
# Retried for the same reason: `env:start` reaches the registry, and on branches where it
# also runs `composer update`, repo.packagist.org.
- name: Start Docker environment (with retry)
run: |
npm run env:start
for attempt in 1 2 3; do
if npm run env:start; then
break
fi

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

echo "npm run env:start failed (attempt $attempt); retrying..."
sleep $(( attempt * 10 ))
done

- name: General debug information
run: |
Expand Down
21 changes: 19 additions & 2 deletions .github/workflows/reusable-phpunit-tests-v3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ jobs:
run: |
docker -v

# Anonymous pulls share a Docker Hub quota across the whole runner IP pool, and transient
# registry errors are routine. Three attempts with a 10s/20s backoff clear the blips. Every
# failure is retried, so a deterministic one such as a bad tag costs 30s before it reports.
- name: Pull Docker images (with retry)
run: |
for attempt in 1 2 3; do
Expand All @@ -221,9 +224,23 @@ jobs:
sleep $(( attempt * 10 ))
done

- name: Start Docker environment
# Retried for the same reason: `env:start` reaches the registry, and on branches where it
# also runs `composer update`, repo.packagist.org.
- name: Start Docker environment (with retry)
run: |
npm run env:start
for attempt in 1 2 3; do
if npm run env:start; then
break
fi

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

echo "npm run env:start failed (attempt $attempt); retrying..."
sleep $(( attempt * 10 ))
done

- name: Log running Docker containers
run: docker ps -a
Expand Down
55 changes: 51 additions & 4 deletions .github/workflows/reusable-test-local-docker-environment-v1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,42 @@ jobs:
run: |
docker -v

- name: Start Docker environment
# Anonymous pulls share a Docker Hub quota across the whole runner IP pool, and transient
# registry errors are routine. Three attempts with a 10s/20s backoff clear the blips. Every
# failure is retried, so a deterministic one such as a bad tag costs 30s before it reports.
- name: Pull Docker images (with retry)
run: |
npm run env:start
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

# Retried for the same reason: `env:start` reaches the registry, and on branches where it
# also runs `composer update`, repo.packagist.org.
- name: Start Docker environment (with retry)
run: |
for attempt in 1 2 3; do
if npm run env:start; then
break
fi

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

echo "npm run env:start failed (attempt $attempt); retrying..."
sleep $(( attempt * 10 ))
done

- name: Log running Docker containers
run: docker ps -a
Expand All @@ -154,8 +187,22 @@ jobs:
- name: Install WordPress
run: npm run env:install

- name: Restart Docker environment
run: npm run env:restart
# `env:restart` ends in `env:start`, so it has the same network exposure.
- name: Restart Docker environment (with retry)
run: |
for attempt in 1 2 3; do
if npm run env:restart; then
break
fi

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

echo "npm run env:restart failed (attempt $attempt); retrying..."
sleep $(( attempt * 10 ))
done

- name: Test a CLI command
run: npm run env:cli option get siteurl
Expand Down
13 changes: 12 additions & 1 deletion tools/local-env/scripts/docker.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const dotenvExpand = require( 'dotenv-expand' );
const { spawnSync } = require( 'child_process' );
const local_env_utils = require( './utils' );

local_env_utils.ensure_env_file();

dotenvExpand.expand( dotenv.config() );

const composeFiles = local_env_utils.get_compose_files();
Expand Down Expand Up @@ -38,4 +40,13 @@ const returns = spawnSync(
{ stdio: 'inherit' }
);

process.exit( returns.status );
if ( returns.error ) {
console.error( `Could not run Docker Compose. ${ returns.error.message }` );
} else if ( returns.signal && returns.signal !== 'SIGINT' ) {
console.error( `Docker Compose was terminated by ${ returns.signal }.` );
}

// `status` is null when Docker could not be spawned at all, or was killed by a signal. SIGINT is
// how a long-running command such as `env:logs` is normally ended, so it is not a failure worth an
// npm error block. Every other signal means the command was killed before it finished.
process.exit( returns.signal === 'SIGINT' ? 0 : ( returns.status ?? 1 ) );
2 changes: 2 additions & 0 deletions tools/local-env/scripts/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const { execSync } = require( 'child_process' );
const { readFileSync, writeFileSync } = require( 'fs' );
const local_env_utils = require( './utils' );

local_env_utils.ensure_env_file();

dotenvExpand.expand( dotenv.config() );

// Create wp-config.php.
Expand Down
19 changes: 13 additions & 6 deletions tools/local-env/scripts/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@ const dotenv = require( 'dotenv' );
const dotenvExpand = require( 'dotenv-expand' );
const { execSync, spawnSync } = require( 'child_process' );
const local_env_utils = require( './utils' );
const { constants, copyFile } = require( 'node:fs' );

// Copy the default .env file when one is not present.
copyFile( '.env.example', '.env', constants.COPYFILE_EXCL, () => {
console.log( '.env file already exists. .env.example was not copied.' );
});
local_env_utils.ensure_env_file();

dotenvExpand.expand( dotenv.config() );

Expand All @@ -32,7 +28,7 @@ if ( process.env.LOCAL_PHP_MEMCACHED === 'true' ) {
containers.push( 'memcached' );
}

spawnSync(
const up = spawnSync(
'docker',
[
'compose',
Expand All @@ -45,6 +41,17 @@ spawnSync(
{ stdio: 'inherit' }
);

// No signal is exempt here, unlike in `docker.js`: `env:start` runs `composer update -W` next, and
// that must not run against containers that never came up.
if ( up.status !== 0 ) {
const reason = up.signal ? `It was terminated by ${ up.signal }.` : up.error?.message ?? '';

console.error( `Could not start the Docker containers. ${ reason }`.trim() );

// `status` is null when Docker could not be spawned at all, or was killed by a signal.
process.exit( up.status ?? 1 );
}

// If Docker Toolbox is being used, we need to manually forward LOCAL_PORT to the Docker VM.
if ( process.env.DOCKER_TOOLBOX_INSTALL_PATH ) {
// VBoxManage is added to the PATH on every platform except Windows.
Expand Down
Loading
Loading