Skip to content

Add branch-only deployments to Sites without ref tags#10486

Merged
Meldiron merged 13 commits into1.8.xfrom
feat-add-branch-deployments
Nov 13, 2025
Merged

Add branch-only deployments to Sites without ref tags#10486
Meldiron merged 13 commits into1.8.xfrom
feat-add-branch-deployments

Conversation

@atharvadeosthale
Copy link
Copy Markdown
Member

@atharvadeosthale atharvadeosthale commented Sep 13, 2025

Edited template deployment route which now accepts owner, repository, type, reference

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 13, 2025

📝 Walkthrough

Walkthrough

Replaces the single templateVersion model with templateReferenceType and templateReferenceValue across template creation, deployment documents, and build flows. Functions and Sites template deployment endpoints now accept a type (commit|branch|tag) and reference, validate type, derive provider URLs, and store provider metadata on deployments with deployment.type set to vcs. The Builds worker non‑VCS template flow requires repositoryName/ownerName/templateReferenceType/templateReferenceValue and generates a dynamic clone command from the new reference fields. Adds a V21 request filter to translate legacy versiontype/reference. Extends e2e tests to cover tag, branch, and commit template deployments and adds helpers to fetch latest commit.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Areas needing extra attention:
    • Functions and Sites HTTP Create handlers: updated method signatures, validation (WhiteList), payload shape changes.
    • Builds worker (Workers/Builds.php): clone command generation and additional required fields.
    • New request filter V21: mapping logic for backward compatibility across endpoints.
    • End-to-end tests: added tests for branch/commit flows and new helper methods; verify network/CI flakiness risk and test assumptions (GitHub API).
    • Router/controller change (app/controllers/general.php): integration of RequestV21 and routing conditions.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title refers to branch-only deployments and Sites, but the changeset covers a much broader refactoring of template deployment references across both Functions and Sites modules, replacing version with type/reference parameters. Update the title to reflect the broader scope, such as: 'Refactor template deployments to use type and reference instead of version' or 'Support branch, commit, and tag-based template deployments'.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description mentions accepting new parameters (owner, repository, type, reference) which is accurate to the changeset, though it lacks depth about the version-to-type/reference migration and backward compatibility layer.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-add-branch-deployments

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 13, 2025

Security Scan Results for PR

Docker Image Scan Results

Package Version Vulnerability Severity
binutils 2.44-r2 CVE-2025-5244 HIGH
binutils 2.44-r2 CVE-2025-5245 HIGH
libxml2 2.13.8-r0 CVE-2025-49794 CRITICAL
libxml2 2.13.8-r0 CVE-2025-49796 CRITICAL
libxml2 2.13.8-r0 CVE-2025-49795 HIGH
libxml2 2.13.8-r0 CVE-2025-6021 HIGH
pcre2 10.43-r1 CVE-2025-58050 CRITICAL
github.com/containerd/containerd/v2 v2.0.2 CVE-2024-25621 HIGH
golang.org/x/crypto v0.31.0 CVE-2025-22869 HIGH
golang.org/x/oauth2 v0.24.0 CVE-2025-22868 HIGH
stdlib 1.22.10 CVE-2025-47907 HIGH
stdlib 1.22.10 CVE-2025-58183 HIGH
stdlib 1.22.10 CVE-2025-58186 HIGH
stdlib 1.22.10 CVE-2025-58187 HIGH
stdlib 1.22.10 CVE-2025-58188 HIGH

Source Code Scan Results

🎉 No vulnerabilities found!

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Sep 13, 2025

Open in StackBlitz

npm i https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@10486

commit: d411b74

Copy link
Copy Markdown
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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1)

1249-1255: Typo: Database::forEach vs foreach.

$dbForPlatform->foreach(...) will fatally error; method is forEach(...) elsewhere in this file.

-$dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) {
+$dbForPlatform->forEach('rules', function (Document $rule) use ($dbForPlatform, $deployment) {
🧹 Nitpick comments (5)
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (2)

355-355: Prefer escapeshellarg over escapeshellcmd for paths.

Using escapeshellcmd on $tarParamDirectory (a path) is brittle; use escapeshellarg to avoid quoting issues and injection edges.

-Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr);
+Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellarg($tarParamDirectory) . ' .', '', $stdout, $stderr);

(Repeat the same change at Line 516.)

Also applies to: 516-516


446-452: (Parity) Support template branch in VCS flow as well.

Non-VCS path now handles branch; the VCS+template path still only accepts version (tag). If you want consistent behavior, allow branch here too.

-$templateVersion = $template->getAttribute('version', '');
+$templateVersion = $template->getAttribute('version', '');
+$templateBranch  = $template->getAttribute('branch', '');

-if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateVersion)) {
+if (!empty($templateRepositoryName) && !empty($templateOwnerName) && (!empty($templateVersion) || !empty($templateBranch))) {
   // Clone template repo
   $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '/template';
-
-  $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory);
+  $ref = !empty($templateVersion) ? $templateVersion : $templateBranch;
+  $type = !empty($templateVersion) ? GitHub::CLONE_TYPE_TAG : GitHub::CLONE_TYPE_BRANCH;
+  $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $ref, $type, $tmpTemplateDirectory, $templateRootDirectory);
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php (2)

65-69: Parameter descriptions: avoid “template” wording.

These params refer to the source repository, not a template. Adjust copy to prevent confusion.

-->param('repository', '', new Text(128, 0), 'Repository name of the template.')
-->param('owner', '', new Text(128, 0), 'The name of the owner of the template.')
-->param('rootDirectory', '', new Text(128, 0), 'Path to site code in the template repo.')
+->param('repository', '', new Text(128, 0), 'Repository name.')
+->param('owner', '', new Text(128, 0), 'Repository owner (user or org).')
+->param('rootDirectory', '', new Text(128, 0), 'Path to site code within the repository.')

141-146: Initialize commit details to avoid undefined var notices.

$commitDetails is used later even if the try-block fails before assignment.

