Skip to content

Fix #29: robust openclaw_version parser (handles 5.6+ output format)#33

Merged
obaid merged 1 commit into
mainfrom
fix/issue-29-persist-server-metadata
May 22, 2026
Merged

Fix #29: robust openclaw_version parser (handles 5.6+ output format)#33
obaid merged 1 commit into
mainfrom
fix/issue-29-persist-server-metadata

Conversation

@obaid
Copy link
Copy Markdown
Contributor

@obaid obaid commented May 22, 2026

Summary

The previous parser used Str::after($output, 'openclaw ') which only matched the lowercase-prefix format with a literal v after — fine for ≤ 5.5 but it silently produced an empty version string when OpenClaw 5.6+ changed the output format. The conditional if ($version) { ... update(...) } then skipped the DB write, leaving servers.openclaw_version empty after every successful provision. This broke version-conditional code paths like ChatGPTAuthService::ensureMinimumOpenClawVersion, which then unnecessarily upgraded openclaw on every ChatGPT pairing.

Fixes #29.

Scope correction

The original ticket also flagged server.ip and server.cloud_resource_id as empty. That was a false alarm: those columns don't exist by those names — the real columns are ipv4_address and provider_server_id, both of which ProvisionDigitalOceanServerJob populates correctly (:60-63). My tinker probe used the wrong names; the data was always there. This PR addresses only the real bug (openclaw_version). The ticket has been corrected.

Changes

  • SetupOpenClawOnServerJob::parseOpenClawVersion (new, public static): single regex (\d{4}\.\d+\.\d+(?:[-.][a-z0-9.]+)?) that captures the version token regardless of casing or prefix and strips a leading v from the match.
  • captureOpenClawVersion: delegates to the new parser and logs the raw output when parsing fails, so future format changes are debuggable instead of silently dropping the value.

Formats covered

Input Output
openclaw v2026.3.8 2026.3.8
openclaw 2026.5.6 (c97b9f7) 2026.5.6
openclaw 2026.5.19 (abc1234) 2026.5.19
OpenClaw 2026.5.19 2026.5.19
v2026.5.19 2026.5.19
2026.5.19 2026.5.19
openclaw 2026.5.20-beta.1 2026.5.20-beta.1
"Warning: foo\nopenclaw 2026.5.19 (abc)" 2026.5.19
"" / "command not found" / "openclaw" null

Tests

9 new unit tests in tests/Unit/Jobs/SetupOpenClawOnServerJobTest.php. Full suite:

php artisan test --compact tests/Unit tests/Feature/Api tests/Feature/Infrastructure tests/Feature/Teams
Tests:    4 skipped, 172 passed (452 assertions)
Duration: 4.78s

Pint: clean.

Live E2E status

⚠️ Live E2E not run on this branch — the Expose tunnel was too flaky to sustain a full DO provision cycle during PR creation (plane wifi). The parser is exhaustively covered by unit tests, so the regression is locked in. To validate on the ground:

  1. Sign up fresh, create a team on DO, wait for server.status=running
  2. php artisan tinker --execute='echo App\Models\Server::latest()->first()->openclaw_version;'
  3. Expect a non-empty version string matching the pinned OPENCLAW_VERSION (e.g. 2026.5.19)

Out of scope (filed separately if needed)

  • ServerSetupScriptService.php:105 uses sed "s/openclaw //" inline for journaling — same brittle parser pattern, but it's a shell-side variable not used for the DB column. Could be hardened in a follow-up.
  • ChatGPTAuthService.php:230 uses a different regex tailored to its capital-O assumption — works for now but worth aligning with this parser eventually.

Test plan

  • CI green
  • Live E2E on stable internet: confirm servers.openclaw_version is populated after a fresh DO provision

The previous parser used `Str::after($output, 'openclaw ')` which only
matched the lowercase-prefix format and silently dropped the value
when the binary's output changed format between releases. Servers
provisioned on 5.6+ ended up with empty `servers.openclaw_version`
columns, breaking version-conditional code paths
(ChatGPTAuthService::ensureMinimumOpenClawVersion).

Extracted the parsing into a static `parseOpenClawVersion` helper that
handles every observed format with a single regex:

  - "openclaw v2026.3.8"            (≤5.5, lowercase + v prefix)
  - "openclaw 2026.5.6 (c97b9f7)"   (5.6+, lowercase + build hash)
  - "OpenClaw 2026.5.19"            (capital O, no prefix)
  - "v2026.5.19" / "2026.5.19"      (bare)
  - "openclaw 2026.5.20-beta.1"     (prerelease)

When the parser returns null we now log the raw output so the next
unknown format is debuggable instead of silently disappearing.

The ipv4_address and provider_server_id concerns from the original
ticket were a false alarm — both columns were populated correctly by
`ProvisionDigitalOceanServerJob`; the reporter was querying with
wrong column names (server.ip, server.cloud_resource_id) in tinker.
This commit only addresses the openclaw_version capture.

Tests: 9 new unit tests covering every observed output format plus
the failure path. Full suite: 172 passed, 4 skipped.

Fixes #29
@obaid obaid merged commit 464502a into main May 22, 2026
1 of 2 checks passed
@obaid obaid deleted the fix/issue-29-persist-server-metadata branch May 22, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server.ip and server.openclaw_version remain empty after successful provisioning

1 participant