Skip to content

test(newman): fix crud file-path + rbac 500 in CI (host-CWD reproduction) - #2152

Merged
rubenvdlinde merged 1 commit into
developmentfrom
wip/fix-crud-rbac-ci-env
Jul 26, 2026
Merged

test(newman): fix crud file-path + rbac 500 in CI (host-CWD reproduction)#2152
rubenvdlinde merged 1 commit into
developmentfrom
wip/fix-crud-rbac-ci-env

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Summary

The openregister-crud and rbac Newman collections failed in the Code Quality Integration Tests (Newman) job (they pass in warm dev-container repros but fail on the CI host runner). Reproduced exactly as CI — newman on the host, CWD = tests/integration, one fresh NC32 + Postgres container, no reset, composer install vendor (sabre/xml 4.1.0) — which surfaced the real root causes.

Root causes & fixes

1. sabre/xml vendor-shadowing — the real cause of BOTH failures

composer.lock pinned sabre/xml 4.1.0 (pulled transitively by the sabre/vobject dev-dep). 4.1.0's XmlSerializable declares xmlSerialize(): void; core Nextcloud ships sabre/xml 2.2.11 (no return type). OR's include vendor/autoload.php registers 4.1.0 first, so core CalDAV classes fail the signature check with a PHP fatal the moment a calendar is provisioned:

Declaration of Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet::xmlSerialize(Sabre\Xml\Writer $writer)
must be compatible with Sabre\Xml\XmlSerializable::xmlSerialize(Sabre\Xml\Writer $writer): void
  • rbac: POST /ocs/v1.php/cloud/users (create e2euser) → calendar-home provisioning → CalDAV → fatal → HTTP 500 (assertion S0).
  • crud: File 1: Create File on Object is the first file op on a fresh install, so OR creates its openregister system user on the fly → same calendar fatal → 500, and File 3–6 then 404.

Fix: pin sabre/xml to ^2.2 in composer.json and regenerate the lock (sabre/xml 2.2.11, sabre/uri 2.3.4). sabre/vobject 4.5.8 is unaffected (allows sabre/xml ^2.1). Matches the documented durable fix for this class-load trap.

2. rbac 1a: core first-login skeleton-copy lock race

e2euser's first authenticated request triggers Nextcloud core's one-time skeleton copy (completeLogin → copySkeleton), which under the DB locking provider (CI has no Redis) raises LockedException on /<uid>/files/Documents → 500 on whatever endpoint is first (in CI, 1a). Added an S0b warm-up request in the rbac Setup folder that logs e2euser in once (tolerant of any status). No RBAC behaviour weakened1a still asserts 403/404 and passes.

3. crud file-upload fixture path (hygiene)

The Import requests referenced an absolute container path (/var/www/html/custom_apps/...) that never resolves on the CI host runner, so the file silently failed to load and Import tested nothing. Committed tests/integration/test-import.csv (with a .gitignore exception) and switched the form-data src to a collection-relative path; Import now returns 200.

4. UserService quota query — real bug, fired in CI on every /user/me

getUsedSpaceMemorySafe selected a non-existent oc_storages.size and joined oc_storages.id (varchar) = oc_mounts.storage_id (bigint) → PostgreSQL SQLSTATE[42883] operator does not exist: character varying = bigint. Rewrote it to read oc_filecache.size for the user's home-mount storage root (bigint join, works on Postgres/MySQL/SQLite) and hardened the catch to \Throwable. Fixes 36 pre-existing UserServiceTest errors. (This was caught and returned 0, so it was not itself the rbac 500 — but is a genuine bug worth fixing.)

Verification (CI-faithful, host CWD, one container)

  • crud 194/194 ✅ · rbac 41/41 ✅ (both from a fresh install)
  • Full 14-collection sequence: 0 failures (no regression)
  • Unit: UserServiceTest 73/73, UserServiceCoverageTest 26/26, UserServiceBranchCoverageTest 8/8, UserControllerTest 39/39 ✅
  • PHPCS on UserService.php: 0 errors

