Skip to content

feat: report resources requested without their prerequisites - #226

Open
HarshMN2345 wants to merge 5 commits into
mainfrom
fix/resource-dependencies
Open

feat: report resources requested without their prerequisites#226
HarshMN2345 wants to merge 5 commits into
mainfrom
fix/resource-dependencies

Conversation

@HarshMN2345

@HarshMN2345 HarshMN2345 commented Sep 10, 2026

Copy link
Copy Markdown
Member

Why

A resource whose prerequisites are absent from the same resources array cannot be transferred, and nothing says so. The exporter walks a cache the missing prerequisite never filled, or is only reached by the prerequisite's own exporter. Either way nothing throws, so the transfer finishes reporting completed with an empty error list having moved none of it.

Reproduced against real instances (Appwrite 1.9.6 source → 2.0.0 destination):

resources Result
["user","team","membership"] membership 3/3, errors: []
["user","membership"] status completed, errors: [], membership stuck at pending: 3, success: 0
["team","membership"] status failed, User not found

The middle row is the problem: a migration that moved nothing reported success. This is also what let a console bug ship unnoticed — it had been omitting teams, memberships, functions and all of messaging from its requests, and every migration still came back green.

What

A source can now declare what each resource needs alongside it, and exportResources records an error naming whatever is absent before any group runs. Sources declare nothing by default, so every other source is unaffected.

The Appwrite source declares the pairings its exporters actually rely on — derived by walking every cache->get() call site and every export gate:

Resource Needs Why
membership user, team exportMemberships reads both caches
subscriber topic, user exportSubscribers reads the topic cache; the importer resolves the user
table database exportEntities reads the database cache
column database, table exportFields reads the entity cache
row database, table, column exportRecords reads the entity and field caches
file bucket exportFiles reads the bucket cache
environment-variable function emitted inline by exportFunctions
deployment function exportDeployments reads the function cache
site-variable site emitted inline by exportSites
site-deployment site exportSiteDeployments reads the site cache

index, collection, attribute and document are deliberately absent. They are shared between the tables, documents and vectors flavours, whose parents differ, and naming one flavour's parents would reject the others.

Also fixed

Two messaging defects found while tracing the above, both silent in their own way:

  • createProvider had no ses arm. It matched eleven provider types and fell through to default => throw for Amazon SES, which lost the provider and failed the whole migration. createSesProvider has been in the SDK all along. Credentials follow the same credentials/options split as the other email providers.
  • createScheduledMessage passed null into createEmail's attachments slot. Every future-dated email lost its attachments unconditionally, even when the buckets and files had been migrated.

Testing

  • docker compose exec tests php vendor/bin/phpunit115 pass, 600 assertions
  • composer lintPASS, 106 files
  • phpstan --level 3 src tests — no errors
  • Removing the guard call makes 2 of the 4 new tests fail, so they are load-bearing

A resource whose prerequisites are absent from the same request cannot be
transferred. Its exporter walks a cache the missing prerequisite never
filled, or is only reached by the prerequisite's own exporter, and
neither path raises anything: the transfer finishes reporting success
having moved none of it. Requesting membership without team is the case
that reaches users, and it leaves the membership counters pending while
the migration reports completed.

Let a source declare what each resource needs alongside it and record an
error naming whatever is absent, so the transfer fails where it used to
go quiet. Sources declare nothing by default.

The Appwrite source declares the pairings its exporters actually rely on.
Index, collection, attribute and document are left out: they are shared
between the tables, documents and vectors flavours, whose parents differ,
and naming one flavour's parents would reject the others.
createProvider matched eleven provider types and fell through to a throw
for Amazon SES, which both lost the provider and failed the whole
migration; the SDK has had createSesProvider all along.

createScheduledMessage passed null in createEmail's attachments slot, so
a future-dated email arrived without its attachments even when the files
had been migrated.
Assert that an incomplete request is reported and names only what is
actually absent, since the untreated case is silent and a transfer that
moves nothing still reports success.
Say plainly what the check is for, and cover the case where a resource is
emitted by its prerequisite's exporter rather than read from the cache.
Keep MockSource's properties together and mark the override.
@greptile-apps

