Skip to content

Commit 0edf68f

Browse files
committed
Add concurrency control and trim per-job overhead
Each run of this workflow fans out to 155 jobs and there was no concurrency group, so a short series of pushes could queue several hundred jobs against each other. Group the runs and cancel superseded ones. Ghostscript ships with the GitHub hosted images, but every job ran `apt-get update && apt-get install ghostscript` regardless — roughly 25 seconds a job across all 155. Skip it when `gs` is already on PATH and keep the install as a fallback. composer.json sets `"lock": false` and every requirement is `dev-main`, so `composer update` resolves on every run while the cache key stays pinned to composer.json and never changes on its own. Rotate the key weekly so third party dependencies cannot be served out of an indefinitely stale cache. Also give the job a `timeout-minutes` — it had none, so a hung Behat run could hold a runner for the full six hour default — and stop the checkout from persisting credentials into the job, matching the reusable workflows in wp-cli/.github. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jy4dmjymj9VmoTBaqrV4iX
1 parent df14a0c commit 0edf68f

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

.github/workflows/reusable-testing.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ jobs:
2727
name: WP ${{ inputs.wp }} | PHP ${{ inputs.php }} | ${{ inputs.dbtype == 'sqlite' && 'SQLite' || inputs.dbtype == 'mysql' && 'MySQL' || 'MariaDB' }}${{ inputs.use-phar && ' (Phar)' || '' }}${{ inputs.object_cache == 'sqlite' && ' (Obj Cache)' || '' }}
2828
runs-on: ubuntu-22.04
2929
continue-on-error: ${{ inputs.dbtype == 'sqlite' || inputs.object_cache == 'sqlite' }}
30+
timeout-minutes: 90
3031

3132
env:
3233
MYSQL_HOST: 127.0.0.1
@@ -42,14 +43,25 @@ jobs:
4243
steps:
4344
- name: Check out source code
4445
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
46+
with:
47+
persist-credentials: false
48+
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
4549

4650
- name: Check existence of composer.json & behat.yml files
4751
id: check_files
4852
run: echo "files_exists=$([ -f composer.json ] && [ -f behat.yml ] && echo true || echo false)" >> "$GITHUB_OUTPUT"
4953

54+
# Ghostscript ships with the GitHub hosted images, so the `apt-get update`
55+
# this used to run unconditionally cost every job ~25s for a package that
56+
# was already there. Keep the install as a fallback in case a future image
57+
# drops it.
5058
- name: Install Ghostscript
5159
if: steps.check_files.outputs.files_exists == 'true'
5260
run: |
61+
if command -v gs > /dev/null 2>&1; then
62+
echo "Ghostscript $(gs --version) is already installed; skipping."
63+
exit 0
64+
fi
5365
sudo apt-get update
5466
sudo apt-get install ghostscript -y
5567
@@ -62,9 +74,19 @@ jobs:
6274
coverage: none
6375
tools: composer
6476

77+
# composer.json sets `"lock": false` and every requirement is `dev-main`, so
78+
# `composer update` resolves on every run while the cache key stays pinned to
79+
# composer.json and never changes on its own. Rotate it weekly so third party
80+
# dependencies cannot be served out of an indefinitely stale cache.
81+
- name: Determine the weekly Composer cache suffix
82+
id: composer-cache-suffix
83+
run: echo "value=$(date -u +%Y-%W)" >> "$GITHUB_OUTPUT"
84+
6585
- name: Install Composer dependencies & cache dependencies
6686
if: steps.check_files.outputs.files_exists == 'true'
6787
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # v4
88+
with:
89+
custom-cache-suffix: ${{ steps.composer-cache-suffix.outputs.value }}
6890
env:
6991
COMPOSER_ROOT_VERSION: dev-${{ github.event.repository.default_branch }}
7092

.github/workflows/testing.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ on:
1010
schedule:
1111
- cron: '0 0 * * *' # Run every day at midnight.
1212

13+
# Each run fans out to 155 jobs, so overlapping runs are expensive.
14+
# Pull requests group per branch so a new push supersedes the previous run.
15+
# Everything else groups per event and commit, so a push to the default branch
16+
# and the nightly schedule never cancel one another.
17+
concurrency:
18+
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
19+
cancel-in-progress: true
20+
1321
jobs:
1422

1523
functional:

0 commit comments

Comments
 (0)