Skip to content

Conversation

@ChiragAgg5k
Copy link
Member

@ChiragAgg5k ChiragAgg5k commented May 21, 2025

What does this PR do?

(Provide a description of what this PR does and why it's needed.)

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)

Related PRs and Issues

  • (Related PR or issue)

Checklist

  • Have you read the Contributing Guidelines on issues?
  • If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?

Summary by CodeRabbit

  • Chores
    • Updated Web SDK to version 18.1.1, Flutter SDK to 17.0.0, and React Native SDK to version 0.9.2.
    • Improved automation to dynamically select the correct SDK directory during build and publish processes.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 21, 2025

Walkthrough

The changes update the GitHub Actions workflow to dynamically set the working directory for SDK build and publish steps based on platform and SDK type. Additionally, version numbers for the Web, Flutter, and React Native SDKs are incremented in the configuration file.

Changes

File(s) Change Summary
.github/workflows/sdk-preview.yml Updated the workflow to set the working directory dynamically for the SDK build and publish steps.
app/config/platforms.php Incremented version numbers for Web SDK (18.1.0 → 18.1.1), Flutter SDK (16.1.0 → 17.0.0), and React Native SDK (0.9.1 → 0.9.2).

Sequence Diagram(s)

sequenceDiagram
    participant Workflow
    participant SetSDKTypeStep
    participant BuildAndPublishStep

    Workflow->>SetSDKTypeStep: Determine platform and SDK type
    SetSDKTypeStep-->>Workflow: Output platform and sdk_type
    Workflow->>BuildAndPublishStep: Run build/publish in ./app/sdks/{platform}-{sdk_type}
Loading

Poem

A hop, a skip, a version bump,
Web, Flutter, React Native jump!
Workflows now dance in directories anew,
Building SDKs for every crew.
With numbers raised and paths made smart,
The code hops forward—let’s all take part! 🐇✨


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c00d032 and 9bb52cd.