-try {
-  $commitDetails = $github->getLatestCommit($owner, $repository, $branch);
-} catch (\Throwable $error) {
+try {
+    $commitDetails = $github->getLatestCommit($owner, $repository, $branch);
+} catch (\Throwable $error) {
     // Ignore; deployment can continue
 }
+// Ensure array shape even on failure
+$commitDetails = $commitDetails ?? [];
src/Appwrite/Platform/Modules/Sites/Services/Http.php (1)

5-15: Fix ordered imports (Pint: ordered_imports).

Sort the Deployments imports to satisfy Pint.

-use Appwrite\Platform\Modules\Sites\Http\Deployments\Create as CreateDeployment;
-use Appwrite\Platform\Modules\Sites\Http\Deployments\Delete as DeleteDeployment;
-use Appwrite\Platform\Modules\Sites\Http\Deployments\Download\Get as DownloadDeployment;
-use Appwrite\Platform\Modules\Sites\Http\Deployments\Duplicate\Create as CreateDuplicateDeployment;
-use Appwrite\Platform\Modules\Sites\Http\Deployments\Direct\Create as CreateDirectDeployment;
-use Appwrite\Platform\Modules\Sites\Http\Deployments\Get as GetDeployment;
-use Appwrite\Platform\Modules\Sites\Http\Deployments\Status\Update as UpdateDeploymentStatus;
-use Appwrite\Platform\Modules\Sites\Http\Deployments\Template\Create as CreateTemplateDeployment;
-use Appwrite\Platform\Modules\Sites\Http\Deployments\Vcs\Create as CreateVcsDeployment;
-use Appwrite\Platform\Modules\Sites\Http\Deployments\XList as ListDeployments;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\Create as CreateDeployment;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\Delete as DeleteDeployment;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\Direct\Create as CreateDirectDeployment;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\Download\Get as DownloadDeployment;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\Duplicate\Create as CreateDuplicateDeployment;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\Get as GetDeployment;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\Status\Update as UpdateDeploymentStatus;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\Template\Create as CreateTemplateDeployment;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\Vcs\Create as CreateVcsDeployment;
+use Appwrite\Platform\Modules\Sites\Http\Deployments\XList as ListDeployments;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b5c5887 and 6e16340.

⛔ Files ignored due to path filters (4)
  • app/config/specs/open-api3-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-server.json is excluded by !app/config/specs/**
📒 Files selected for processing (3)
  • src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1 hunks)
  • src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Sites/Services/Http.php (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php (3)
src/Appwrite/Platform/Modules/Sites/Services/Http.php (2)
  • Http (37-88)
  • __construct (39-87)
src/Appwrite/Event/Event.php (1)
  • Event (10-653)
src/Appwrite/Platform/Modules/Compute/Base.php (1)
  • redeployVcsSite (112-304)
src/Appwrite/Platform/Modules/Sites/Services/Http.php (1)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php (2)
  • Create (28-231)
  • getName (32-35)
🪛 GitHub Actions: Linter
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php

[error] 1-1: Pint: PSR-12 style issue detected (single_space_...) in Builds.php.

src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php

[error] 1-1: Pint: PSR-12 style issue detected (single_space_...) in Create.php.

src/Appwrite/Platform/Modules/Sites/Services/Http.php

[error] 1-1: Pint: PSR-12 style issue detected: ordered_imports

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build SDK
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (1)
src/Appwrite/Platform/Modules/Sites/Services/Http.php (1)

64-65: Registration LGTM.

Action is correctly registered; name aligns with CreateDirectDeployment::getName().

@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 13, 2025

✨ Benchmark results

  • Requests per second: 1,125
  • Requests with 200 status code: 202,545
  • P99 latency: 0.172292732

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 1,125 1,140
200 202,545 205,240
P99 0.172292732 0.181744067

Copy link
Copy Markdown
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1)

1249-1249: Fix typo: call Database::forEach, not foreach.

This is a fatal error at runtime. Match the method used elsewhere in the file.

Apply:

-                    $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) {
+                    $dbForPlatform->forEach('rules', function (Document $rule) use ($dbForPlatform, $deployment) {
♻️ Duplicate comments (1)
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1)

325-334: Create /tmp/builds before cloning + remove stray blank lines.

Without ensuring the parent dir exists, git clone to “/tmp/builds/-template” will fail on fresh workers. This was flagged earlier; still missing here. Also, drop extra blank lines to satisfy Pint.

Apply:

                     // Clone template repo
                     $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '-template';
-
+                    Console::execute('mkdir -p ' . \escapeshellarg('/tmp/builds'), '', $stdout, $stderr);
-                    
-                    if (empty($templateVersion)) {
+                    if (empty($templateVersion)) {
                         $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateBranch, GitHub::CLONE_TYPE_BRANCH, $tmpTemplateDirectory, $templateRootDirectory);
                     } else {
                         // True template
                         $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory);
                     }
-
🧹 Nitpick comments (1)
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1)

436-452: Parity: support templateBranch in VCS+Template merge path too.

The VCS path only clones templates by tag. For consistency with the non‑VCS path and to enable branch-based templates here as well, add branch fallback.

Proposed change:

                 // Build from template
                 $templateRepositoryName = $template->getAttribute('repositoryName', '');
                 $templateOwnerName = $template->getAttribute('ownerName', '');
                 $templateVersion = $template->getAttribute('version', '');
+                $templateBranch = $template->getAttribute('branch', '');

                 $templateRootDirectory = $template->getAttribute('rootDirectory', '');
                 $templateRootDirectory = \rtrim($templateRootDirectory, '/');
                 $templateRootDirectory = \ltrim($templateRootDirectory, '.');
                 $templateRootDirectory = \ltrim($templateRootDirectory, '/');

-                if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateVersion)) {
+                if (!empty($templateRepositoryName) && !empty($templateOwnerName) && (!empty($templateVersion) || !empty($templateBranch))) {
                     // Clone template repo
                     $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '/template';
-
-                    $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory);
+                    $gitCloneCommandForTemplate = empty($templateVersion)
+                        ? $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateBranch, GitHub::CLONE_TYPE_BRANCH, $tmpTemplateDirectory, $templateRootDirectory)
+                        : $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory);
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e16340 and 4858317.

📒 Files selected for processing (3)
  • src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1 hunks)
  • src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Sites/Services/Http.php (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Appwrite/Platform/Modules/Sites/Services/Http.php
  • src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Benchmark
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (Webhooks)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Databases/Legacy)
🔇 Additional comments (2)
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (2)

321-333: Branch fallback logic is correct.

Using branch clone when templateVersion is empty, and tag clone otherwise, reads well and preserves backward compatibility.


314-314: Harden templateBranch input (trim + newline/null guard) — verify GitHub::generateCloneCommand shell-safety

Normalize and validate branch to prevent injection/formatting; generateCloneCommand implementation not found in the provided repo output, so its escaping/quoting can't be confirmed.

Location: src/Appwrite/Platform/Modules/Functions/Workers/Builds.php

Apply:

-                $templateBranch = $template->getAttribute('branch', '');
+                $templateBranch = \trim($template->getAttribute('branch', ''));
+                if ($templateBranch !== '' && \strpbrk($templateBranch, "\r\n\0") !== false) {
+                    throw new \Exception('Invalid template branch value.');
+                }

Either apply the change and ensure GitHub::generateCloneCommand properly quotes/escapes branch/ref inputs, or provide the path to the GitHub class/implementation so I can verify it.

Copy link
Copy Markdown
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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1)

431-447: VCS+Template still uses deprecated templateVersion; breaks new referenceType/referenceValue flow.

This block will no-op now that templates store referenceType/referenceValue, not version.

Apply:

-// Build from template
-$templateRepositoryName = $template->getAttribute('repositoryName', '');
-$templateOwnerName = $template->getAttribute('ownerName', '');
-$templateVersion = $template->getAttribute('version', '');
+// Build from template (supports tag/branch/commit)
+$templateRepositoryName = $template->getAttribute('repositoryName', '');
+$templateOwnerName = $template->getAttribute('ownerName', '');
+$templateReferenceType = $template->getAttribute('referenceType', '');
+$templateReferenceValue = $template->getAttribute('referenceValue', '');

 ...
-if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateVersion)) {
+if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateReferenceType) && !empty($templateReferenceValue)) {
     // Clone template repo
     $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '/template';

-    $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory);
+    $gitCloneCommandForTemplate = $github->generateCloneCommand(
+        $templateOwnerName,
+        $templateRepositoryName,
+        $templateReferenceValue,
+        $templateReferenceType,
+        $tmpTemplateDirectory,
+        $templateRootDirectory
+    );
src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (1)

89-109: Strengthen validation: require (version) XOR (type + reference) and whitelist type.

Prevents empty reference with type set and rejects unknown types early.

Apply:

 public function action(
 ...
     string $version,
     string $type,
     string $reference,
 ...
 ) {
@@
-    if (empty($version) && empty($type) && empty($reference)) {
-        throw new Exception("Either version or type & reference must be provided");
-    }
+    if (empty($version) && empty($type) && empty($reference)) {
+        throw new Exception('Either version or (type & reference) must be provided');
+    }
+    // Enforce pairing and exclusivity
+    if (!empty($type) xor !empty($reference)) {
+        throw new Exception('Both type and reference must be provided together');
+    }
+    if (!empty($version) && (!empty($type) || !empty($reference))) {
+        throw new Exception('Provide either version or (type & reference), not both');
+    }
+
+    // Whitelist type when provided
+    if (!empty($type)) {
+        $allowedRefTypes = [GitHub::CLONE_TYPE_BRANCH, GitHub::CLONE_TYPE_TAG, GitHub::CLONE_TYPE_COMMIT];
+        if (!\in_array($type, $allowedRefTypes, true)) {
+            throw new Exception('Invalid reference type: ' . $type);
+        }
+    }
♻️ Duplicate comments (1)
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1)

321-331: Ensure /tmp/builds exists before cloning (prevents git clone failure).

Parent dir isn’t created in the non‑VCS path; clone to /tmp/builds/-template will fail if /tmp/builds is missing.

Apply:

 if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateReferenceType) && !empty($templateReferenceValue)) {
     $stdout = '';
     $stderr = '';

     // Clone template repo
     $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '-template';
-
-    $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateReferenceValue, $templateReferenceType, $tmpTemplateDirectory, $templateRootDirectory);
+    Console::execute('mkdir -p ' . \escapeshellarg('/tmp/builds'), '', $stdout, $stderr);
+    $gitCloneCommandForTemplate = $github->generateCloneCommand(
+        $templateOwnerName,
+        $templateRepositoryName,
+        $templateReferenceValue,
+        $templateReferenceType,
+        $tmpTemplateDirectory,
+        $templateRootDirectory
+    );
🧹 Nitpick comments (3)
src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1)

313-315: Validate template referenceType against known constants.

Prevent bad inputs from reaching git by whitelisting allowed types.

Apply:

 $templateReferenceType = $template->getAttribute('referenceType', '');
 $templateReferenceValue = $template->getAttribute('referenceValue', '');
+
+// Guard allowed reference types
+$allowedRefTypes = [GitHub::CLONE_TYPE_TAG, GitHub::CLONE_TYPE_BRANCH, GitHub::CLONE_TYPE_COMMIT];
+if (!\in_array($templateReferenceType, $allowedRefTypes, true)) {
+    throw new \Exception('Invalid template referenceType: ' . $templateReferenceType);
+}
src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (1)

68-71: Clarify “type” values in API docs (use tag instead of version).

Align wording with GitHub::CLONE_TYPE_* constants.

Apply:

-->param('type', '', new Text(128, 0), 'Type for the reference provided. Can be commit, branch, or version', true)
+->param('type', '', new Text(128, 0), 'Type for the reference provided. One of: commit | branch | tag', true)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)

70-72: Fix param descriptions (site, and use tag instead of version in type list).

Small doc correctness.

Apply:

-->param('version', '', new Text(128, 0), 'Version (tag) for the repo linked to the function template.', true)
-->param('type', '', new Text(128, 0), 'Type for the reference provided. Can be commit, branch, or version', true)
+->param('version', '', new Text(128, 0), 'Version (tag) for the repo linked to the site template.', true)
+->param('type', '', new Text(128, 0), 'Type for the reference provided. One of: commit | branch | tag', true)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4858317 and 2b1e3bd.

📒 Files selected for processing (3)
  • src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (4 hunks)
  • src/Appwrite/Platform/Modules/Functions/Workers/Builds.php (1 hunks)
  • src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (1)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-447)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (2)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-447)
src/Appwrite/Utopia/Response/Model/Document.php (1)
  • Document (8-112)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (Migrations)
  • GitHub Check: E2E Service Test (VCS)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (GraphQL)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E General Test
  • GitHub Check: Unit Test
  • GitHub Check: Setup & Build SDK
  • GitHub Check: scan
🔇 Additional comments (2)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)

175-183: Deployment type changed to 'vcs' — server-side consumers OK; confirm UI/console

  • No direct equality checks for 'manual' in deployment consumers were found; the only literal 'manual' is for function creation: src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php:338.
  • Deployment type is read/forwarded (APPWRITE_DEPLOYMENT_TYPE) in: src/Appwrite/Platform/Workers/Functions.php:506, src/Appwrite/Platform/Modules/Functions/Workers/Builds.php:621, src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php:380, app/controllers/general.php:492 — these will receive 'vcs'.
  • Action: verify frontend/console and any external consumers accept 'vcs' (outside this repo).
src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (1)

165-171: Verified — changing deployment 'type' to 'vcs' is safe.

No code branches compare deployment.type to 'manual'; VCS behavior is driven by providerRepositoryId/providerBranch and consumers read provider* fields (e.g. src/Appwrite/Platform/Modules/Functions/Workers/Builds.php, app/controllers/api/vcs.php). Non‑VCS template deployments still create 'type' => 'manual' (src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php).

Copy link
Copy Markdown
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: 1

♻️ Duplicate comments (1)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)

110-116: Bug: invalid Exception usage and missing XOR validation (can crash and allow partial input).

  • Throwing new Exception("...") passes the message as the type constant and will break error mapping.
  • Does not enforce version XOR (type AND reference), nor the “both-or-none” constraint for type/reference.

Apply:

-        if (empty($version) && empty($type) && empty($reference)) {
-            throw new Exception("Either version or type & reference must be provided");
-        }
-
-        $referenceType = !empty($version) ? GitHub::CLONE_TYPE_TAG : $type;
-        $referenceValue = !empty($version) ? $version : $reference;
+        // Enforce: version XOR (type AND reference)
+        if (empty($version) && (empty($type) || empty($reference))) {
+            throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Either version or (type & reference) must be provided');
+        }
+        if (!empty($type) xor !empty($reference)) {
+            throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Both type and reference must be provided together');
+        }
+        if (!empty($version) && (!empty($type) || !empty($reference))) {
+            throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Provide either version or (type & reference), not both');
+        }
+        // Defense-in-depth (validator already restricts the values)
+        $allowedRefTypes = [GitHub::CLONE_TYPE_BRANCH, GitHub::CLONE_TYPE_TAG, GitHub::CLONE_TYPE_COMMIT];
+        if (!empty($type) && !\in_array($type, $allowedRefTypes, true)) {
+            throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid reference type: ' . $type);
+        }
+
+        $referenceType = !empty($version) ? GitHub::CLONE_TYPE_TAG : $type;
+        $referenceValue = !empty($version) ? $version : $reference;
🧹 Nitpick comments (1)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)

71-74: Fix param docs and clarify mutual exclusivity (version XOR type+reference).

  • Wording: use “site template” (not “function template”).
  • Use “tag” (not “version”) in the type description; values are branch|commit|tag.
  • Add guidance that clients must send either version or (type + reference).

Apply:

-            ->param('version', '', new Text(128, 0), 'Version (tag) for the repo linked to the function template.', true)
-            ->param('type', '', new WhiteList(['branch', 'commit', 'tag']), 'Type for the reference provided. Can be commit, branch, or version', true)
-            ->param('reference', '', new Text(128, 0), 'Reference value, can be a commit hash, branch name, or release tag', true)
+            ->param('version', '', new Text(128, 0), 'Version (tag) for the repo linked to the site template. Provide either version or (type + reference).', true)
+            ->param('type', '', new WhiteList(['branch', 'commit', 'tag']), 'Type for the reference provided. Can be commit, branch, or tag.', true)
+            ->param('reference', '', new Text(128, 0), 'Reference value: commit SHA, branch name, or tag name.', true)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b1e3bd and fca2727.

⛔ Files ignored due to path filters (4)
  • app/config/specs/open-api3-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-server.json is excluded by !app/config/specs/**
📒 Files selected for processing (2)
  • src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (5 hunks)
  • src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php
🧰 Additional context used
🧬 Code graph analysis (1)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
  • param (254-355)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-447)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (VCS)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E General Test
  • GitHub Check: Unit Test
  • GitHub Check: Benchmark
  • GitHub Check: Setup & Build SDK
  • GitHub Check: scan
🔇 Additional comments (3)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (3)

26-26: LGTM: WhiteList validator import

Import is correct and aligns with the new type enum.


124-126: LGTM: canonical template reference fields

Storing referenceType/referenceValue is the right abstraction for VCS-based templates.


92-94: Signature change looks good — regenerate SDKs/GraphQL & update docs

Both Sites and Functions template Create endpoints mark 'type' and 'reference' optional via ->param(..., true) and their action signatures match (src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php, src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php). Run the SDK / OpenAPI & GraphQL generation and confirm generated SDKs/docs expose these optional params.

Copy link
Copy Markdown
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: 3

🧹 Nitpick comments (3)
src/Appwrite/Utopia/Request/Filters/V21.php (1)

12-17: Scope models are correct — consider centralizing list.
Targets the two template deployment routes only; fine. Optional: lift model names to a private const to avoid typos.

src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (1)

106-108: Build provider links from canonical reference and use strict comparisons.
Precompute repositoryUrl, use it to derive branchUrl, and compare with === to avoid surprises.

Apply:

-        $branchUrl = $type == GitHub::CLONE_TYPE_BRANCH ? "https://github.com/$owner/$repository/tree/$reference" : "";
-        $repositoryUrl = "https://github.com/$owner/$repository";
+        $repositoryUrl = "https://github.com/{$owner}/{$repository}";
+        $branchUrl = $type === GitHub::CLONE_TYPE_BRANCH ? "{$repositoryUrl}/tree/{$reference}" : '';
@@
-            'providerRepositoryName' => $repository,
-            'providerRepositoryOwner' => $owner,
-            'providerRepositoryUrl' => $repositoryUrl,
-            'providerBranchUrl' => $branchUrl,
-            'providerBranch' => $type == GitHub::CLONE_TYPE_BRANCH ? $reference : '',
+            'providerRepositoryName' => $repository,
+            'providerRepositoryOwner' => $owner,
+            'providerRepositoryUrl' => $repositoryUrl,
+            'providerBranchUrl' => $branchUrl,
+            'providerBranch' => $type === GitHub::CLONE_TYPE_BRANCH ? $reference : '',

Also applies to: 156-163

src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)

108-110: Derive URLs from repositoryUrl and use strict comparisons.
Avoid duplicate string assembly and weak equality.

Apply:

-        $branchUrl = $type == GitHub::CLONE_TYPE_BRANCH ? "https://github.com/$owner/$repository/tree/$reference" : "";
-        $repositoryUrl = "https://github.com/$owner/$repository";
+        $repositoryUrl = "https://github.com/{$owner}/{$repository}";
+        $branchUrl = $type === GitHub::CLONE_TYPE_BRANCH ? "{$repositoryUrl}/tree/{$reference}" : '';
@@
-            'providerRepositoryName' => $repository,
-            'providerRepositoryOwner' => $owner,
-            'providerRepositoryUrl' => $repositoryUrl,
-            'providerBranchUrl' => $branchUrl,
-            'providerBranch' => $type == GitHub::CLONE_TYPE_BRANCH ? $reference : '',
+            'providerRepositoryName' => $repository,
+            'providerRepositoryOwner' => $owner,
+            'providerRepositoryUrl' => $repositoryUrl,
+            'providerBranchUrl' => $branchUrl,
+            'providerBranch' => $type === GitHub::CLONE_TYPE_BRANCH ? $reference : '',

Also applies to: 167-175

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fca2727 and 8e32fb0.

⛔ Files ignored due to path filters (4)
  • app/config/specs/open-api3-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-server.json is excluded by !app/config/specs/**
📒 Files selected for processing (4)
  • app/controllers/general.php (2 hunks)
  • src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (5 hunks)
  • src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (5 hunks)
  • src/Appwrite/Utopia/Request/Filters/V21.php (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-12T06:05:27.133Z
Learnt from: abnegate
PR: appwrite/appwrite#9743
File: src/Appwrite/Utopia/Request.php:33-36
Timestamp: 2025-05-12T06:05:27.133Z
Learning: In Appwrite's architecture, the Request class should only filter parameters when filters are explicitly registered. If no filters are present, all parameters should be passed through, and the route action is responsible for validating which parameters are present/valid.

Applied to files:

  • src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php
🧬 Code graph analysis (4)
src/Appwrite/Utopia/Request/Filters/V21.php (1)
src/Appwrite/Utopia/Request/Filter.php (1)
  • Filter (8-57)
app/controllers/general.php (1)
src/Appwrite/Utopia/Request/Filters/V21.php (1)
  • V21 (7-34)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
  • param (254-355)
src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
  • param (254-355)
src/Appwrite/Utopia/Response/Model/Document.php (1)
  • Document (8-112)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build SDK
  • GitHub Check: scan
🔇 Additional comments (4)
app/controllers/general.php (2)

26-26: Add V21 filter import — LGTM.
Import alias is correct and consistent with existing V16–V20 usage.


910-912: Apply V21 for requestFormat < 1.8.1 — LGTM, confirm filter order.
Order is V20 then V21, which is desirable for callers on ≤1.7.x. Just confirm Request::addFilter executes in registration order.

src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (1)

113-115: Template stores canonical reference — LGTM.
Persisting referenceType/referenceValue aligns with build worker expectations.

src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)

115-117: Template stores canonical reference — LGTM.
Matches Functions flow and Build worker expectations.

Copy link
Copy Markdown
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: 2

🧹 Nitpick comments (4)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (2)

506-559: Branch test: avoid hardcoded 'main' and add Retry to curb flakes.

Use template default/provider branch and add #[Retry] to handle transient network/GitHub hiccups.

-    public function testCreateFunctionAndDeploymentFromTemplateBranch()
+    #[Retry(count: 3)]
+    public function testCreateFunctionAndDeploymentFromTemplateBranch()
     {
         $starterTemplate = $this->getTemplate('starter');
@@
-        // Deploy using branch
+        // Deploy using branch
+        $branch = $starterTemplate['body']['providerBranch'] ?? 'main';
         $deployment = $this->createTemplateDeployment(
             $functionId,
             [
@@
-                'type' => 'branch',
-                'reference' => 'main',
+                'type' => 'branch',
+                'reference' => $branch,
             ]
         );

561-619: Commit test: make resilient to missing latestCommit and add Retry.

Skip (not fail) when GitHub is offline/rate‑limited; add #[Retry].

-    public function testCreateFunctionAndDeploymentFromTemplateCommit()
+    #[Retry(count: 3)]
+    public function testCreateFunctionAndDeploymentFromTemplateCommit()
     {
         $starterTemplate = $this->getTemplate('starter');
         $this->assertEquals(200, $starterTemplate['headers']['status-code']);
 
-        // Ensure we have the latest commit
-        $this->assertArrayHasKey('latestCommit', $starterTemplate['body']);
-        $latestCommit = $starterTemplate['body']['latestCommit'];
+        // Ensure we have the latest commit
+        if (!isset($starterTemplate['body']['latestCommit'])) {
+            $this->markTestSkipped('latestCommit could not be resolved from GitHub (rate limit/offline).');
+        }
+        $latestCommit = $starterTemplate['body']['latestCommit'];
tests/e2e/Services/Sites/SitesCustomServerTest.php (2)

1611-1680: Branch test: prefer template/default branch and add Retry.

Avoid hardcoded 'main'; add #[Retry] to reduce external flakiness.

-    public function testCreateSiteFromTemplateBranch()
+    #[Retry(count: 3)]
+    public function testCreateSiteFromTemplateBranch()
     {
         $template = $this->getTemplate('playground-for-astro');
@@
-        $deployment = $this->createTemplateDeployment($siteId, [
+        $branch = $template['body']['providerBranch'] ?? 'main';
+        $deployment = $this->createTemplateDeployment($siteId, [
             'repository' => $template['providerRepositoryId'],
             'owner' => $template['providerOwner'],
             'rootDirectory' => $template['frameworks'][0]['providerRootDirectory'],
             'type' => 'branch',
-            'reference' => 'main',
+            'reference' => $branch,
             'activate' => true
         ]);

1682-1755: Commit test: skip when latestCommit missing and add Retry.

Guard against GitHub outages/rate limits; add #[Retry].

-    public function testCreateSiteFromTemplateCommit()
+    #[Retry(count: 3)]
+    public function testCreateSiteFromTemplateCommit()
     {
         $template = $this->getTemplate('playground-for-astro');
         $this->assertEquals(200, $template['headers']['status-code']);
 
-        // Ensure we have the latest commit
-        $this->assertArrayHasKey('latestCommit', $template['body']);
-        $latestCommit = $template['body']['latestCommit'];
+        // Ensure we have the latest commit
+        if (!isset($template['body']['latestCommit'])) {
+            $this->markTestSkipped('latestCommit could not be resolved from GitHub (rate limit/offline).');
+        }
+        $latestCommit = $template['body']['latestCommit'];
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e32fb0 and 9fe3e94.

📒 Files selected for processing (4)
  • tests/e2e/Services/Functions/FunctionsBase.php (1 hunks)
  • tests/e2e/Services/Functions/FunctionsCustomServerTest.php (2 hunks)
  • tests/e2e/Services/Sites/SitesBase.php (1 hunks)
  • tests/e2e/Services/Sites/SitesCustomServerTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: atharvadeosthale
PR: appwrite/appwrite#10486
File: src/Appwrite/Utopia/Request/Filters/V21.php:25-33
Timestamp: 2025-09-18T07:42:08.717Z
Learning: In Appwrite's V21 request filter for backward compatibility, clients will never send both old (`version`) and new (`type`/`reference`) parameters simultaneously - they use either the old 1.8.0 format or the new 1.8.1+ format, not a mix of both.
🧬 Code graph analysis (2)
tests/e2e/Services/Sites/SitesCustomServerTest.php (2)
tests/e2e/Services/Sites/SitesBase.php (7)
  • getDeployment (187-195)
  • getSite (177-185)
  • setupSiteDomain (374-392)
  • cleanupSite (85-94)
  • getTemplate (326-362)
  • setupSite (21-34)
  • createTemplateDeployment (306-314)
tests/e2e/Client.php (2)
  • Client (8-342)
  • setEndpoint (140-145)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (1)
tests/e2e/Services/Functions/FunctionsBase.php (5)
  • getTemplate (264-300)
  • createFunction (80-88)
  • createTemplateDeployment (244-252)
  • getDeployment (160-168)
  • cleanupFunction (69-78)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: Benchmark
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (VCS)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E General Test
  • GitHub Check: scan
🔇 Additional comments (2)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (1)

403-405: LGTM: migrate to type/reference for tag deployments.

Matches the new API surface; no concerns.

tests/e2e/Services/Sites/SitesCustomServerTest.php (1)

1566-1609: LGTM: Sites template deployment via tag/reference.

Aligns with new API; assertions look good.

Comment on lines +279 to +297
// GitHub API to get latest commit from main branch
$ch = curl_init("https://api.github.com/repos/{$owner}/{$repo}/commits/main");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'User-Agent: Appwrite',
'Accept: application/vnd.github.v3+json'
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 200) {
$commitData = json_decode($response, true);
if (isset($commitData['sha'])) {
$template['body']['latestCommit'] = $commitData['sha'];
}
}
}
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.

⚠️ Potential issue

Same resiliency improvements for GitHub lookup as SitesBase.

Avoid hardcoded "main", add short timeouts, support AUTH header, URL‑encode owner/repo.

-            // GitHub API to get latest commit from main branch
-            $ch = curl_init("https://api.github.com/repos/{$owner}/{$repo}/commits/main");
-            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-            curl_setopt($ch, CURLOPT_HTTPHEADER, [
-                'User-Agent: Appwrite',
-                'Accept: application/vnd.github.v3+json'
-            ]);
-
-            $response = curl_exec($ch);
-            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
-            curl_close($ch);
-
-            if ($httpCode === 200) {
-                $commitData = json_decode($response, true);
-                if (isset($commitData['sha'])) {
-                    $template['body']['latestCommit'] = $commitData['sha'];
-                }
-            }
+            $ownerEnc = rawurlencode((string)$owner);
+            $repoEnc  = rawurlencode((string)$repo);
+            $headers  = ['User-Agent: Appwrite', 'Accept: application/vnd.github+json'];
+            $token    = \Utopia\System\System::getEnv('GITHUB_TOKEN') ?: \Utopia\System\System::getEnv('GITHUB_API_TOKEN');
+            if ($token) {
+                $headers[] = 'Authorization: Bearer ' . $token;
+            }
+            $branch = $template['body']['providerBranch'] ?? null;
+            if (!$branch) {
+                $ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}");
+                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+                curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+                $repoResp = curl_exec($ch);
+                $repoCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+                curl_close($ch);
+                $branch = ($repoCode === 200 && is_string($repoResp))
+                    ? (json_decode($repoResp, true)['default_branch'] ?? 'main')
+                    : 'main';
+            }
+            $ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}/commits/{$branch}");
+            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+            $response = curl_exec($ch);
+            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+            curl_close($ch);
+            if ($httpCode === 200 && is_string($response)) {
+                $commitData = json_decode($response, true);
+                if (isset($commitData['sha'])) {
+                    $template['body']['latestCommit'] = $commitData['sha'];
+                }
+            }
📝 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.

Suggested change
// GitHub API to get latest commit from main branch
$ch = curl_init("https://api.github.com/repos/{$owner}/{$repo}/commits/main");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'User-Agent: Appwrite',
'Accept: application/vnd.github.v3+json'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$commitData = json_decode($response, true);
if (isset($commitData['sha'])) {
$template['body']['latestCommit'] = $commitData['sha'];
}
}
}
$ownerEnc = rawurlencode((string)$owner);
$repoEnc = rawurlencode((string)$repo);
$headers = ['User-Agent: Appwrite', 'Accept: application/vnd.github+json'];
$token = \Utopia\System\System::getEnv('GITHUB_TOKEN') ?: \Utopia\System\System::getEnv('GITHUB_API_TOKEN');
if ($token) {
$headers[] = 'Authorization: Bearer ' . $token;
}
$branch = $template['body']['providerBranch'] ?? null;
if (!$branch) {
$ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$repoResp = curl_exec($ch);
$repoCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$branch = ($repoCode === 200 && is_string($repoResp))
? (json_decode($repoResp, true)['default_branch'] ?? 'main')
: 'main';
}
$ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}/commits/{$branch}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && is_string($response)) {
$commitData = json_decode($response, true);
if (isset($commitData['sha'])) {
$template['body']['latestCommit'] = $commitData['sha'];
}
}
}
🤖 Prompt for AI Agents
In tests/e2e/Services/Functions/FunctionsBase.php around lines 279-297, the
GitHub API call is fragile: it hardcodes "main", lacks timeouts, doesn't support
Authorization, and doesn't URL-encode owner/repo; update the request to use a
branch variable (default from env or parameter instead of hardcoded "main"),
URL-encode $owner and $repo before building the URL, add short curl timeouts
(CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT), conditionally add an
Authorization: Bearer <token> header when a GITHUB_TOKEN (or similar) is
available, and preserve existing headers; also ensure curl errors and non-200
responses are handled gracefully before accessing json fields.

Comment on lines +341 to +358
// GitHub API to get latest commit from main branch
$ch = curl_init("https://api.github.com/repos/{$owner}/{$repo}/commits/main");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'User-Agent: Appwrite',
'Accept: application/vnd.github.v3+json'
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 200) {
$commitData = json_decode($response, true);
if (isset($commitData['sha'])) {
$template['body']['latestCommit'] = $commitData['sha'];
}
}
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.

⚠️ Potential issue

Harden GitHub commit lookup: respect default branch, add timeouts, optional token, and URL‑encode.

Hardcoding "main" and omitting curl timeouts can cause flakes/hangs in CI; also support private repos/rate limits via a token.

Apply:

-            // GitHub API to get latest commit from main branch
-            $ch = curl_init("https://api.github.com/repos/{$owner}/{$repo}/commits/main");
-            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-            curl_setopt($ch, CURLOPT_HTTPHEADER, [
-                'User-Agent: Appwrite',
-                'Accept: application/vnd.github.v3+json'
-            ]);
-
-            $response = curl_exec($ch);
-            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
-            curl_close($ch);
-
-            if ($httpCode === 200) {
-                $commitData = json_decode($response, true);
-                if (isset($commitData['sha'])) {
-                    $template['body']['latestCommit'] = $commitData['sha'];
-                }
-            }
+            // Resolve branch -> prefer template's providerBranch, else repo default_branch, else 'main'
+            $ownerEnc = rawurlencode((string)$owner);
+            $repoEnc  = rawurlencode((string)$repo);
+            $headers  = ['User-Agent: Appwrite', 'Accept: application/vnd.github+json'];
+            $token    = \Utopia\System\System::getEnv('GITHUB_TOKEN') ?: \Utopia\System\System::getEnv('GITHUB_API_TOKEN');
+            if ($token) {
+                $headers[] = 'Authorization: Bearer ' . $token;
+            }
+            $branch = $template['body']['providerBranch'] ?? null;
+            if (!$branch) {
+                $ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}");
+                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+                curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+                $repoResp = curl_exec($ch);
+                $repoCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+                curl_close($ch);
+                $branch = ($repoCode === 200 && is_string($repoResp))
+                    ? (json_decode($repoResp, true)['default_branch'] ?? 'main')
+                    : 'main';
+            }
+            $ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}/commits/{$branch}");
+            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+            $response = curl_exec($ch);
+            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+            curl_close($ch);
+            if ($httpCode === 200 && is_string($response)) {
+                $commitData = json_decode($response, true);
+                if (isset($commitData['sha'])) {
+                    $template['body']['latestCommit'] = $commitData['sha'];
+                }
+            }
📝 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.

Suggested change
// GitHub API to get latest commit from main branch
$ch = curl_init("https://api.github.com/repos/{$owner}/{$repo}/commits/main");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'User-Agent: Appwrite',
'Accept: application/vnd.github.v3+json'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$commitData = json_decode($response, true);
if (isset($commitData['sha'])) {
$template['body']['latestCommit'] = $commitData['sha'];
}
}
// Resolve branch -> prefer template's providerBranch, else repo default_branch, else 'main'
$ownerEnc = rawurlencode((string)$owner);
$repoEnc = rawurlencode((string)$repo);
$headers = ['User-Agent: Appwrite', 'Accept: application/vnd.github+json'];
$token = \Utopia\System\System::getEnv('GITHUB_TOKEN') ?: \Utopia\System\System::getEnv('GITHUB_API_TOKEN');
if ($token) {
$headers[] = 'Authorization: Bearer ' . $token;
}
$branch = $template['body']['providerBranch'] ?? null;
if (!$branch) {
$ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$repoResp = curl_exec($ch);
$repoCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$branch = ($repoCode === 200 && is_string($repoResp))
? (json_decode($repoResp, true)['default_branch'] ?? 'main')
: 'main';
}
$ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}/commits/{$branch}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && is_string($response)) {
$commitData = json_decode($response, true);
if (isset($commitData['sha'])) {
$template['body']['latestCommit'] = $commitData['sha'];
}
}
🤖 Prompt for AI Agents
In tests/e2e/Services/Sites/SitesBase.php around lines 341-358, the GitHub
commit lookup is brittle: it hardcodes "main", lacks URL-encoding, timeouts,
optional auth, and robust error handling; update the flow to first GET
https://api.github.com/repos/{owner}/{repo} (with owner/repo URL-encoded) to
read default_branch, then request the commit for that branch; set curl options
CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT, CURLOPT_FAILONERROR, and add an
Authorization: Bearer <token> header when a GITHUB_TOKEN env var is present to
handle private repos/rate limits; ensure headers include User-Agent and Accept,
check curl_exec for false and handle curl_error, validate HTTP codes before
json_decode, and extract the commit SHA reliably (top-level "sha" or from
"commit") before assigning template['body']['latestCommit'].

Copy link
Copy Markdown
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: 1

♻️ Duplicate comments (3)
tests/e2e/Services/Sites/SitesBase.php (1)

336-357: Harden GitHub commit lookup: respect default branch, add timeouts, optional token, and URL‑encode.

Current code hardcodes "main", lacks timeouts, and doesn’t support private/rate‑limited repos. Improve resilience and CI stability.

Apply:

-    protected function helperGetLatestCommit(string $owner, string $repository): ?string
+    protected function helperGetLatestCommit(string $owner, string $repository, ?string $branch = null): ?string
     {
-        $ch = curl_init("https://api.github.com/repos/{$owner}/{$repository}/commits/main");
-        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-        curl_setopt($ch, CURLOPT_HTTPHEADER, [
-            'User-Agent: Appwrite',
-            'Accept: application/vnd.github.v3+json'
-        ]);
-
-        $response = curl_exec($ch);
-        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
-        curl_close($ch);
-
-        if ($httpCode === 200) {
-            $commitData = json_decode($response, true);
-            if (isset($commitData['sha'])) {
-                return $commitData['sha'];
-            }
-        }
-
-        return null;
+        $ownerEnc = rawurlencode((string) $owner);
+        $repoEnc  = rawurlencode((string) $repository);
+
+        $headers = ['User-Agent: Appwrite', 'Accept: application/vnd.github+json'];
+        $token   = System::getEnv('GITHUB_TOKEN') ?: System::getEnv('GITHUB_API_TOKEN');
+        if ($token) {
+            $headers[] = 'Authorization: Bearer ' . $token;
+        }
+
+        // Resolve branch: prefer provided, else repo default_branch, else 'main'
+        if ($branch === null || $branch === '') {
+            $ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}");
+            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+            $repoResp = curl_exec($ch);
+            $repoCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+            curl_close($ch);
+            $branch = ($repoCode === 200 && is_string($repoResp))
+                ? (json_decode($repoResp, true)['default_branch'] ?? 'main')
+                : 'main';
+        }
+
+        $branchEnc = rawurlencode((string) $branch);
+        $ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}/commits/{$branchEnc}");
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+        $response = curl_exec($ch);
+        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+        curl_close($ch);
+
+        if ($httpCode === 200 && is_string($response)) {
+            $commitData = json_decode($response, true);
+            if (is_array($commitData)) {
+                if (isset($commitData['sha']) && is_string($commitData['sha'])) {
+                    return $commitData['sha'];
+                }
+                // Be tolerant if an array is ever returned
+                if (isset($commitData[0]['sha']) && is_string($commitData[0]['sha'])) {
+                    return $commitData[0]['sha'];
+                }
+            }
+        }
+        return null;
     }
tests/e2e/Services/Functions/FunctionsBase.php (1)

274-295: Harden GitHub lookup: encode owner/repo, short timeouts, optional auth, default branch discovery, and error checks.

Avoid hardcoding "main" and make this resilient to rate limits and slow networks.

Apply:

-    protected function helperGetLatestCommit(string $owner, string $repository): ?string
-    {
-        $ch = curl_init("https://api.github.com/repos/{$owner}/{$repository}/commits/main");
-        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-        curl_setopt($ch, CURLOPT_HTTPHEADER, [
-            'User-Agent: Appwrite',
-            'Accept: application/vnd.github.v3+json'
-        ]);
-
-        $response = curl_exec($ch);
-        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
-        curl_close($ch);
-
-        if ($httpCode === 200) {
-            $commitData = json_decode($response, true);
-            if (isset($commitData['sha'])) {
-                return $commitData['sha'];
-            }
-        }
-
-        return null;
-    }
+    protected function helperGetLatestCommit(string $owner, string $repository): ?string
+    {
+        $ownerEnc = rawurlencode((string) $owner);
+        $repoEnc  = rawurlencode((string) $repository);
+        $headers  = ['User-Agent: Appwrite', 'Accept: application/vnd.github+json'];
+        $token    = System::getEnv('GITHUB_TOKEN') ?: System::getEnv('GITHUB_API_TOKEN');
+        if ($token) {
+            $headers[] = 'Authorization: Bearer ' . $token;
+        }
+
+        // Discover default branch
+        $ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}");
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+        $repoResp = curl_exec($ch);
+        $repoCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+        curl_close($ch);
+
+        $branch = 'main';
+        if ($repoCode === 200 && is_string($repoResp)) {
+            $branch = json_decode($repoResp, true)['default_branch'] ?? 'main';
+        }
+
+        // Fetch latest commit on the resolved branch
+        $ch = curl_init("https://api.github.com/repos/{$ownerEnc}/{$repoEnc}/commits/{$branch}");
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+        $response = curl_exec($ch);
+        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+        curl_close($ch);
+
+        if ($httpCode === 200 && is_string($response)) {
+            $commitData = json_decode($response, true);
+            if (isset($commitData['sha']) && is_string($commitData['sha'])) {
+                return $commitData['sha'];
+            }
+        }
+        return null;
+    }
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (1)

411-416: Nice: wait for readiness before assertions.

Addresses prior flakiness feedback.

🧹 Nitpick comments (5)
tests/e2e/Services/Sites/SitesBase.php (1)

336-357: Thread providerBranch into helperGetLatestCommit and dedupe duplicate helpers

  • Add an optional $branch parameter to helperGetLatestCommit and use it in the GitHub URL instead of hardcoding "main".
  • Update callers to pass providerBranch where available (e.g. tests/e2e/Services/Sites/SitesCustomServerTest.php:1688, tests/e2e/Services/Functions/FunctionsCustomServerTest.php:577).
  • Consolidate duplicate helpers in tests/e2e/Services/Sites/SitesBase.php (≈line 336) and tests/e2e/Services/Functions/FunctionsBase.php (≈line 274) into a shared test utility to avoid drift.
tests/e2e/Services/Functions/FunctionsBase.php (1)

274-295: Deduplicate: share one helper with SitesBase.

Extract this GitHub helper to a common test utility to prevent drift between FunctionsBase and SitesBase.

tests/e2e/Services/Functions/FunctionsCustomServerTest.php (3)

364-367: Guard against missing runtime match to avoid undefined offset.

Add a sanity check before indexing the filtered array.

-        $runtime = array_values(array_filter($starterTemplate['body']['runtimes'], function ($runtime) {
-            return $runtime['name'] === 'node-22';
-        }))[0];
+        $matches = array_values(array_filter($starterTemplate['body']['runtimes'], fn($r) => $r['name'] === 'node-22'));
+        $this->assertNotEmpty($matches, 'starter template is missing runtime node-22');
+        $runtime = $matches[0];

Also applies to: 377-377, 382-382, 386-386


548-549: Avoid hardcoded 'main' and extend wait to reduce flakes.

Use template default branch when available; give builds more time.

-                'type' => 'branch',
-                'reference' => 'main',
+                'type' => 'branch',
+                'reference' => $starterTemplate['body']['providerBranch'] ?? 'main',
@@
-        }, 50000, 500);
+        }, 100000, 500);

Also applies to: 556-560


571-581: Commit test: rely on robust helper and increase wait budget.

After hardening helperGetLatestCommit, bump the readiness wait to match other tests.

-        }, 50000, 500);
+        }, 100000, 500);

Also applies to: 628-631

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9fe3e94 and 2a145bc.

📒 Files selected for processing (4)
  • tests/e2e/Services/Functions/FunctionsBase.php (1 hunks)
  • tests/e2e/Services/Functions/FunctionsCustomServerTest.php (5 hunks)
  • tests/e2e/Services/Sites/SitesBase.php (1 hunks)
  • tests/e2e/Services/Sites/SitesCustomServerTest.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/Services/Sites/SitesCustomServerTest.php
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: atharvadeosthale
PR: appwrite/appwrite#10486
File: src/Appwrite/Utopia/Request/Filters/V21.php:25-33
Timestamp: 2025-09-18T07:42:08.734Z
Learning: In Appwrite's V21 request filter for backward compatibility, clients will never send both old (`version`) and new (`type`/`reference`) parameters simultaneously - they use either the old 1.8.0 format or the new 1.8.1+ format, not a mix of both.
🧬 Code graph analysis (2)
tests/e2e/Services/Functions/FunctionsBase.php (1)
tests/e2e/Services/Sites/SitesBase.php (1)
  • helperGetLatestCommit (336-357)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (1)
tests/e2e/Services/Functions/FunctionsBase.php (6)
  • getDeployment (160-168)
  • getTemplate (264-272)
  • createFunction (80-88)
  • createTemplateDeployment (244-252)
  • cleanupFunction (69-78)
  • helperGetLatestCommit (274-295)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build SDK
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (3)
tests/e2e/Services/Sites/SitesBase.php (1)

336-357: Good extraction into a helper; preserves getTemplate’s contract.

Moving GitHub lookup out of getTemplate aligns with the API mirroring requirement and unblocks template changes.

tests/e2e/Services/Functions/FunctionsCustomServerTest.php (2)

403-405: Typed template deployment (tag) looks good.

Using type=tag with reference=providerVersion aligns with the new API.


418-425: Good: verify non-zero sizes and total equals sum.

Solid assertions to prevent regressions in size accounting.

Also applies to: 434-435

Copy link
Copy Markdown
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)
tests/e2e/General/UsageTest.php (1)

45-76: Keep alias symmetry and drop duplicate alias lines in trait adaptations

For consistency with other methods, also alias the SitesBase variant, and remove repeated alias lines to reduce noise.

 use SitesBase {
   FunctionsBase::createDeployment insteadof SitesBase;
   FunctionsBase::setupDeployment insteadof SitesBase;
   FunctionsBase::createVariable insteadof SitesBase;
   FunctionsBase::getVariable insteadof SitesBase;
   FunctionsBase::listVariables insteadof SitesBase;
   FunctionsBase::helperGetLatestCommit insteadof SitesBase;
   FunctionsBase::updateVariable insteadof SitesBase;
   FunctionsBase::deleteVariable insteadof SitesBase;
   FunctionsBase::getDeployment insteadof SitesBase;
   FunctionsBase::listDeployments insteadof SitesBase;
   FunctionsBase::deleteDeployment insteadof SitesBase;
   FunctionsBase::setupDuplicateDeployment insteadof SitesBase;
   FunctionsBase::createDuplicateDeployment insteadof SitesBase;
   FunctionsBase::createTemplateDeployment insteadof SitesBase;
   FunctionsBase::getUsage insteadof SitesBase;
   FunctionsBase::getTemplate insteadof SitesBase;
   FunctionsBase::getDeploymentDownload insteadof SitesBase;
   FunctionsBase::cancelDeployment insteadof SitesBase;
   FunctionsBase::listSpecifications insteadof SitesBase;
   SitesBase::createDeployment as createDeploymentSite;
   SitesBase::setupDeployment as setupDeploymentSite;
   SitesBase::createVariable as createVariableSite;
   SitesBase::getVariable as getVariableSite;
-  SitesBase::listVariables as listVariablesSite;
-  SitesBase::listVariables as listVariablesSite;
+  SitesBase::listVariables as listVariablesSite;
+  SitesBase::helperGetLatestCommit as helperGetLatestCommitSite;
-  SitesBase::updateVariable as updateVariableSite;
-  SitesBase::updateVariable as updateVariableSite;
+  SitesBase::updateVariable as updateVariableSite;
-  SitesBase::deleteVariable as deleteVariableSite;
-  SitesBase::deleteVariable as deleteVariableSite;
+  SitesBase::deleteVariable as deleteVariableSite;
-  SitesBase::getDeployment as getDeploymentSite;
-  SitesBase::getDeployment as getDeploymentSite;
+  SitesBase::getDeployment as getDeploymentSite;
-  SitesBase::listDeployments as listDeploymentsSite;
-  SitesBase::listDeployments as listDeploymentsSite;
+  SitesBase::listDeployments as listDeploymentsSite;
-  SitesBase::deleteDeployment as deleteDeploymentSite;
-  SitesBase::deleteDeployment as deleteDeploymentSite;
+  SitesBase::deleteDeployment as deleteDeploymentSite;
-  SitesBase::setupDuplicateDeployment as setupDuplicateDeploymentSite;
-  SitesBase::setupDuplicateDeployment as setupDuplicateDeploymentSite;
+  SitesBase::setupDuplicateDeployment as setupDuplicateDeploymentSite;
-  SitesBase::createDuplicateDeployment as createDuplicateDeploymentSite;
-  SitesBase::createDuplicateDeployment as createDuplicateDeploymentSite;
+  SitesBase::createDuplicateDeployment as createDuplicateDeploymentSite;
-  SitesBase::createTemplateDeployment as createTemplateDeploymentSite;
-  SitesBase::createTemplateDeployment as createTemplateDeploymentSite;
+  SitesBase::createTemplateDeployment as createTemplateDeploymentSite;
-  SitesBase::getUsage as getUsageSite;
-  SitesBase::getUsage as getUsageSite;
+  SitesBase::getUsage as getUsageSite;
-  SitesBase::getTemplate as getTemplateSite;
-  SitesBase::getTemplate as getTemplateSite;
+  SitesBase::getTemplate as getTemplateSite;
-  SitesBase::getDeploymentDownload as getDeploymentDownloadSite;
-  SitesBase::getDeploymentDownload as getDeploymentDownloadSite;
+  SitesBase::getDeploymentDownload as getDeploymentDownloadSite;
-  SitesBase::cancelDeployment as cancelDeploymentSite;
-  SitesBase::cancelDeployment as cancelDeploymentSite;
+  SitesBase::cancelDeployment as cancelDeploymentSite;
   SitesBase::listSpecifications as listSpecificationsSite;
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a145bc and 1a19e01.

📒 Files selected for processing (1)
  • tests/e2e/General/UsageTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: atharvadeosthale
PR: appwrite/appwrite#10486
File: src/Appwrite/Utopia/Request/Filters/V21.php:25-33
Timestamp: 2025-09-18T07:42:08.734Z
Learning: In Appwrite's V21 request filter for backward compatibility, clients will never send both old (`version`) and new (`type`/`reference`) parameters simultaneously - they use either the old 1.8.0 format or the new 1.8.1+ format, not a mix of both.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Migrations)
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Webhooks)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E General Test
  • GitHub Check: Unit Test
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: Setup & Build SDK
  • GitHub Check: scan
🔇 Additional comments (1)
tests/e2e/General/UsageTest.php (1)

31-31: LGTM — prefer FunctionsBase::helperGetLatestCommit; confirm implementations match

Both helpers are defined (FunctionsBase: tests/e2e/Services/Functions/FunctionsBase.php:274; SitesBase: tests/e2e/Services/Sites/SitesBase.php:336) and are used from the corresponding *CustomServerTest.php files. Sandbox extraction failed to produce a reliable diff of the full function bodies — run a local diff to confirm behavioral parity, e.g.:

sed -n '/protected function helperGetLatestCommit/,/}/p' tests/e2e/Services/Functions/FunctionsBase.php > /tmp/fn1 && sed -n '/protected function helperGetLatestCommit/,/}/p' tests/e2e/Services/Sites/SitesBase.php > /tmp/fn2 && diff -u /tmp/fn1 /tmp/fn2

Copy link
Copy Markdown
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

♻️ Duplicate comments (2)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (2)

418-425: Addresses prior ask: verify non‑zero sizes and total

Nice addition; this covers readiness and size integrity.


503-504: Resolved: don’t assign result of void cleanupFunction()

Assignment removed; this fixes the fatal noted earlier.

🧹 Nitpick comments (13)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (13)

364-367: Guard against missing runtime before indexing

array_filter can return an empty array; indexing [0] would raise a notice/fatal. Assert non‑empty before dereferencing.

Apply this diff:

-$runtime = array_values(array_filter($starterTemplate['body']['runtimes'], function ($runtime) {
-    return $runtime['name'] === 'node-22';
-}))[0];
+$runtimes = array_values(array_filter($starterTemplate['body']['runtimes'], function ($runtime) {
+    return $runtime['name'] === 'node-22';
+}));
+$this->assertNotEmpty($runtimes, 'node-22 runtime not found in template runtimes');
+$runtime = $runtimes[0];

411-417: Also assert HTTP 200 inside the polling closure

Adds early signal if the resource vanishes or returns errors instead of silently looping.

 $this->assertEventually(function () use ($functionId, $deploymentId) {
     $deployment = $this->getDeployment($functionId, $deploymentId);
-    $this->assertEquals('ready', $deployment['body']['status']);
+    $this->assertEquals(200, $deployment['headers']['status-code']);
+    $this->assertEquals('ready', $deployment['body']['status']);
 }, 50000, 500);

433-435: Also assert buildSize on the list view

Validates parity between single‑item GET and list results.

 $this->assertNotEmpty($lastDeployment['$id']);
 $this->assertGreaterThan(0, $lastDeployment['sourceSize']);
+$this->assertGreaterThan(0, $lastDeployment['buildSize']);

506-531: Mark network/VCS test retriable to reduce flakiness

Branch deployments can be slow or transient; add Retry to smooth CI flakes.

+#[Retry(count: 3)]
 public function testCreateFunctionAndDeploymentFromTemplateBranch()

538-550: Avoid hardcoding 'main' branch

Prefer the template’s default branch (if exposed in the template payload) and fall back to 'main' only if not present. Please confirm the field name in the response (e.g., a “default branch” field) and use it here.

Would you verify the template response exposes a default-branch field and wire it in here instead of the literal 'main'?


561-567: Assert deployment type is 'vcs'

Completes validation that the new VCS flow is used.

 $deployment = $this->getDeployment($functionId, $deploymentId);
 $this->assertEquals(200, $deployment['headers']['status-code']);
 $this->assertGreaterThan(0, $deployment['body']['sourceSize']);
 $this->assertGreaterThan(0, $deployment['body']['buildSize']);
 $totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize'];
 $this->assertEquals($totalSize, $deployment['body']['totalSize']);
+$this->assertEquals('vcs', $deployment['body']['type']);

576-582: External GitHub call: add token support and retries in helper

Unauthenticated GitHub API calls are rate‑limited and can flake. Enhance helperGetLatestCommit to use GITHUB_TOKEN if present and retry a few times.

Proposed helper tweak (in tests/e2e/Services/Functions/FunctionsBase.php):

$ch = curl_init("https://api.github.com/repos/{$owner}/{$repository}/commits/main");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$headers = ['User-Agent: Appwrite', 'Accept: application/vnd.github.v3+json'];
if ($token = getenv('GITHUB_TOKEN')) {
    $headers[] = "Authorization: Bearer {$token}";
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

// simple retry
for ($i = 0; $i < 3; $i++) {
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($httpCode === 200 && $response) break;
    usleep(250000);
}

Optionally also add #[Retry(count: 3)] to this test, like the branch test.


583-586: Same runtime guard here

Replicate the empty‑check before indexing as above.

-$runtime = array_values(array_filter($starterTemplate['body']['runtimes'], function ($runtime) {
-    return $runtime['name'] === 'node-22';
-}))[0];
+$runtimes = array_values(array_filter($starterTemplate['body']['runtimes'], function ($runtime) {
+    return $runtime['name'] === 'node-22';
+}));
+$this->assertNotEmpty($runtimes, 'node-22 runtime not found in template runtimes');
+$runtime = $runtimes[0];

610-622: Assert deployment type is 'vcs' for commit flow

Mirror the branch test and confirm the new flow.

 $deployment = $this->createTemplateDeployment(
     $functionId,
     [
         'resourceId' => ID::unique(),
         'activate' => true,
         'repository' => $starterTemplate['body']['providerRepositoryId'],
         'owner' => $starterTemplate['body']['providerOwner'],
         'rootDirectory' => $runtime['providerRootDirectory'],
         'type' => 'commit',
         'reference' => $latestCommit,
     ]
 );

After readiness and size checks, add:

$this->assertEquals('vcs', $deployment['body']['type']);

627-632: Also assert HTTP 200 in the wait loop

Consistent with other suggestions.

 $this->assertEventually(function () use ($functionId, $deploymentId) {
     $deployment = $this->getDeployment($functionId, $deploymentId);
-    $this->assertEquals('ready', $deployment['body']['status']);
+    $this->assertEquals(200, $deployment['headers']['status-code']);
+    $this->assertEquals('ready', $deployment['body']['status']);
 }, 50000, 500);

633-639: Optionally assert function.active deployment equals this deployment

Ensures the activation flag took effect.

 $deployment = $this->getDeployment($functionId, $deploymentId);
 $this->assertEquals(200, $deployment['headers']['status-code']);
 $this->assertGreaterThan(0, $deployment['body']['sourceSize']);
 $this->assertGreaterThan(0, $deployment['body']['buildSize']);
 $totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize'];
 $this->assertEquals($totalSize, $deployment['body']['totalSize']);
+
+$function = $this->getFunction($functionId);
+$this->assertEquals(200, $function['headers']['status-code']);
+$this->assertEquals($deploymentId, $function['body']['deploymentId']);

511-514: Repeat runtime guard in Branch test

Same undefined‑offset risk; add the non‑empty assertion before [0] access.

-$runtime = array_values(array_filter($starterTemplate['body']['runtimes'], function ($runtime) {
-    return $runtime['name'] === 'node-22';
-}))[0];
+$runtimes = array_values(array_filter($starterTemplate['body']['runtimes'], function ($runtime) {
+    return $runtime['name'] === 'node-22';
+}));
+$this->assertNotEmpty($runtimes, 'node-22 runtime not found in template runtimes');
+$runtime = $runtimes[0];

506-506: Add Retry attribute to both VCS template tests

Both paths hit external providers; make both retriable.

+#[Retry(count: 3)]
 public function testCreateFunctionAndDeploymentFromTemplateBranch()
+#[Retry(count: 3)]
 public function testCreateFunctionAndDeploymentFromTemplateCommit()

Also applies to: 571-571

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a19e01 and 7d4486b.

📒 Files selected for processing (1)
  • tests/e2e/Services/Functions/FunctionsCustomServerTest.php (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (1)
tests/e2e/Services/Functions/FunctionsBase.php (6)
  • getDeployment (160-168)
  • cleanupFunction (69-78)
  • getTemplate (264-272)
  • createFunction (80-88)
  • createTemplateDeployment (244-252)
  • helperGetLatestCommit (274-295)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (VCS)
  • GitHub Check: E2E Service Test (Users)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E General Test
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: Unit Test
  • GitHub Check: Benchmark
  • GitHub Check: Setup & Build SDK
  • GitHub Check: scan
🔇 Additional comments (2)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (2)

377-377: LGTM: using runtime-derived entrypoint/commands/rootDirectory

This aligns function config with the selected runtime metadata.

Also applies to: 382-382, 386-386


402-405: Template deployment via (type, reference) — good

Using type=tag with provider version is correct for the tag flow.

Copy link
Copy Markdown

@Aglowharmony Aglowharmony left a comment

Choose a reason for hiding this comment

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

Merge this to main

Copy link
Copy Markdown
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

♻️ Duplicate comments (4)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (2)

71-72: Make type and reference required parameters.

The empty-string defaults allow these parameters to be omitted or empty, but the endpoint requires both for correct behavior. Remove the defaults to make them required and prevent empty values from reaching the action.

Apply this diff:

-            ->param('type', '', new WhiteList(['branch', 'commit', 'tag']), 'Type for the reference provided. Can be commit, branch, or tag')
-            ->param('reference', '', new Text(128, 0), 'Reference value, can be a commit hash, branch name, or release tag')
+            ->param('type', null, new WhiteList(['branch', 'commit', 'tag'], required: true), 'Type for the reference provided. Can be commit, branch, or tag')
+            ->param('reference', null, new Text(128, 1), 'Reference value, can be a commit hash, branch name, or release tag')

167-174: Use strict comparison for type checks.

Line 171 uses loose equality (==) which can lead to unexpected type coercion. Use strict comparison (===) to ensure exact match.

Apply this diff:

             'providerRepositoryName' => $repository,
             'providerRepositoryOwner' => $owner,
             'providerRepositoryUrl' => $repositoryUrl,
             'providerBranchUrl' => $branchUrl,
-            'providerBranch' => $type == GitHub::CLONE_TYPE_BRANCH ? $reference : '',
+            'providerBranch' => $type === GitHub::CLONE_TYPE_BRANCH ? $reference : '',
             'adapter' => $site->getAttribute('adapter', ''),
             'fallbackFile' => $site->getAttribute('fallbackFile', ''),
             'type' => 'vcs',
src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (2)

69-70: Make type and reference required parameters.

The empty-string defaults allow these parameters to be omitted or empty, but the endpoint requires both for correct behavior. Remove the defaults to make them required and prevent empty values from reaching the action.

Apply this diff:

-            ->param('type', '', new WhiteList(['commit', 'branch', 'tag']), 'Type for the reference provided. Can be commit, branch, or tag')
-            ->param('reference', '', new Text(128, 0), 'Reference value, can be a commit hash, branch name, or release tag')
+            ->param('type', null, new WhiteList(['commit', 'branch', 'tag'], required: true), 'Type for the reference provided. Can be commit, branch, or tag')
+            ->param('reference', null, new Text(128, 1), 'Reference value, can be a commit hash, branch name, or release tag')

157-162: Use strict comparison for type checks.

Line 161 uses loose equality (==) which can lead to unexpected type coercion. Use strict comparison (===) to ensure exact match.

Apply this diff:

             'providerRepositoryName' => $repository,
             'providerRepositoryOwner' => $owner,
             'providerRepositoryUrl' => $repositoryUrl,
             'providerBranchUrl' => $branchUrl,
-            'providerBranch' => $type == GitHub::CLONE_TYPE_BRANCH ? $reference : '',
+            'providerBranch' => $type === GitHub::CLONE_TYPE_BRANCH ? $reference : '',
             'type' => 'vcs',
             'activate' => $activate,
🧹 Nitpick comments (2)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)

108-109: Build branchUrl only for branch references; use blob path for all types.

Currently branchUrl is built for all reference types. However, based on maintainer feedback, GitHub's blob path works for commits, branches, and tags. Consider renaming to reflect this, or verify the URL is appropriate for the given type.

For example:

-        $branchUrl = "https://github.com/$owner/$repository/blob/$reference";
+        $referenceUrl = "https://github.com/$owner/$repository/blob/$reference";
         $repositoryUrl = "https://github.com/$owner/$repository";

Then update the deployment payload field name accordingly. Alternatively, keep branchUrl as-is if the field semantics are intentionally broader.

src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (1)

106-108: Build branchUrl only for branch references; use blob path for all types.

Currently branchUrl is built for all reference types. However, based on maintainer feedback, GitHub's blob path works for commits, branches, and tags. Consider renaming to reflect this, or verify the URL is appropriate for the given type.

For example:

-        $branchUrl = "https://github.com/$owner/$repository/blob/$reference";
-
+        $referenceUrl = "https://github.com/$owner/$repository/blob/$reference";
         $repositoryUrl = "https://github.com/$owner/$repository";

Then update the deployment payload field name accordingly. Alternatively, keep branchUrl as-is if the field semantics are intentionally broader.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5963b2b and d411b74.

📒 Files selected for processing (2)
  • src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (5 hunks)
  • src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (5 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: atharvadeosthale
Repo: appwrite/appwrite PR: 10486
File: src/Appwrite/Utopia/Request/Filters/V21.php:25-33
Timestamp: 2025-09-18T07:42:08.734Z
Learning: In Appwrite's V21 request filter for backward compatibility, clients will never send both old (`version`) and new (`type`/`reference`) parameters simultaneously - they use either the old 1.8.0 format or the new 1.8.1+ format, not a mix of both.
📚 Learning: 2025-09-18T07:42:08.734Z
Learnt from: atharvadeosthale
Repo: appwrite/appwrite PR: 10486
File: src/Appwrite/Utopia/Request/Filters/V21.php:25-33
Timestamp: 2025-09-18T07:42:08.734Z
Learning: In Appwrite's V21 request filter for backward compatibility, clients will never send both old (`version`) and new (`type`/`reference`) parameters simultaneously - they use either the old 1.8.0 format or the new 1.8.1+ format, not a mix of both.

Applied to files:

  • src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php
📚 Learning: 2025-05-12T06:05:27.133Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 9743
File: src/Appwrite/Utopia/Request.php:33-36
Timestamp: 2025-05-12T06:05:27.133Z
Learning: In Appwrite's architecture, the Request class should only filter parameters when filters are explicitly registered. If no filters are present, all parameters should be passed through, and the route action is responsible for validating which parameters are present/valid.

Applied to files:

  • src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php
📚 Learning: 2025-05-12T06:07:51.470Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 9743
File: src/Appwrite/Utopia/Request.php:0-0
Timestamp: 2025-05-12T06:07:51.470Z
Learning: In Appwrite's request handling architecture, the Request::getParams() method selects which SDK method to use based on parameter matching, but does not validate required parameters. The action execution flow handles parameter validation separately. This separation of concerns allows for more flexible handling of multi-method routes.

Applied to files:

  • src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php
🧬 Code graph analysis (2)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
  • param (254-355)
src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
  • param (254-355)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Setup & Build SDK
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (2)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php (1)

115-116: Template payload correctly uses referenceType and referenceValue.

The template document now stores the new reference model instead of the legacy version field.

src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php (1)

114-115: Template payload correctly uses referenceType and referenceValue.

The template document now stores the new reference model instead of the legacy version field.

@Meldiron Meldiron merged commit 5e4c74d into 1.8.x Nov 13, 2025
73 of 75 checks passed
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.

4 participants