Skip to content

0.9.x#51

Open
loks0n wants to merge 37 commits intomainfrom
0.9.x
Open

0.9.x#51
loks0n wants to merge 37 commits intomainfrom
0.9.x

Conversation

@loks0n
Copy link

@loks0n loks0n commented Mar 13, 2026

Summary by CodeRabbit

  • New Features

    • Enhanced parameter metadata: models, examples, deprecation markers and validation skip options to improve API documentation.
  • Chores

    • Upgraded PHP baseline and updated dependencies; improved container/build config and CI workflows.
    • Added code formatting config and updated ignore rules.
    • Added automated static analysis and test workflows.
  • Tests

    • Expanded unit and integration test coverage for parameter handling and platform behavior.
  • Documentation

    • Minimum PHP requirement updated in README.

TorstenDittmann and others added 30 commits October 22, 2024 12:27
Fix: worker name matching, case and negative check
chore: update utopia-php/queue to 0.8.0
…rading utopia-php/queue to ^0.12.0 and adding appwrite-labs/php-amqplib. Also updated several other packages to their latest versions.
@coderabbitai
Copy link

coderabbitai bot commented Mar 13, 2026

Walkthrough

Adds CI workflows (CodeQL and Tests), updates Docker base image and PHP version, modifies composer dependencies and adds a phpstan "check" script and pint.json, updates docker-compose and .gitignore. Introduces extended param metadata and docblocks across Platform classes (Action, Module, Platform, Scope/HTTP, Service), changes some method signatures/return types (getEnv, HTTP getters, test actions), replaces App-based startup with an Http server in tests, and adds extensive unit tests for Action param/model behavior plus multiple test updates and small client/test tweaks.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title '0.9.x' is a branch name, not a meaningful description of the pull request's purpose or changes. Replace the title with a concise, descriptive summary of the main changes, such as 'Upgrade to PHP 8.4 and modernize platform architecture' or 'Update dependencies and add type safety improvements'.
Docstring Coverage ⚠️ Warning Docstring coverage is 58.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 0.9.x
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link

@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: 8

Caution

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

⚠️ Outside diff range comments (1)
src/Platform/Scope/HTTP.php (1)

54-62: ⚠️ Potential issue | 🟡 Minor

Docblock return type doesn't match method signature.

The docblock states @return string but the method signature is ?string. This inconsistency can cause issues with static analysis tools.

🔧 Proposed fix
     /**
      * Get the value of httpAliasPath
      *
-     * `@return` string
+     * `@return` string|null
      */
     public function getHttpAliasPath(): ?string
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Platform/Scope/HTTP.php` around lines 54 - 62, Update the docblock for
the getHttpAliasPath method to match its nullable return type; change the
`@return` annotation in the getHttpAliasPath() docblock from "string" to
"string|null" (or "?string") so it aligns with the method signature public
function getHttpAliasPath(): ?string and static analyzers; leave the rest of the
docblock unchanged.
🧹 Nitpick comments (6)
tests/e2e/Client.php (2)

48-50: Narrow the PHPDoc return type to match the actual contract.

call() currently returns an array payload (or throws), so array<string, mixed>|string on Line 50 is misleading and weakens static analysis.

Proposed docblock tightening
-     * `@param`  array<string, mixed>  $headers
-     * `@param`  array<string, mixed>  $params
-     * `@return` array<string, mixed>|string
+     * `@param`  array<string, mixed>  $headers
+     * `@param`  array<string, mixed>  $params
+     * `@return` array{headers: array<string, mixed>, body: string}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/Client.php` around lines 48 - 50, The PHPDoc for the Client::call()
method incorrectly declares the return as array<string,mixed>|string even though
the implementation always returns an array payload (or throws); update the
docblock on the call() method to tighten the return type to array<string,mixed>
only, and adjust any related `@return` annotations and inline docblocks
referencing call() to match this contract to improve static analysis.

68-68: Normalize headers to valid cURL header lines before setting CURLOPT_HTTPHEADER.

Using array_values($headers) on Line 68 is fragile for associative/header-map input and mixed values. Convert to explicit "Name: value" lines (or strictly require list<string>).