⛔ Files ignored due to path filters (2)
  • composer.lock is excluded by !**/*.lock
  • docs/sdks/flutter/CHANGELOG.md is excluded by !docs/sdks/**
📒 Files selected for processing (1)
  • app/config/platforms.php (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/config/platforms.php
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
composer.json (1)

89-89: Review the decision to require a development branch for sdk-generator
Switching from a stable "0.40.*" constraint to "dev-fix-devkeys-header" may introduce instability and reproducibility issues.

  • Verify that the fix-devkeys-header branch is published and accessible via Packagist or your custom repository.
  • Ensure your Composer configuration (minimum-stability / prefer-stable) allows dev requirements.
  • Consider pinning to a specific commit SHA or creating a tagged prerelease once the fix is merged upstream for more deterministic installs.
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 61b2016 and 6cb6d15.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • composer.json (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Setup & Build SDK
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan

@github-actions
Copy link

github-actions bot commented May 21, 2025

Security Scan Results for PR

Docker Image Scan Results

Package Version Vulnerability Severity
binutils 2.42-r0 CVE-2025-0840 HIGH
libexpat 2.6.4-r0 CVE-2024-8176 HIGH
libxml2 2.12.7-r0 CVE-2024-56171 HIGH
libxml2 2.12.7-r0 CVE-2025-24928 HIGH
libxml2 2.12.7-r0 CVE-2025-27113 HIGH
libxml2 2.12.7-r0 CVE-2025-32414 HIGH
libxml2 2.12.7-r0 CVE-2025-32415 HIGH
sqlite-libs 3.45.3-r1 CVE-2025-29087 HIGH
xz 5.6.2-r0 CVE-2025-31115 HIGH
xz-libs 5.6.2-r0 CVE-2025-31115 HIGH
golang.org/x/crypto v0.31.0 CVE-2025-22869 HIGH

Source Code Scan Results

🎉 No vulnerabilities found!

@pkg-pr-new
Copy link

pkg-pr-new bot commented May 21, 2025

Open in StackBlitz

npm i https://pkg.pr.new/appwrite/appwrite@9849

commit: 2803693

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
.github/workflows/sdk-preview.yml (1)

50-50: Optional: abstract SDK path into a reusable output
You could compute the combined SDK directory once and reuse it across steps. For example:

- name: Set SDK path
  id: sdk-path
  run: |
    echo "sdk_path=app/sdks/${{ steps.set-sdk.outputs.platform }}-${{ steps.set-sdk.outputs.sdk_type }}" >> $GITHUB_OUTPUT

- name: Build and Publish SDK
  working-directory: ${{ steps.sdk-path.outputs.sdk_path }}
  run: |
    npm install
    npm run build
    npx pkg-pr-new publish --comment=update

This centralizes the directory logic and makes future updates simpler.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 6cb6d15 and 1593a4e.

📒 Files selected for processing (1)
  • .github/workflows/sdk-preview.yml (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Benchmark
  • GitHub Check: E2E Service Test (Migrations)
  • GitHub Check: E2E Service Test (Webhooks)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Databases)
🔇 Additional comments (1)
.github/workflows/sdk-preview.yml (1)

50-50: Dynamic working-directory improves flexibility
Switching from a hardcoded path to

./app/sdks/${{ steps.set-sdk.outputs.platform }}-${{ steps.set-sdk.outputs.sdk_type }}

automatically adapts to all SDK variants and removes duplication in your workflow.

@github-actions
Copy link

github-actions bot commented May 21, 2025

✨ Benchmark results

  • Requests per second: 937
  • Requests with 200 status code: 168,716
  • P99 latency: 0.20377799

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 937 1,156
200 168,716 208,192
P99 0.20377799 0.160099426

@ChiragAgg5k ChiragAgg5k force-pushed the update-sdks-devkeys branch from 1593a4e to 2803693 Compare May 21, 2025 13:43
@ChiragAgg5k ChiragAgg5k changed the base branch from 1.7.x to main May 21, 2025 13:43
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 6

🔭 Outside diff range comments (2)
app/http.php (1)

175-190: ⚠️ Potential issue

Potential connection-pool leak on repeated retry attempts

while (true) acquires a new adapter on every failed attempt without returning the previous one to the pool.
If the root cause is credentials/privileges (not network) the loop may exhaust the pool before hitting $max and start throwing unrelated “too many connections” errors.

Two possible mitigations:

-    $resource = $app->getResource($resourceKey);
+    try {
+        $resource = $app->getResource($resourceKey);
+    } finally {
+        // ensure connection is returned when the adapter constructor fails mid-handshake
+        $pools->reclaim(); // or adapter->close() depending on pool API
+    }

or re-use the same adapter instance across retries rather than re-allocating.

app/controllers/api/health.php (1)

103-113: ⚠️ Potential issue

ping latency calculation is wrong – divide vs multiply

(\microtime(true) - $checkStart) / 1000 converts seconds to seconds ÷ 1000 (i.e., milliseconds⁄1000).
If you intend to output milliseconds multiply by 1000, otherwise remove the division. Same issue exists for cache & pubsub sections.

- 'ping' => round((microtime(true) - $checkStart) / 1000)
+ 'ping' => round((microtime(true) - $checkStart) * 1000) // ms
🧹 Nitpick comments (5)
app/controllers/general.php (1)

1050-1051: Header allow-list duplicated & growing – centralize to avoid drift

The expanded Access-Control-Allow-Headers string now appears twice with only minor differences. As more SDK headers are introduced this list keeps lengthening, increasing the chance that the two occurrences diverge.

Recommend placing the header list in a constant (e.g., CORS_ALLOW_HEADERS) and referencing it in both locations:

$response->addHeader('Access-Control-Allow-Headers', CORS_ALLOW_HEADERS);

Besides preventing inconsistencies it becomes easier to audit permitted headers for security reviews.

Also applies to: 1113-1114

app/http.php (2)

372-378: Wrapper allocation inside tight loop – cache adapter instance

new DatabasePool($pools->get($hostname)) is executed for every shared-table host on every cold-start.
Because DatabasePool already caches the base connection internally you can safely move the wrapper construction outside the loop or memoise it per $hostname to reduce object churn.


523-523: Stack trace logged in production – watch for PII & log noise

Dumping the full trace string helps during debugging but may expose sensitive file paths or secrets in production aggregators.
Consider guarding the extra Trace: line behind App::isDevelopment() or redacting passwords/tokens before emitting.

app/controllers/api/health.php (1)

92-124: Three nearly identical health-check blocks – extract helper

The DB, cache and pubsub checks share the same structure (loop pools → ping → collect failures).
Duplicated logic means three places to patch the ping fix and harder testability.

Consider a small reusable closure/helper:

$checkPools = function(array $names, callable $factory): array {
    $statuses = []; $fail = [];
    foreach ($names as $n) {
        try {
            $adapter = $factory($n);
            $ok = $adapter->ping();
        } catch (\Throwable) { $ok = false; }
        if ($ok) {
            $statuses[] = /*build doc*/;
        } else { $fail[] = $n; }
    }
    return [$statuses, $fail];
};

This reduces duplication and keeps the health file easier to reason about.

Also applies to: 154-185, 214-245

app/init/resources.php (1)