greptile-apps Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

This PR is not safe to merge until all requestable cache-dependent database resources are validated and the implementation-coupled tests are replaced.

Fix All in Claude CodeFindings

  1. P1 Database dependencies remain incomplete
  2. P2 Tests mirror dependency configuration
Fix with agent prompt
### Issue 1
src/Migration/Sources/Appwrite.php:332-335
The declaration deliberately omits `index`, `collection`, `attribute`, and `document`, leaving the silent-success defect incomplete. These are requestable resources whose exporters depend on caches populated by their database or entity exporters. For example, requesting `index` without `table` or `collection` makes `exportIndexes()` iterate an empty entity cache, transfer nothing, and record no dependency error. The dependency model needs to support valid alternative parents instead of exempting these resources from validation.

### Issue 2
tests/Migration/Unit/General/ResourceDependenciesTest.php:38-40
These tests inject the exact membership prerequisites that the production Appwrite source is supposed to declare. A typo, omission, or incorrect Appwrite declaration therefore leaves every test green; the real declaration is never exercised. This violates the repository directive to test observable behavior instead of mirroring source code or configuration in assertions. Replace this setup with coverage that consumes Appwrite's actual dependency declarations. This repository requirement must be satisfied before merging.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

  • Adds dependency validation before export groups run.
  • Declares prerequisites for several Appwrite auth, database, storage, function, site, and messaging resources.
  • Adds an Amazon SES destination provider arm.
  • Passes scheduled-email attachments to the destination SDK.
  • Adds unit coverage for generic dependency reporting.

Reviews (1) · Last reviewed commit: "style: close empty closures the way the ..."

Comment on lines +332 to +335
* Index, collection, attribute and document are deliberately absent. They
* are shared between the tables, documents and vectors flavours, whose
* parents differ, and naming one flavour's parents would reject the others.
*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Database dependencies remain incomplete

The declaration deliberately omits index, collection, attribute, and document, leaving the silent-success defect incomplete. These are requestable resources whose exporters depend on caches populated by their database or entity exporters. For example, requesting index without table or collection makes exportIndexes() iterate an empty entity cache, transfer nothing, and record no dependency error. The dependency model needs to support valid alternative parents instead of exempting these resources from validation.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/Migration/Sources/Appwrite.php
Line: 332-335

Comment:
**Database dependencies remain incomplete**

The declaration deliberately omits `index`, `collection`, `attribute`, and `document`, leaving the silent-success defect incomplete. These are requestable resources whose exporters depend on caches populated by their database or entity exporters. For example, requesting `index` without `table` or `collection` makes `exportIndexes()` iterate an empty entity cache, transfer nothing, and record no dependency error. The dependency model needs to support valid alternative parents instead of exempting these resources from validation.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

Comment on lines +38 to +40
$this->source->setResourceDependencies([
Resource::TYPE_MEMBERSHIP => [Resource::TYPE_USER, Resource::TYPE_TEAM],
]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Tests mirror dependency configuration

These tests inject the exact membership prerequisites that the production Appwrite source is supposed to declare. A typo, omission, or incorrect Appwrite declaration therefore leaves every test green; the real declaration is never exercised. This violates the repository directive to test observable behavior instead of mirroring source code or configuration in assertions. Replace this setup with coverage that consumes Appwrite's actual dependency declarations. This repository requirement must be satisfied before merging.

Context Used: Call out and harshly judge implementation-coupled ... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/Migration/Unit/General/ResourceDependenciesTest.php
Line: 38-40

Comment:
**Tests mirror dependency configuration**

These tests inject the exact membership prerequisites that the production Appwrite source is supposed to declare. A typo, omission, or incorrect Appwrite declaration therefore leaves every test green; the real declaration is never exercised. This violates the repository directive to test observable behavior instead of mirroring source code or configuration in assertions. Replace this setup with coverage that consumes Appwrite's actual dependency declarations. This repository requirement must be satisfied before merging.

**Context Used:** Call out and harshly judge implementation-coupled ... ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code Fix in Codex

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