Skip to content

Feat: Project labels#11056

Merged
Meldiron merged 3 commits into1.8.xfrom
feat-project-labels
Jan 5, 2026
Merged

Feat: Project labels#11056
Meldiron merged 3 commits into1.8.xfrom
feat-project-labels

Conversation

@Meldiron
Copy link
Copy Markdown
Contributor

What does this PR do?

Adds labels to projects for ease filtering

Test Plan

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

Related PRs and Issues

x

Checklist

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

@Meldiron Meldiron requested a review from Copilot December 31, 2025 14:46
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Dec 31, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds a new project "labels" attribute (VAR_STRING, size 128, array, default []) to the projects collection and initializes it on project creation. Introduces an HTTP action class to update project labels via PUT /v1/projects/:projectId/labels with validation and persistence. Registers the new action in the Projects HTTP service. Updates query validation to allow filtering by "labels". Extends the Project response model to include the "labels" field. Adds end-to-end tests covering label creation, updates, and label-based querying across projects.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feat: Project labels' directly and clearly describes the main feature addition in the changeset, which is implementing project labels functionality.
Description check ✅ Passed The description 'Adds labels to projects for ease filtering' is directly related to the changeset, which implements project labels across multiple files including database configuration, API endpoints, and response models.
✨ Finishing touches
  • 📝 Generate docstrings

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

❤️ Share

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

@github-actions
Copy link
Copy Markdown

github-actions bot commented Dec 31, 2025

Security Scan Results for PR

Docker Image Scan Results

Package Version Vulnerability Severity
libpng 1.6.51-r0 CVE-2025-66293 HIGH
libpng-dev 1.6.51-r0 CVE-2025-66293 HIGH

Source Code Scan Results

🎉 No vulnerabilities found!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a labels feature to projects, enabling easier filtering and organization of projects within the Appwrite platform. The implementation includes database schema updates, API endpoints for managing labels, and comprehensive test coverage.

Key Changes:

  • Added a labels array field to the projects collection schema
  • Implemented a new API endpoint (PUT /v1/projects/:projectId/labels) to update project labels
  • Extended the project query validator to support filtering by labels

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
app/config/collections/platform.php Adds labels field to the projects collection schema as a string array
app/controllers/api/projects.php Initializes the labels field as an empty array during project creation
src/Appwrite/Utopia/Response/Model/Project.php Adds labels to the Project response model definition
src/Appwrite/Utopia/Database/Validator/Queries/Projects.php Adds labels to the allowed queryable attributes for projects
src/Appwrite/Platform/Modules/Projects/Services/Http.php Registers the new UpdateProjectLabels action in the HTTP service
src/Appwrite/Platform/Modules/Projects/Http/Projects/Labels/Update.php Implements the update labels endpoint with validation and business logic
tests/e2e/Services/Projects/ProjectsConsoleClientTest.php Adds comprehensive end-to-end tests for the labels functionality including filtering scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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)
app/config/collections/platform.php (1)

334-344: Consider default value and index for the labels field.

Two observations:

  1. Default value inconsistency: The default is set to null, but the controller initializes it as [] (line 207 in app/controllers/api/projects.php). Consider changing the default to [] for consistency.

  2. Missing index: The labels field is included in ALLOWED_ATTRIBUTES for queries (see src/Appwrite/Utopia/Database/Validator/Queries/Projects.php), but there's no index defined. If filtering/querying by labels is expected to be common, consider adding an index to improve performance.

🔎 Proposed fix for default value
             [
                 '$id' => ID::custom('labels'),
                 'type' => Database::VAR_STRING,
                 'format' => '',
                 'size' => 128,
                 'signed' => true,
                 'required' => false,
-                'default' => null,
+                'default' => [],
                 'array' => true,
                 'filters' => [],
             ],

Note: For the index consideration, verify whether array field indexes are supported and beneficial in your database configuration before adding one.

tests/e2e/Services/Projects/ProjectsConsoleClientTest.php (1)

5492-5589: Minor test hygiene: second project cleanup and misleading comment

  • The comment // Setup: Second project with only imagine label doesn’t match the data; project 2 gets ['vip', 'imagine'].
  • The test deletes only $projectId and the team, but leaves $projectId2 around. In this suite, extra projects may affect tests that rely on global counts / ordering.

Consider:

  • Updating the comment to reflect actual labels, and
  • Deleting $projectId2 as part of the cleanup to keep the test self-contained.
src/Appwrite/Platform/Modules/Projects/Http/Projects/Labels/Update.php (2)

24-32: Add return type to getName() for consistency with other actions

getName() currently has no return type hint. To keep this aligned with typical Action implementations and avoid potential signature mismatches with the base class/interface, it’s safer to declare : string.

Also, since getQueriesValidator() returns a Projects validator but the action doesn’t accept queries, this override is effectively unused today. That’s fine, but if the base Action doesn’t expect queries here, you could drop it to reduce noise.

If the base Action (or an interface it implements) already defines public static function getName(): string, please update this method signature accordingly:

public static function getName(): string
{
    return 'updateProjectLabels';
}

Please verify against the current Action definition in your codebase.


59-82: Label validation and normalization considerations

The labels param is well-constrained (max count via APP_LIMIT_ARRAY_LABELS_SIZE, per-label length 36, alphanumeric only). The action also de-duplicates labels via array_unique.

If you want stricter consistency over time, you might also consider:

  • Trimming whitespace from each label before validation.
  • Normalizing case (e.g., lowercasing) so VIP and vip aren’t treated as distinct.

Not strictly required for correctness, but improves long-term data hygiene and query predictability.

If you decide to normalize, confirm with product/API docs that label matching is intended to be case-insensitive before changing behavior.