364-366: Duplicate logic – extract common builder

Identical adapter-construction logic now lives in three places (dbForProject, dbForPlatform, getProjectDB). Centralising it in a makeDatabaseFromPool(string $key): Database helper eliminates duplication and keeps future timeout / metadata tweaks in one spot.

🛑 Comments failed to post (6)
app/controllers/general.php (1)

455-479: 🛠️ Refactor suggestion

DRY violation – duplicated env-var scaffolding for site & function

The two array_merge blocks build nearly identical lists that differ only in the prefix (APPWRITE_FUNCTION_* vs APPWRITE_SITE_*). Maintaining these manually-expanded arrays in lock-step is error-prone: any future addition for one resource type risks being forgotten for the other.

Consider extracting the common keys and computing the prefix dynamically, e.g.:

$baseVars = [
    'API_ENDPOINT'     => $endpoint,
    'ID'               => $resource->getId(),
    'NAME'             => $resource->getAttribute('name'),
    'DEPLOYMENT'       => $deployment->getId(),
    'PROJECT_ID'       => $project->getId(),
    'RUNTIME_NAME'     => $runtime['name'] ?? '',
    'RUNTIME_VERSION'  => $runtime['version'] ?? '',
    'CPUS'             => $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT,
    'MEMORY'           => $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT,
];

$prefix = $type === 'function' ? 'APPWRITE_FUNCTION_' : 'APPWRITE_SITE_';
$vars = array_merge(
    $vars,
    array_combine(
        array_map(fn($k) => $prefix.$k, array_keys($baseVars)),
        $baseVars
    )
);

This reduces duplication, eases future maintenance, and guarantees parity between the two resource types.

🤖 Prompt for AI Agents
In app/controllers/general.php around lines 455 to 479, the environment variable
arrays for 'function' and 'site' types are duplicated with only the prefix
differing. To fix this, extract the common key-value pairs into a single base
array without prefixes, then dynamically compute the prefix based on the type
('APPWRITE_FUNCTION_' or 'APPWRITE_SITE_'). Use array_map to prepend the prefix
to each key and array_combine to merge these prefixed keys with the base values,
then merge this result into $vars. This eliminates duplication and ensures
consistent environment variable sets for both types.
app/init/resources.php (5)

420-422: 🛠️ Refactor suggestion

Unbounded in-memory cache can leak connections

$databases[$dsn->getHost()] permanently stores Database objects for every host ever seen. In long-running PHP-FPM or Swoole workers this grows without limit.

Option A – LRU cache with a max size:

