Skip to content

Cover members + invitations in org integration suite#182

Open
sdairs wants to merge 3 commits into
issue-152-bootstrap-org-integrationfrom
issue-153-members-invitations
Open

Cover members + invitations in org integration suite#182
sdairs wants to merge 3 commits into
issue-152-bootstrap-org-integrationfrom
issue-153-members-invitations

Conversation

@sdairs
Copy link
Copy Markdown
Collaborator

@sdairs sdairs commented May 15, 2026

Summary

Adds the members + invitations phases to the live org integration suite that #152 bootstrapped. Both areas were previously only mock-tested — this closes the live-coverage gap for member_get_list, member_get, member_update and the full invitation CRUD (invitation_create, invitation_get_list, invitation_get, invitation_delete).

  • Members phase — assert the configured secondary user appears in member_get_list, fetch them via member_get, capture their pre-test role and register a restore task with the cleanup registry, then flip Admin <-> Developer via member_update, verify via GET, and eagerly restore. The registry safety net runs even on panic. member_delete is intentionally out of scope (would kick the fixture).
  • Invitations phase — create an invitation to alasdair.brown+clickhousectl_{run_id}@clickhouse.com (Gmail catch-all alias — real inbox, no human reads it), register with CleanupRegistry::register_invitation, exercise invitation_get_list + invitation_get, then cancel via invitation_delete before the recipient could accept. Accept is UI-only and out of scope.

All steps are NonBlocking per the parent strategy in #151 so one CI run reports every broken endpoint rather than tripping on the first.

CleanupRegistry gains register_member_role_restore / unregister_member_role_restore. Teardown PATCHes the captured original role back first, before the existing invitation/role/api-key deletes. 404s are swallowed (mirrors the api-key + invitation pattern).

Closes #153
Parent: #151

Stacked PR

This PR is stacked on #173 (the #152 bootstrap). It is opened against issue-152-bootstrap-org-integration so GitHub shows the stacked diff. GitHub will auto-retarget to main once #173 merges — no action required here.

Verification

  • cargo build -p clickhouse-cloud-api clean
  • cargo clippy -p clickhouse-cloud-api --tests -- -D warnings clean on the changed files (integration_org_test, integration/support). Pre-existing clippy errors in spec_coverage_test.rs (6x collapsible-if) and integration_test.rs (1x too-many-arguments) are also present on main, confirmed via stash + checkout.
  • cargo test -p clickhouse-cloud-api — all suites green; integration_org_test::cloud_org_lifecycle registers as a single ignored lifecycle test as expected.
  • Live --ignored run via cloud-integration workflow — runs as part of CI on this PR.

Test plan

  • Cloud integration workflow on this PR exercises the new phases against the live org with the secondary user fixture in place.
  • Verify the teardown registry restored the secondary user's pre-test role (visible in the workflow log under cleanup).

🤖 Generated with Claude Code

@sdairs sdairs requested a review from iskakaushik as a code owner May 15, 2026 16:09
@sdairs sdairs had a problem deploying to cloud-integration May 15, 2026 16:09 — with GitHub Actions Failure
@sdairs sdairs had a problem deploying to cloud-integration May 15, 2026 18:07 — with GitHub Actions Failure
@sdairs sdairs had a problem deploying to cloud-integration May 15, 2026 18:23 — with GitHub Actions Failure
@sdairs sdairs temporarily deployed to cloud-integration May 15, 2026 18:46 — with GitHub Actions Inactive
@sdairs sdairs linked an issue May 15, 2026 that may be closed by this pull request
@sdairs sdairs force-pushed the issue-152-bootstrap-org-integration branch 2 times, most recently from efa7803 to 4fbc39a Compare May 16, 2026 11:24
sdairs and others added 3 commits May 16, 2026 12:29
Adds two phases to `integration_org_test.rs`:

- Members: list/get the secondary user via `member_get_list` +
  `member_get`, capture the pre-test role, flip it via `member_update`
  (Admin <-> Developer), verify via GET, then eagerly restore. The
  capture is registered with `CleanupRegistry::register_member_role_restore`
  before any mutating call so teardown always restores the original
  role even on panic. `member_delete` is intentionally out of scope —
  it would kick the test fixture.
- Invitations: create an invitation to
  `alasdair.brown+clickhousectl_{run_id}@clickhouse.com` (catch-all
  alias is read by a real inbox but never actioned), register with
  `CleanupRegistry::register_invitation`, list/get to confirm, then
  cancel (delete) before accept. Accept is UI-only and out of scope.

All steps are NonBlocking per the parent plan (#151) so one CI run
reports every broken endpoint, not just the first.

`CleanupRegistry` gains `register_member_role_restore` /
`unregister_member_role_restore`; teardown runs role restores first
(member_update PATCH) before the existing invitation/role/api-key
deletes. 404s are swallowed (mirrors the existing api-key + invitation
patterns), so an already-restored member doesn't fail the run.

Closes #153
Parent: #151
Stacked on: #173 (#152 bootstrap)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The legacy `role` enum (Admin/Developer) on MemberPatchRequest is
rejected with 400 by orgs that have migrated to Custom Roles:
"Organization has migrated to Custom Roles. Use 'assignedRoleIds'
instead of 'role'." The test fixture org is on the new model, so the
round-trip has to use assignedRoleIds.

Round-trip flow:
- Capture the secondary user's current assignedRoleIds (from the GET
  response's Member.assigned_roles[].role_id list).
- List org roles, pick a target role id not currently assigned. If none
  exists and the user already has at least one role, target an empty
  set (drop all assignments). If neither is possible, log a skip — no
  meaningful state change is reachable.
- PATCH assignedRoleIds = target, verify via GET, then restore the
  original set. The cleanup registry stores the original list and
  teardown patches it back if the test body fails mid-flight.

CleanupRegistry::member_role_restores now stores `(user_id,
Vec<String>)` instead of `(user_id, MemberPatchRequestRole)`. Drop the
legacy `flip_member_role` / `member_role_for_restore` helpers — the
new flow has no use for the deprecated enum.
The previous run showed `member_update` returning 200 with the
pre-change `assignedRoles` set echoed in the response body. The API
treats the update as eventually consistent — the PATCH response can
reflect pre-change state and the subsequent GET reflects the new
state after a short propagation window.

Two changes:

1. Drop the assertion on the PATCH response body. The flip step now
   only requires the call to return a result, not that the response
   echoes the new role ids.

2. The verify-via-GET step (and the restore step) now use
   `poll_until` with a 30s timeout to wait for propagation, instead
   of asserting on a single GET.

This applies the same eventual-consistency pattern used by the
ClickHouse settings round-trip in integration_test.rs.
@sdairs sdairs force-pushed the issue-153-members-invitations branch from abe4a18 to 254dcd4 Compare May 16, 2026 11:30
@sdairs sdairs temporarily deployed to cloud-integration May 16, 2026 11:31 — with GitHub Actions Inactive
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.

Cover members + invitations in org integration suite

1 participant