Proposed normalization
-        curl_setopt($ch, CURLOPT_HTTPHEADER, array_values($headers));
+        $normalizedHeaders = [];
+        foreach ($headers as $name => $value) {
+            if (\is_int($name)) {
+                $normalizedHeaders[] = (string) $value;
+            } else {
+                $normalizedHeaders[] = $name.': '.(string) $value;
+            }
+        }
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $normalizedHeaders);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/Client.php` at line 68, The code currently passes
array_values($headers) into curl_setopt for CURLOPT_HTTPHEADER which loses
header names when $headers is an associative map; replace that with a normalized
list of header lines: iterate the $headers variable (handle both associative
name=>value and numeric lists), produce strings "Name: value" for each
associative entry, for values that are arrays either join with ", " or emit
multiple header lines for the same name, and for already well-formed string
entries keep them as-is; assign that to a $normalizedHeaders array and pass
$normalizedHeaders to curl_setopt($ch, CURLOPT_HTTPHEADER, $normalizedHeaders)
instead of array_values($headers).
.github/workflows/tests.yml (1)

17-21: Consider adding a healthcheck instead of fixed sleep.

The sleep 10 is a race condition waiting to happen. If containers take longer to start, tests will fail intermittently.

♻️ Proposed improvement using healthcheck
     - name: Run Tests
       run: |
         docker compose up -d
-        sleep 10
+        # Wait for container to be healthy (up to 60s)
+        timeout 60 bash -c 'until docker compose exec -T web php -v > /dev/null 2>&1; do sleep 2; done'
         docker compose exec -T web vendor/bin/phpunit --configuration phpunit.xml
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/tests.yml around lines 17 - 21, The workflow's Run Tests
step uses a brittle fixed sleep; add a HEALTHCHECK for the web service in your
docker-compose.yml and replace the "sleep 10" in the Run Tests job with a loop
that polls the web container's health status (e.g., via docker inspect or docker
compose ps) and only runs "docker compose exec -T web vendor/bin/phpunit
--configuration phpunit.xml" once the container reports "healthy"; reference the
Run Tests step and the web service/healthcheck and implement a small retry/wait
loop to avoid the race.
tests/e2e/HTTPServicesTest.php (2)

7-7: Class name doesn't match filename.

The class is named ResponseTest but the file is HTTPServicesTest.php. Consider renaming the class to HTTPServicesTest for consistency with PSR-4 autoloading conventions and easier navigation.

Suggested fix
-class ResponseTest extends TestCase
+class HTTPServicesTest extends TestCase
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/HTTPServicesTest.php` at line 7, The test class is misnamed: change
the class declaration from ResponseTest to HTTPServicesTest so the class name
matches the file name and PSR-4 expectations; update the class keyword in the
test file (the declaration that currently reads "class ResponseTest") to "class
HTTPServicesTest" and run the tests to ensure autoloading works.

14-16: Empty tearDown method.

The tearDown method is now empty. If client cleanup is no longer needed, consider removing the method entirely unless it's intentionally left as a placeholder.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/HTTPServicesTest.php` around lines 14 - 16, The tearDown method in
the HTTPServicesTest class is empty; either remove the empty public function
tearDown(): void declaration entirely if no cleanup is required, or restore
appropriate cleanup by calling parent::tearDown() and/or re-adding client
cleanup logic inside the tearDown() method (keep the method name tearDown and
signature as-is if you choose to implement cleanup).
src/Platform/Platform.php (1)

120-120: Inconsistent global namespace prefix usage.

Line 120 uses \substr and \stripos with the global namespace prefix, but lines 179 and 236 use substr and stripos without the prefix. Consider making this consistent across all three locations.

Apply consistent style

Either remove the backslash on line 120:

-                            $key = \substr($key, \stripos($key, ':') + 1);
+                            $key = substr($key, stripos($key, ':') + 1);

Or add the backslash on lines 179 and 236:

-                            $key = substr($key, stripos($key, ':') + 1);
+                            $key = \substr($key, \stripos($key, ':') + 1);