-if (isset($databases[$dsn->getHost()])) {
+if (array_key_exists($dsn->getHost(), $databases)) {
     ...
 }
-...
-$databases[$dsn->getHost()] = $database;
+// Cap at 50 hosts
+if (count($databases) >= 50) {
+    array_shift($databases); // Removes oldest
+}
+$databases[$dsn->getHost()] = $database;

Option B – rely on the upstream DatabasePool to multiplex and drop the manual array entirely.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In app/init/resources.php around lines 420 to 422, the $databases array stores
Database objects keyed by host indefinitely, causing unbounded memory growth in
long-running processes. To fix this, remove the manual $databases array entirely
and rely on the upstream DatabasePool to manage connection multiplexing and
lifecycle. This avoids retaining Database instances manually and prevents memory
leaks.

337-339: ⚠️ Potential issue

Missing pool-key guard can raise hard-to-trace null errors

$pools->get($dsn->getHost()) is assumed to exist. If the DSN host is mis-typed or the connection was not registered, Group::get() will likely return null leading to a fatal when DatabasePool expects a valid adapter.

Recommend:

$pool = $pools->get($dsn->getHost());
-if (!$pool) {
-    throw new Exception(Exception::GENERAL_SERVER_ERROR, "Database pool '{$dsn->getHost()}' not configured");
-}
-$adapter = new DatabasePool($pool);
+$adapter = new DatabasePool($pool ?? throw new Exception(
+    Exception::GENERAL_SERVER_ERROR,
+    "Database pool '{$dsn->getHost()}' not configured"
+));

This fails fast with a clear message instead of an opaque type error down-stream.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In app/init/resources.php around lines 337 to 339, the code assumes that
$pools->get($dsn->getHost()) always returns a valid adapter, but if the DSN host
is incorrect or missing, it returns null causing a fatal error later. Add a
guard to check if the adapter is null immediately after calling $pools->get(),
and if so, throw an exception or trigger an error with a clear message
indicating the missing pool key. This will fail fast and provide a clear
diagnostic instead of an obscure downstream error.

462-466: 🛠️ Refactor suggestion

Sharding with zero adapters will error on first call

If pools-cache env/config is empty the loop yields $adapters = [].
new Sharding([]) will later throw when pick() is called.

Add a fallback:

-    foreach ($list as $value) {
-        $adapters[] = new CachePool($pools->get($value));
-    }
-    return new Cache(new Sharding($adapters));
+    foreach ($list as $value) {
+        $adapter = $pools->get($value);
+        if ($adapter) {
+            $adapters[] = new CachePool($adapter);
+        }
+    }
+    return new Cache(
+        empty($adapters)
+            ? new \Utopia\Cache\Adapter\Memory()   // or NullAdapter
+            : new Sharding($adapters)
+    );

Prevents boot failure on minimal installations.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    foreach ($list as $value) {
        $adapter = $pools->get($value);
        if ($adapter) {
            $adapters[] = new CachePool($adapter);
        }
    }

    return new Cache(
        empty($adapters)
            ? new \Utopia\Cache\Adapter\Memory()   // or NullAdapter
            : new Sharding($adapters)
    );
🤖 Prompt for AI Agents
In app/init/resources.php around lines 462 to 466, the code creates a Sharding
instance with an empty adapters array if the pools-cache config is empty, which
causes an error when pick() is called. To fix this, add a check after the loop
to verify if $adapters is empty, and if so, provide a fallback adapter or handle
the case gracefully before creating the Sharding instance. This prevents boot
failure on minimal installations.

80-84: 🛠️ Refactor suggestion

Named-argument coupling may break on future SDKs

new BrokerPool(publisher: $pools->get('publisher')) and the matching call for consumer rely on parameter names instead of position.
If BrokerPool::__construct() changes its parameter list (common in evolving SDKs) the call will throw a Named parameter $publisher does not exist error.

Safer pattern:

-    return new BrokerPool(publisher: $pools->get('publisher'));
+    // Order-based to avoid tight coupling with parameter names
+    return new BrokerPool($pools->get('publisher'));

—or add an adapting factory so the surface area stays in one place.

🤖 Prompt for AI Agents
In app/init/resources.php around lines 80 to 84, the use of named arguments in
the BrokerPool constructor (e.g., publisher: $pools->get('publisher')) risks
breaking if the constructor's parameter names change in future SDK versions. To
fix this, replace the named arguments with positional arguments by passing the
parameters in the correct order without specifying names, or create an adapter
factory function that maps the current call to the constructor, isolating the
dependency on parameter names in one place.

432-440: ⚠️ Potential issue

Shared $database instance crossed by reference ⇒ race condition

The outer $database is reused for every call to getLogsDB().
Under Swoole coroutines simultaneous requests may:

  1. Mutate tenant with setTenant().
  2. Continue executing while another coroutine overwrites the tenant pointer.

Result: request A might suddenly read/write logs under request B’s tenant.

Safer approach – clone per call:

-        if ($database !== null && $project !== null ...
-            $database->setTenant($project->getInternalId());
-            return $database;
+        if ($database !== null) {
+            $instance = clone $database;            // cheap shallow clone
+            if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
+                $instance->setTenant($project->getInternalId());
+            }
+            return $instance;
         }

Or simply drop the shared static and let DatabasePool handle pooling.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    return function (?Document $project = null) use ($pools, $cache, &$database) {
        if ($database !== null) {
            $instance = clone $database;            // cheap shallow clone
            if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
                $instance->setTenant($project->getInternalId());
            }
            return $instance;
        }

        $adapter = new DatabasePool($pools->get('logs'));
        $database = new Database($adapter, $cache);
🤖 Prompt for AI Agents
In app/init/resources.php around lines 432 to 440, the shared $database variable
is passed by reference and reused across calls, causing potential race
conditions in concurrent environments like Swoole. To fix this, avoid reusing
the shared $database instance by removing the reference and instead create a new
Database instance for each call, either by cloning the existing one or by
instantiating a fresh Database object using the DatabasePool. This ensures each
request gets an isolated database connection without tenant data leakage.

@ChiragAgg5k ChiragAgg5k requested a review from stnguyen90 May 26, 2025 04:33
@stnguyen90 stnguyen90 merged commit a68d49a into main May 26, 2025
65 of 66 checks passed
@stnguyen90 stnguyen90 deleted the update-sdks-devkeys branch May 26, 2025 14:15
@coderabbitai coderabbitai bot mentioned this pull request Jul 3, 2025
2 tasks
This was referenced Jul 22, 2025
@coderabbitai coderabbitai bot mentioned this pull request Sep 11, 2025
2 tasks
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.

3 participants