Follow-up (not in this PR)

[MetricsService] Failed to record metric — "Only strings, Literals and Parameters are allowed" (MetricsService.php:211) logs on nearly every object create/update in CI. Caught and non-fatal, but a real query-builder bug worth a separate issue.

…uses)

Both the openregister-crud and rbac Newman collections failed in the Code
Quality "Integration Tests (Newman)" job. Reproduced exactly as CI (newman on
the host runner, CWD = tests/integration, one fresh NC32+Postgres container,
no reset). Root causes and fixes:

1. sabre/xml vendor-shadowing (the real cause of BOTH failures)
   OpenRegister's composer.lock pinned sabre/xml 4.1.0 (pulled transitively by
   the sabre/vobject dev-dep). 4.1.0's XmlSerializable declares
   `xmlSerialize(): void`; core Nextcloud ships sabre/xml 2.2.11 (no return
   type). OR's autoloader registers 4.1.0 first, so core's CalDAV classes fail
   the signature check with a PHP fatal the moment any calendar is provisioned.
   - rbac: POST /ocs/v1.php/cloud/users (create e2euser) -> calendar home
     provisioning -> CalDAV -> fatal -> HTTP 500 (S0).
   - crud: "File 1: Create File on Object" is the first file op on a fresh
     install, so OR creates its "openregister" system user on the fly ->
     same calendar fatal -> 500, and File 3-6 then 404.
   Fix: pin sabre/xml to ^2.2 (matches the platform) in composer.json and
   regenerate the lock (sabre/xml 2.2.11, sabre/uri 2.3.4). sabre/vobject 4.5.8
   is unaffected (it allows sabre/xml ^2.1).

2. rbac 1a: core first-login skeleton-copy lock race
   e2euser's first authenticated request triggers Nextcloud core's one-time
   skeleton copy (completeLogin -> copySkeleton), which under the DB locking
   provider (CI has no Redis) raises a LockedException on
   "/<uid>/files/Documents" -> 500 on whatever endpoint is first. Added an
   "S0b" warm-up request in the rbac Setup folder that logs e2euser in once
   (tolerant of any status) so the RBAC assertions see a settled home. No RBAC
   behaviour is weakened; 1a still asserts 403/404.

3. crud file-upload fixture path (hygiene)
   The Import requests referenced an absolute container path
   (/var/www/html/custom_apps/...) that never resolves on the CI host runner,
   so the file silently failed to load and Import tested nothing. Committed a
   small tests/integration/test-import.csv fixture (with a .gitignore
   exception) and switched the form-data src to a collection-relative path;
   Import now returns 200.

4. UserService quota query (real bug, fired in CI on every /user/me)
   getUsedSpaceMemorySafe queried a non-existent oc_storages.size column and
   joined oc_storages.id (varchar) = oc_mounts.storage_id (bigint), which
   PostgreSQL rejects (SQLSTATE[42883] operator does not exist). Rewrote it to
   read oc_filecache.size for the user's home-mount storage root (bigint join,
   no cast needed, works on Postgres/MySQL/SQLite) and hardened the catch to
   \Throwable so a stray Error can never turn a quota lookup into a 500. Fixes
   36 pre-existing UserServiceTest errors.

Verified from a CI-faithful host-CWD reproduction: crud 194/194 and rbac 41/41
pass, full 14-collection sequence 0 failures, UserService unit suites green.
@rubenvdlinde
rubenvdlinde merged commit f42184d into development Jul 26, 2026
16 of 17 checks passed
@rubenvdlinde
rubenvdlinde deleted the wip/fix-crud-rbac-ci-env branch July 26, 2026 17:04
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openregister @ b3b590b

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 174/174
npm ✅ 555/555
PHPUnit
Newman
Playwright ⏭️

Quality workflow — 2026-07-26 17:11 UTC

Download the full PDF report from the workflow artifacts.

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.

1 participant