Also applies to: 179-179, 236-236

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Platform/Platform.php` at line 120, The codebase has inconsistent usage
of the global namespace prefix for substr/stripos; update the three occurrences
so they match. Edit the line currently reading "$key = \substr($key,
\stripos($key, ':') + 1);" and the other two occurrences that call "substr(...)"
and "stripos(...)" to use a single consistent style (either remove the
backslashes to use substr/stripos everywhere or add backslashes to use
\substr/\stripos everywhere), ensuring all three calls reference the same symbol
form.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/codeql.yml:
- Around line 10-16: Replace the fragile checkout step and unsupported
actions/checkout version: update the actions/checkout usage (the step currently
using "uses: actions/checkout@v3") to the supported major version and configure
it to fetch the PR head explicitly (use the PR head ref instead of running "git
checkout HEAD^2"); remove the separate "run: git checkout HEAD^2" step and pass
the PR head commit/ref (e.g., the pull request head SHA) into the checkout
step's ref input so the workflow checks out the correct PR head in a single,
supported actions/checkout invocation.

In @.github/workflows/tests.yml:
- Around line 10-15: Update the GitHub Actions checkout step to use
actions/checkout@v4 and remove the fragile manual "git checkout HEAD^2" step;
instead configure the checkout action to use ref: ${{
github.event.pull_request.head.sha }} so the workflow reliably checks out the PR
head commit (replace the current uses: actions/checkout@v3 and the separate git
checkout command with a single checkout step using `@v4` and the ref input).

In `@composer.json`:
- Around line 37-44: composer.json's config.platform.php is set to "8.0" which
conflicts with dependencies (e.g., utopia-php/queue 0.14.0 requires PHP >= 8.3)
and the indentation for "allow-plugins" is inconsistent; update the
"platform.php" value to at least "8.3" (or the highest minimum required by your
dependencies) so Composer resolves correctly, and realign the indentation so
"platform" and "allow-plugins" use the same spacing under "config" (match the
existing style used elsewhere) to keep formatting consistent.
- Around line 21-24: The composer.json dependency "utopia-php/cli" is pinned to
an exact version ("0.22.0") while the other Utopya packages use wildcard ranges
("utopia-php/framework", "utopia-php/queue", "utopia-php/validators"); change
the "utopia-php/cli" constraint to "0.22.*" to match the others so you receive
patch updates, update composer.lock by running composer update for that package
(or full composer update if needed), and commit the modified composer.json (and
composer.lock) to keep versioning consistent.

In `@Dockerfile`:
- Line 18: The Dockerfile and tests/docker/start are using the wrong Alpine
PHP-FPM config path: replace usages of /etc/php/$PHP_VERSION/fpm/pool.d/www.conf
with the Alpine layout /etc/php${PHP_VERSION}/php-fpm.d/www.conf; specifically
update the COPY in the Dockerfile that references PHP_VERSION and update the two
references in tests/docker/start (the lines injecting env into www.conf) to use
/etc/php${PHP_VERSION}/php-fpm.d/www.conf so the file is copied and modified at
the actual Alpine package location.

In `@tests/e2e/Client.php`:
- Around line 63-65: After calling curl_init() in tests/e2e/Client.php, add an
explicit null/false check for the returned handle ($ch) and throw a
RuntimeException (or appropriate exception) if initialization failed, then
proceed to call curl_setopt; remove the /** `@phpstan-ignore-next-line` */
suppression above the curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method) line so
static analysis sees the guard; reference the curl_init() call, the $ch
variable, and the subsequent curl_setopt(...) usages when making the change.

In `@tests/e2e/server.php`:
- Line 12: The ini_set call is using an invalid PHP ini directive; update the
ini_set invocation (the call to ini_set) to use "default_socket_timeout" instead
of "display_socket_timeout" so the socket timeout is set correctly (keep the
existing value '-1' or adjust as intended).

In `@tests/unit/ActionTest.php`:
- Around line 637-648: The test currently retrieves $options via
$action->getOptions() but never uses it; either remove the unused $options line
or add assertions to validate that the options were overwritten consistently
with the second definition. If you choose to add assertions, reference
$action->getOptions() and assert that the 'overwriteTest' entry in the options
matches the expected updated values (the same fields you assert for $params —
e.g.,
default/description/optional/injections/skipValidation/deprecated/example/model
or whatever option keys your implementation uses) so the test no longer leaves
$options unused.

---

Outside diff comments:
In `@src/Platform/Scope/HTTP.php`:
- Around line 54-62: Update the docblock for the getHttpAliasPath method to
match its nullable return type; change the `@return` annotation in the
getHttpAliasPath() docblock from "string" to "string|null" (or "?string") so it
aligns with the method signature public function getHttpAliasPath(): ?string and
static analyzers; leave the rest of the docblock unchanged.

---

Nitpick comments:
In @.github/workflows/tests.yml:
- Around line 17-21: The workflow's Run Tests step uses a brittle fixed sleep;
add a HEALTHCHECK for the web service in your docker-compose.yml and replace the
"sleep 10" in the Run Tests job with a loop that polls the web container's
health status (e.g., via docker inspect or docker compose ps) and only runs
"docker compose exec -T web vendor/bin/phpunit --configuration phpunit.xml" once
the container reports "healthy"; reference the Run Tests step and the web
service/healthcheck and implement a small retry/wait loop to avoid the race.

In `@src/Platform/Platform.php`:
- Line 120: The codebase has inconsistent usage of the global namespace prefix
for substr/stripos; update the three occurrences so they match. Edit the line
currently reading "$key = \substr($key, \stripos($key, ':') + 1);" and the other
two occurrences that call "substr(...)" and "stripos(...)" to use a single
consistent style (either remove the backslashes to use substr/stripos everywhere
or add backslashes to use \substr/\stripos everywhere), ensuring all three calls
reference the same symbol form.

In `@tests/e2e/Client.php`:
- Around line 48-50: The PHPDoc for the Client::call() method incorrectly
declares the return as array<string,mixed>|string even though the implementation
always returns an array payload (or throws); update the docblock on the call()
method to tighten the return type to array<string,mixed> only, and adjust any
related `@return` annotations and inline docblocks referencing call() to match
this contract to improve static analysis.
- Line 68: The code currently passes array_values($headers) into curl_setopt for
CURLOPT_HTTPHEADER which loses header names when $headers is an associative map;
replace that with a normalized list of header lines: iterate the $headers
variable (handle both associative name=>value and numeric lists), produce
strings "Name: value" for each associative entry, for values that are arrays
either join with ", " or emit multiple header lines for the same name, and for
already well-formed string entries keep them as-is; assign that to a
$normalizedHeaders array and pass $normalizedHeaders to curl_setopt($ch,
CURLOPT_HTTPHEADER, $normalizedHeaders) instead of array_values($headers).

In `@tests/e2e/HTTPServicesTest.php`:
- Line 7: The test class is misnamed: change the class declaration from
ResponseTest to HTTPServicesTest so the class name matches the file name and
PSR-4 expectations; update the class keyword in the test file (the declaration
that currently reads "class ResponseTest") to "class HTTPServicesTest" and run
the tests to ensure autoloading works.
- Around line 14-16: The tearDown method in the HTTPServicesTest class is empty;
either remove the empty public function tearDown(): void declaration entirely if
no cleanup is required, or restore appropriate cleanup by calling
parent::tearDown() and/or re-adding client cleanup logic inside the tearDown()
method (keep the method name tearDown and signature as-is if you choose to
implement cleanup).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6699bd2e-e521-4915-adeb-543f2efc2de2

📥 Commits

Reviewing files that changed from the base of the PR and between d5c8535 and 030b710.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (24)
  • .github/workflows/codeql.yml
  • .github/workflows/tests.yml
  • .gitignore
  • Dockerfile
  • composer.json
  • docker-compose.yml
  • pint.json
  • src/Platform/Action.php
  • src/Platform/Module.php
  • src/Platform/Platform.php
  • src/Platform/Scope/HTTP.php
  • src/Platform/Service.php
  • tests/Platform/TestActionCLI.php
  • tests/Platform/TestActionChunked.php
  • tests/Platform/TestActionInit.php
  • tests/Platform/TestActionRedirect.php
  • tests/Platform/TestActionRoot.php
  • tests/Platform/TestActionWithModel.php
  • tests/e2e/CLITest.php
  • tests/e2e/Client.php
  • tests/e2e/HTTPServicesTest.php
  • tests/e2e/server.php
  • tests/unit/ActionTest.php
  • tests/unit/GetEnvTest.php

Comment on lines +10 to +16
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 2

- run: git checkout HEAD^2

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

What is the currently supported major version for actions/checkout, and is @V3 deprecated for GitHub-hosted runners?

💡 Result:

  • Currently supported major version of actions/checkout: v6 (the repo’s README examples use actions/checkout@v6, and the latest release shown is v6.0.2). [1]
  • Is actions/checkout@v3 deprecated for GitHub-hosted runners? @v3 is a Node16-based action (runs.using: node16). [2] GitHub removed Node16 from the Actions runner on November 12, 2024, and “customers will no longer be able to use Node16 Actions” after that date—so actions/checkout@v3 is effectively unsupported on GitHub-hosted runners. [3]

Sources: [1] [2] [3]


🏁 Script executed:

cat -n .github/workflows/codeql.yml | head -40

Repository: utopia-php/platform

Length of output: 620


Update actions/checkout to supported version and use explicit PR head ref instead of HEAD^2.

actions/checkout@v3 uses Node16 runtime, which was removed from GitHub-hosted runners in November 2024 and is no longer supported. The git checkout HEAD^2 approach is fragile—use the PR head commit reference explicitly instead.

Proposed fix
-    - name: Checkout repository
-      uses: actions/checkout@v3
+    - name: Checkout PR head
+      uses: actions/checkout@v6
       with:
-        fetch-depth: 2
-
-    - run: git checkout HEAD^2
+        ref: ${{ github.event.pull_request.head.sha }}
+        fetch-depth: 0
🧰 Tools
🪛 actionlint (1.7.11)

[error] 11-11: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/codeql.yml around lines 10 - 16, Replace the fragile
checkout step and unsupported actions/checkout version: update the
actions/checkout usage (the step currently using "uses: actions/checkout@v3") to
the supported major version and configure it to fetch the PR head explicitly
(use the PR head ref instead of running "git checkout HEAD^2"); remove the
separate "run: git checkout HEAD^2" step and pass the PR head commit/ref (e.g.,
the pull request head SHA) into the checkout step's ref input so the workflow
checks out the correct PR head in a single, supported actions/checkout
invocation.

Comment on lines +10 to +15
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 2

- run: git checkout HEAD^2
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Update checkout action and fix unreliable HEAD^2 checkout.

  1. Outdated action version: actions/checkout@v3 is deprecated. Update to @v4.

  2. Fragile HEAD^2 checkout: git checkout HEAD^2 assumes a merge commit exists, which isn't guaranteed for all PR events (e.g., synchronize events on force-pushed branches). This will cause the workflow to fail with "fatal: ambiguous argument 'HEAD^2'".

The checkout action with ref: ${{ github.event.pull_request.head.sha }} handles this properly.

🛠️ Proposed fix
     - name: Checkout repository
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
       with:
-        fetch-depth: 2
-
-    - run: git checkout HEAD^2
+        ref: ${{ github.event.pull_request.head.sha }}
🧰 Tools
🪛 actionlint (1.7.11)

[error] 11-11: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/tests.yml around lines 10 - 15, Update the GitHub Actions
checkout step to use actions/checkout@v4 and remove the fragile manual "git
checkout HEAD^2" step; instead configure the checkout action to use ref: ${{
github.event.pull_request.head.sha }} so the workflow reliably checks out the PR
head commit (replace the current uses: actions/checkout@v3 and the separate git
checkout command with a single checkout step using `@v4` and the ref input).

composer.json Outdated
Comment on lines +21 to +24
"utopia-php/cli": "0.22.0",
"utopia-php/framework": "0.34.*",
"utopia-php/queue": "0.14.*",
"utopia-php/validators": "0.2.*"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify API compatibility for utopia-php/queue by checking if used methods still exist
echo "Checking utopia-php/queue changelog or release notes..."
curl -s "https://api.github.com/repos/utopia-php/queue/releases" | jq '.[0:3] | .[] | {tag_name, name, body}' 2>/dev/null || echo "Could not fetch releases"

Repository: utopia-php/platform

Length of output: 143


🏁 Script executed:

cat composer.json | grep -A 20 '"require"'

Repository: utopia-php/platform

Length of output: 773


🏁 Script executed:

rg -l "queue" --type php | head -5

Repository: utopia-php/platform

Length of output: 88


🏁 Script executed:

rg "Server|initWorker" --type php -B 2 -A 5

Repository: utopia-php/platform

Length of output: 3848


🏁 Script executed:

rg "breaking|deprecated|incompatible" --type php -i | head -20

Repository: utopia-php/platform

Length of output: 1546


🏁 Script executed:

git log --oneline -20 -- composer.json

Repository: utopia-php/platform

Length of output: 129


🏁 Script executed:

rg "queue.*Server|0\.14|0\.7" --type php -i

Repository: utopia-php/platform

Length of output: 113


🏁 Script executed:

git show HEAD~1:composer.json | grep -A 10 '"require"' | head -20

Repository: utopia-php/platform

Length of output: 99


🏁 Script executed:

git diff HEAD~1 composer.json

Repository: utopia-php/platform

Length of output: 251


🏁 Script executed:

git log --oneline composer.json 2>/dev/null | head -20

Repository: utopia-php/platform

Length of output: 129


🏁 Script executed:

git show HEAD:composer.json | grep -A 10 '"require"'

Repository: utopia-php/platform

Length of output: 373


Use consistent version constraints across dependencies.

utopia-php/cli uses an exact version (0.22.0) while other packages use ranges (0.34.*, 0.14.*, 0.2.*). For consistency and to receive patch updates, consider using 0.22.* instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@composer.json` around lines 21 - 24, The composer.json dependency
"utopia-php/cli" is pinned to an exact version ("0.22.0") while the other Utopya
packages use wildcard ranges ("utopia-php/framework", "utopia-php/queue",
"utopia-php/validators"); change the "utopia-php/cli" constraint to "0.22.*" to
match the others so you receive patch updates, update composer.lock by running
composer update for that package (or full composer update if needed), and commit
the modified composer.json (and composer.lock) to keep versioning consistent.

