Skip to content
Merged
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
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "0.27.4",
"version": "0.27.5",
"type": "module",
"bin": {
"spawn": "cli.js"
Expand Down
4 changes: 3 additions & 1 deletion packages/cli/src/digitalocean/digitalocean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,9 @@ export async function checkAccountStatus(): Promise<void> {
if (existingDroplets.ok) {
const currentCount = existingDroplets.data.length;
if (currentCount >= dropletLimit) {
const msg = `DigitalOcean droplet limit reached: ${currentCount}/${dropletLimit} droplets in use. Delete existing droplets or request a limit increase at https://cloud.digitalocean.com/account/team/droplet_limit_increase`;
// List existing droplet names to help operators identify which to delete
const dropletNames = existingDroplets.data.map((d) => (isString(d.name) ? d.name : "unknown")).join(", ");
const msg = `DigitalOcean droplet limit reached: ${currentCount}/${dropletLimit} droplets in use. Existing: [${dropletNames}]. Delete existing droplets at ${DO_DASHBOARD_URL} or request a limit increase at https://cloud.digitalocean.com/account/team/droplet_limit_increase`;
logWarn(msg);
if (process.env.SPAWN_NON_INTERACTIVE === "1") {
throw new Error(msg);
Expand Down
15 changes: 15 additions & 0 deletions sh/e2e/e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,21 @@ run_agents_for_cloud() {
fi
fi

# Bail out early if the cloud reports zero capacity (e.g. droplet limit reached).
# All agents would fail anyway — skip with an actionable error instead of wasting
# time on retries that cannot succeed. (#3059)
if [ "${effective_parallel}" -eq 0 ] && [ "${SEQUENTIAL_MODE}" -eq 0 ]; then
log_err "No capacity available on ${cloud} — all ${cloud} agents will be marked as failed."
log_err "Delete existing instances or request a limit increase, then re-run."
for agent in ${AGENTS_TO_TEST}; do
printf 'fail' > "${log_dir}/${cloud}-${agent}.result"
if [ -z "${cloud_failed}" ]; then cloud_failed="${agent}"; else cloud_failed="${cloud_failed} ${agent}"; fi
done
printf '%s %s %s %s %s' "0" "$(printf '%s\n' "${AGENTS_TO_TEST}" | wc -w | tr -d ' ')" "0s" "" "|${cloud_failed}" \
> "${log_dir}/${cloud}.summary"
return 1
fi

if [ "${effective_parallel}" -gt 0 ] && [ "${SEQUENTIAL_MODE}" -eq 0 ]; then
# Parallel mode: batch agents
log_info "Running agents in parallel (batch size: ${effective_parallel})"
Expand Down
4 changes: 3 additions & 1 deletion sh/e2e/lib/clouds/digitalocean.sh
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ EOF
# Queries the DigitalOcean account to determine available droplet capacity.
# Subtracts non-e2e droplets from the account limit so parallel test runs
# don't fail due to pre-existing droplets consuming quota slots.
# Returns 0 when no capacity is available so the caller can skip the cloud.
# Falls back to 3 if the API is unavailable.
# ---------------------------------------------------------------------------
_digitalocean_max_parallel() {
Expand All @@ -375,7 +376,8 @@ _digitalocean_max_parallel() {
_existing=$(_do_curl_auth -sf "${_DO_API}/droplets?per_page=200" 2>/dev/null | grep -o '"id":[0-9]*' | wc -l | tr -d ' ') || { printf '3'; return 0; }
_available=$(( _limit - _existing ))
if [ "${_available}" -lt 1 ]; then
printf '1'
log_warn "DigitalOcean droplet limit reached: ${_existing}/${_limit} droplets in use (0 available)"
printf '0'
else
printf '%d' "${_available}"
fi
Expand Down
Loading