📜 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 5534337 and 8d1acef.

📒 Files selected for processing (7)
  • app/config/collections/platform.php
  • app/controllers/api/projects.php
  • src/Appwrite/Platform/Modules/Projects/Http/Projects/Labels/Update.php
  • src/Appwrite/Platform/Modules/Projects/Services/Http.php
  • src/Appwrite/Utopia/Database/Validator/Queries/Projects.php
  • src/Appwrite/Utopia/Response/Model/Project.php
  • tests/e2e/Services/Projects/ProjectsConsoleClientTest.php
🧰 Additional context used
🧬 Code graph analysis (4)
src/Appwrite/Utopia/Response/Model/Project.php (1)
src/Appwrite/Utopia/Response/Model.php (1)
  • addRule (90-102)
src/Appwrite/Platform/Modules/Projects/Http/Projects/Labels/Update.php (2)
src/Appwrite/Utopia/Database/Validator/Queries/Projects.php (2)
  • Projects (5-26)
  • __construct (17-20)
src/Appwrite/Utopia/Response/Model/Project.php (1)
  • __construct (17-322)
src/Appwrite/Platform/Modules/Projects/Services/Http.php (1)
src/Appwrite/Platform/Modules/Projects/Http/Projects/Labels/Update.php (2)
  • Update (20-86)
  • getName (24-27)
tests/e2e/Services/Projects/ProjectsConsoleClientTest.php (4)
tests/e2e/Client.php (1)
  • Client (8-342)
src/Appwrite/Event/Event.php (1)
  • getProject (153-156)
tests/e2e/Scopes/ProjectCustom.php (1)
  • getProject (21-184)
tests/e2e/Scopes/Scope.php (2)
  • getProject (150-150)
  • getHeaders (145-145)
⏰ 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: Agent
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (3)
src/Appwrite/Platform/Modules/Projects/Services/Http.php (1)

10-10: LGTM!

The import and registration of the UpdateProjectLabels action follow the established patterns in this service.

Also applies to: 26-26

src/Appwrite/Utopia/Database/Validator/Queries/Projects.php (1)

9-10: LGTM!

Adding 'labels' to the allowed query attributes is correct and enables filtering projects by labels.

src/Appwrite/Utopia/Response/Model/Project.php (1)

279-285: Project model labels field looks consistent

The new labels rule (string, array, default []) matches the intended usage in the API and tests and integrates cleanly with the existing model.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Dec 31, 2025

✨ Benchmark results

  • Requests per second: 2,270
  • Requests with 200 status code: 408,593
  • P99 latency: 0.077433026

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 2,270 1,225
200 408,593 220,538
P99 0.077433026 0.164239567

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/Services/Projects/ProjectsConsoleClientTest.php (1)

5416-5442: Good coverage of label operations.

The test validates both applying initial labels and updating them. The assertions properly check array structure, count, and individual values. Note that the test assumes label order is preserved (lines 5427-5429, 5440-5441), which is appropriate if order preservation is part of the API contract.

Consider adding test cases for edge cases and failure scenarios, such as:

  • Empty labels array (might already be covered by default state)
  • Invalid label values (if any constraints exist)
  • Duplicate labels in input
  • Maximum label array size (if any limit exists)

These could help ensure robustness, though they may be covered in other test files.

📜 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 8d1acef and 1db12e7.

📒 Files selected for processing (2)
  • app/config/collections/platform.php
  • tests/e2e/Services/Projects/ProjectsConsoleClientTest.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/config/collections/platform.php
🧰 Additional context used
🧬 Code graph analysis (1)
tests/e2e/Services/Projects/ProjectsConsoleClientTest.php (4)
tests/e2e/Client.php (1)
  • Client (8-342)
src/Appwrite/Event/Event.php (1)
  • getProject (153-156)
tests/e2e/Scopes/ProjectCustom.php (1)
  • getProject (21-184)
tests/e2e/Scopes/Scope.php (1)
  • getProject (150-150)
⏰ 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 (Teams)
  • GitHub Check: E2E Service Test (Users)
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E General Test
  • GitHub Check: Unit Test
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: Benchmark
  • GitHub Check: scan
🔇 Additional comments (4)
tests/e2e/Services/Projects/ProjectsConsoleClientTest.php (4)

5388-5414: LGTM! Well-structured test setup.

The setup properly creates a team and project, and validates that the labels field is initialized as an empty array. This provides a clean starting point for the label operations testing.


5444-5490: Excellent! Status-code assertions now reference the correct variable.

All filtering queries correctly use $projects['headers']['status-code'] instead of the previous incorrect $project['headers']['status-code']. This resolves the issue flagged in past reviews where assertions were validating the wrong response.

The filtering tests properly cover:

  • Single label queries (lines 5450, 5462, 5473)
  • OR operation using Query::contains('labels', ['nonvip', 'imagine']) (line 5485)

5492-5573: Comprehensive cross-project filtering tests.

The test properly validates filtering behavior across multiple projects and distinguishes between AND and OR operations:

  • Lines 5553-5554: Multiple Query::contains() calls implement AND logic (must match all)
  • Line 5567: Single Query::contains() with array implements OR logic (match any)

The assertions correctly use $projects variable throughout, and the expected results properly validate the filtering logic.


5575-5595: Proper cleanup now includes both projects!

The cleanup correctly deletes both projectId and projectId2 before removing the team. This resolves the past review concern about the second project not being cleaned up.

The cleanup order (projects → team) is appropriate since projects belong to the team.

@Meldiron Meldiron merged commit b1373c0 into 1.8.x Jan 5, 2026
72 of 73 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.

3 participants