Comment on lines +37 to +44
"config": {
"platform": {
"php": "8.0"
},
"allow-plugins": {
"php-http/discovery": false,
"tbachert/spi": false
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check PHP version requirements for utopia-php/queue 0.14.*
curl -s https://packagist.org/packages/utopia-php/queue.json | jq '.package.versions["0.14.0"].require.php // .package.versions["0.14.1"].require.php // "not found"'

Repository: utopia-php/platform

Length of output: 70


Align platform.php with actual dependency requirements.

The platform.php is set to "8.0", but utopia-php/queue 0.14.0 requires PHP >= 8.3. Composer will resolve dependencies assuming PHP 8.0 compatibility, potentially masking incompatibilities. Update platform.php to match the minimum PHP version required by dependencies.

Additionally, fix indentation inconsistency: platform uses 2 spaces while allow-plugins uses 4 spaces relative to config.

Proposed fix
     "config": {
+      "allow-plugins": {
+          "php-http/discovery": false,
+          "tbachert/spi": false
+      },
       "platform": {
-        "php": "8.0"
+          "php": "8.3"
       },
-      "allow-plugins": {
-          "php-http/discovery": false,
-          "tbachert/spi": false
-      }
     }
📝 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
"config": {
"platform": {
"php": "8.0"
},
"allow-plugins": {
"php-http/discovery": false,
"tbachert/spi": false
}
"config": {
"allow-plugins": {
"php-http/discovery": false,
"tbachert/spi": false
},
"platform": {
"php": "8.3"
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@composer.json` around lines 37 - 44, composer.json's config.platform.php is
set to "8.0" which conflicts with dependencies (e.g., utopia-php/queue 0.14.0
requires PHP >= 8.3) and the indentation for "allow-plugins" is inconsistent;
update the "platform.php" value to at least "8.3" (or the highest minimum
required by your dependencies) so Composer resolves correctly, and realign the
indentation so "platform" and "allow-plugins" use the same spacing under
"config" (match the existing style used elsewhere) to keep formatting
consistent.


ENV DEBIAN_FRONTEND=noninteractive \
PHP_VERSION=8
PHP_VERSION=84
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify real php-fpm binary and pool config path for Alpine PHP 8.4
docker run --rm php:8.4-cli-alpine3.21 sh -lc '
  apk add --no-cache php84 php84-fpm >/dev/null
  echo "php-fpm binaries:"
  command -v php-fpm84 || true
  command -v php-fpm || true
  echo "www.conf candidates:"
  find /etc -maxdepth 4 -type f -name "www.conf" | sort
'

Repository: utopia-php/platform

Length of output: 109


🏁 Script executed:

# Find and examine the Dockerfile
git ls-files | grep -i dockerfile

Repository: utopia-php/platform

Length of output: 73


🏁 Script executed:

# Read the Dockerfile to understand PHP_VERSION usage
cat -n Dockerfile

Repository: utopia-php/platform

Length of output: 1670


🏁 Script executed:

# Check the tests/docker directory structure
fd . tests/docker/ -type f

Repository: utopia-php/platform

Length of output: 233


🏁 Script executed:

# List files in tests/docker directory
ls -la tests/docker/

Repository: utopia-php/platform

Length of output: 419


🏁 Script executed:

# Read the tests/docker/start script
cat -n tests/docker/start

Repository: utopia-php/platform

Length of output: 985


🏁 Script executed:

# Read the tests/docker/supervisord.conf
cat -n tests/docker/supervisord.conf

Repository: utopia-php/platform

Length of output: 1986


🌐 Web query:

Alpine Linux php84 fpm package paths /etc/php

💡 Result:

On Alpine, PHP 8.4 is versioned under /etc/php84/ (not /etc/php/):

  • Main PHP ini: /etc/php84/php.ini (from php84-common) [1]
  • PHP-FPM main config: /etc/php84/php-fpm.conf (from php84-fpm) [2]
  • Default FPM pool config: /etc/php84/php-fpm.d/www.conf (from php84-fpm) [2]
  • FPM service script: /etc/init.d/php-fpm84 (from php84-fpm) [2]
  • Logrotate: /etc/logrotate.d/php-fpm84 (from php84-fpm) [2]
  • Extension drop-in INIs: typically /etc/php84/conf.d/*.ini (installed by individual php84-… extension packages; add your own *.ini there as well).

Sources:
[1] https://pkgs.alpinelinux.org/contents?arch=armhf&branch=edge&name=php84-common&repo=community
[2] https://pkgs.alpinelinux.org/contents?arch=x86_64&branch=edge&name=php84-fpm&repo=community


🌐 Web query:

Alpine Linux php-fpm8.4 binary location package structure

💡 Result:

On Alpine Linux, PHP-FPM 8.4 is provided by the php84-fpm package, and it installs:

  • Binary: /usr/sbin/php-fpm84 (this is the executable you run) [1]
  • Main config: /etc/php84/php-fpm.conf [1]
  • Pool config dir / default pool: /etc/php84/php-fpm.d/ (default pool: www.conf) [1]
  • OpenRC service script: /etc/init.d/php-fpm84 [1]
  • Logrotate config: /etc/logrotate.d/php-fpm84 [1]
  • FPM status page file: /usr/share/php84/fpm/status.html [1]

To inspect the exact file list on your system, use:

apk info -L php84-fpm

Sources: Alpine package contents listing for php84-fpm [1].


Fix Alpine PHP 8.4 FPM configuration paths.

Line 29 copies www.conf to /etc/php/$PHP_VERSION/fpm/pool.d/www.conf, which expands to /etc/php/84/fpm/pool.d/www.conf. However, Alpine Linux PHP 8.4 packages install FPM config to /etc/php84/php-fpm.d/www.conf. The current path does not match the actual package layout, causing the COPY command to place the file in a non-existent directory or wrong location. Additionally, tests/docker/start references the same incorrect path when attempting to inject environment variables at runtime, which will silently fail.

Update line 29 to use the correct Alpine path:

-COPY ./tests/docker/www.conf /etc/php/$PHP_VERSION/fpm/pool.d/www.conf
+COPY ./tests/docker/www.conf /etc/php${PHP_VERSION}/php-fpm.d/www.conf

Also update tests/docker/start lines 15 and 17 to reference /etc/php${PHP_VERSION}/php-fpm.d/www.conf instead of /etc/php/$PHP_VERSION/fpm/pool.d/www.conf.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` at line 18, The Dockerfile and tests/docker/start are using the
wrong Alpine PHP-FPM config path: replace usages of
/etc/php/$PHP_VERSION/fpm/pool.d/www.conf with the Alpine layout
/etc/php${PHP_VERSION}/php-fpm.d/www.conf; specifically update the COPY in the
Dockerfile that references PHP_VERSION and update the two references in
tests/docker/start (the lines injecting env into www.conf) to use
/etc/php${PHP_VERSION}/php-fpm.d/www.conf so the file is copied and modified at
the actual Alpine package location.

Comment on lines +63 to +65
/** @phpstan-ignore-next-line */
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and read the relevant file and lines
find . -name "Client.php" -path "*/tests/e2e/*" | head -5

Repository: utopia-php/platform

Length of output: 85


🏁 Script executed:

# Read the file around the specified lines to see the full context
cat -n tests/e2e/Client.php | sed -n '50,75p'

Repository: utopia-php/platform

Length of output: 1505


🏁 Script executed:

# Read more of the method to see the complete flow
cat -n tests/e2e/Client.php | sed -n '54,120p'

Repository: utopia-php/platform

Length of output: 2420


Add explicit curl_init() failure handling; remove the static analysis suppression.

curl_init() can return false on failure. Currently, the code uses $ch in curl_setopt() calls without checking, and the @phpstan-ignore annotation suppresses the legitimate warning. Add an explicit guard after initialization to throw an exception if curl_init() fails, then remove the suppression.

Proposed fix
         $ch = curl_init($this->baseUrl.$path.(($method == self::METHOD_GET && ! empty($params)) ? '?'.http_build_query($params) : ''));
+        if ($ch === false) {
+            throw new Exception('Failed to initialize cURL handle');
+        }
         $responseHeaders = [];
         $responseStatus = -1;
         $responseType = '';
         $responseBody = '';
 
-        /** `@phpstan-ignore-next-line` */
         curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/Client.php` around lines 63 - 65, After calling curl_init() in
tests/e2e/Client.php, add an explicit null/false check for the returned handle
($ch) and throw a RuntimeException (or appropriate exception) if initialization
failed, then proceed to call curl_setopt; remove the /**
`@phpstan-ignore-next-line` */ suppression above the curl_setopt($ch,
CURLOPT_CUSTOMREQUEST, $method) line so static analysis sees the guard;
reference the curl_init() call, the $ch variable, and the subsequent
curl_setopt(...) usages when making the change.

ini_set('display_socket_timeout', -1);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
ini_set('display_socket_timeout', '-1');
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Is display_socket_timeout a valid PHP ini directive, and what directive controls socket timeout globally?

💡 Result:

display_socket_timeout is not a valid PHP php.ini directive (it does not exist in PHP’s documented INI settings).

The global directive that controls the default timeout for socket-based streams is:

  • default_socket_timeout (seconds) (php.net)

Citations:


Replace invalid ini directive display_socket_timeout with default_socket_timeout.

display_socket_timeout is not a valid PHP ini directive. Use default_socket_timeout instead to control the default socket timeout globally.

Proposed fix
-ini_set('display_socket_timeout', '-1');
+ini_set('default_socket_timeout', '-1');
📝 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
ini_set('display_socket_timeout', '-1');
ini_set('default_socket_timeout', '-1');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/server.php` at line 12, The ini_set call is using an invalid PHP
ini directive; update the ini_set invocation (the call to ini_set) to use
"default_socket_timeout" instead of "display_socket_timeout" so the socket
timeout is set correctly (keep the existing value '-1' or adjust as intended).

Comment on lines +637 to +648
$params = $action->getParams();
$options = $action->getOptions();

// Should have the second definition's values
$this->assertEquals('second', $params['overwriteTest']['default']);
$this->assertEquals('Second definition', $params['overwriteTest']['description']);
$this->assertTrue($params['overwriteTest']['optional']);
$this->assertEquals(['response'], $params['overwriteTest']['injections']);
$this->assertTrue($params['overwriteTest']['skipValidation']);
$this->assertTrue($params['overwriteTest']['deprecated']);
$this->assertEquals('second_example', $params['overwriteTest']['example']);
$this->assertEquals('secondModel', $params['overwriteTest']['model']);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unused $options variable.

The $options variable is retrieved on line 638 but never used in the assertions. Either remove it or add assertions to verify the options are also updated when overwriting a param.

Option 1: Remove unused variable
         $params = $action->getParams();
-        $options = $action->getOptions();

         // Should have the second definition's values
Option 2: Add assertions for options consistency
         $this->assertEquals('second_example', $params['overwriteTest']['example']);
         $this->assertEquals('secondModel', $params['overwriteTest']['model']);
+
+        // Verify options are also updated
+        $this->assertEquals('secondModel', $options['param:overwriteTest']['model']);
+        $this->assertEquals('second_example', $options['param:overwriteTest']['example']);
📝 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
$params = $action->getParams();
$options = $action->getOptions();
// Should have the second definition's values
$this->assertEquals('second', $params['overwriteTest']['default']);
$this->assertEquals('Second definition', $params['overwriteTest']['description']);
$this->assertTrue($params['overwriteTest']['optional']);
$this->assertEquals(['response'], $params['overwriteTest']['injections']);
$this->assertTrue($params['overwriteTest']['skipValidation']);
$this->assertTrue($params['overwriteTest']['deprecated']);
$this->assertEquals('second_example', $params['overwriteTest']['example']);
$this->assertEquals('secondModel', $params['overwriteTest']['model']);
$params = $action->getParams();
// Should have the second definition's values
$this->assertEquals('second', $params['overwriteTest']['default']);
$this->assertEquals('Second definition', $params['overwriteTest']['description']);
$this->assertTrue($params['overwriteTest']['optional']);
$this->assertEquals(['response'], $params['overwriteTest']['injections']);
$this->assertTrue($params['overwriteTest']['skipValidation']);
$this->assertTrue($params['overwriteTest']['deprecated']);
$this->assertEquals('second_example', $params['overwriteTest']['example']);
$this->assertEquals('secondModel', $params['overwriteTest']['model']);
🧰 Tools
🪛 PHPMD (2.15.0)

[warning] 638-638: Avoid unused local variables such as '$options'. (undefined)

(UnusedLocalVariable)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/ActionTest.php` around lines 637 - 648, The test currently
retrieves $options via $action->getOptions() but never uses it; either remove
the unused $options line or add assertions to validate that the options were
overwritten consistently with the second definition. If you choose to add
assertions, reference $action->getOptions() and assert that the 'overwriteTest'
entry in the options matches the expected updated values (the same fields you
assert for $params — e.g.,
default/description/optional/injections/skipValidation/deprecated/example/model
or whatever option keys your implementation uses) so the test no longer leaves
$options unused.

Copy link

@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

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

26-35: PHPStan 2.x upgrade doesn't require config migration for this project.

Since this project has no custom PHPStan configuration file, the breaking changes in PHPStan 2.0 (removed config options like checkMissingIterableValueType and excludes_analyse) won't impact the upgrade. The PHP 8.2 requirement is compatible with PHPStan 2.0's minimum of PHP 7.4. However, ensure the codebase passes the analysis at level 8 before merging, as stricter type-checking behavior may reveal new issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@composer.json` around lines 26 - 35, composer.json already bumps
phpstan/phpstan to "2.*" so no config migration is required; run the existing
"check" script (the composer "check" script referencing vendor/bin/phpstan
analyse --level 8) against the codebase and fix any new type errors PHPStan 2.x
reports at level 8 (adjust code, add phpdoc or stricter types in the offending
functions/classes), then re-run the "check" until it passes before merging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@composer.json`:
- Around line 37-45: Update the composer.json config->platform PHP version from
"8.2" to "8.3" to satisfy utopia-php/queue 0.16.*; edit the "platform": { "php":
"8.2" } entry to "8.3" in composer.json (config.platform.php) and then run
composer update / validate to ensure dependency resolution succeeds.

---

Nitpick comments:
In `@composer.json`:
- Around line 26-35: composer.json already bumps phpstan/phpstan to "2.*" so no
config migration is required; run the existing "check" script (the composer
"check" script referencing vendor/bin/phpstan analyse --level 8) against the
codebase and fix any new type errors PHPStan 2.x reports at level 8 (adjust
code, add phpdoc or stricter types in the offending functions/classes), then
re-run the "check" until it passes before merging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 850e03f5-7627-44e2-9794-9807a28247df

📥 Commits

Reviewing files that changed from the base of the PR and between 030b710 and 490e9aa.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • README.md
  • composer.json
  • tests/e2e/server.php

Comment on lines +37 to 45
"config": {
"platform": {
"php": "8.2"
},
"allow-plugins": {
"php-http/discovery": false,
"tbachert/spi": false
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check PHP version requirements for utopia-php/queue 0.16.*
curl -s "https://packagist.org/packages/utopia-php/queue.json" | jq '.package.versions | to_entries | map(select(.key | startswith("0.16"))) | .[0].value.require.php // "not found"'

Repository: utopia-php/platform

Length of output: 70


Update platform PHP version to 8.3 or higher.

The platform.php is set to "8.2", but utopia-php/queue 0.16.* requires PHP >=8.3. Update the platform configuration to match the dependency requirement:

"platform": {
  "php": "8.3"
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@composer.json` around lines 37 - 45, Update the composer.json
config->platform PHP version from "8.2" to "8.3" to satisfy utopia-php/queue
0.16.*; edit the "platform": { "php": "8.2" } entry to "8.3" in composer.json
(config.platform.php) and then run composer update / validate to ensure
dependency resolution succeeds.

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.

8 participants