Skip to content

Optimize for better Windows compatibility#161

Merged
koriym merged 58 commits into
1.xfrom
cache
Jun 20, 2025
Merged

Optimize for better Windows compatibility#161
koriym merged 58 commits into
1.xfrom
cache

Conversation

@koriym
Copy link
Copy Markdown
Member

@koriym koriym commented Jan 21, 2025

Description:
Refactored the CI workflow to enhance maintainability, support multiple OS and PHP versions, adjust matrix configurations, streamline dependency management, introduce environment-based conditions, update step names, and improve Composer caching for better performance.

Summary by Sourcery

Refactor the CI workflow to improve flexibility and efficiency by broadening OS/PHP coverage, streamlining dependency management, upgrading core actions, and enhancing caching strategies.

CI:

  • Expand PHPUnit job matrix to cover Ubuntu, Windows, and macOS across PHP 8.1–8.4 with both lowest and highest dependencies
  • Upgrade checkout and cache actions to v4, set fail-fast to false, and ignore Markdown-only changes on triggers
  • Standardize Composer flags, consolidate dependency resolution steps (unset platform), and conditionally run the demo script only on Ubuntu
  • Optimize Composer caching paths and keys per OS and PHP version for faster builds
  • Rename workflow steps for clarity and consistency

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 21, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough
## Walkthrough

The continuous integration workflow was refactored to expand matrix testing across multiple operating systems and PHP versions, update action versions, improve dependency management, and modernize configuration. Job naming, environment variables, and CI steps were clarified. Redis and Memcached services setup and demo script execution were revised, with more precise triggers and improved caching.

## Changes

| File(s)                                         | Change Summary                                                                                                   |
|------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
| .github/workflows/continuous-integration.yml   | Refactored workflow: expanded matrix (OS, PHP, dependencies), updated action versions, revised env vars, improved caching, clarified steps, modernized triggers, updated Redis and Memcached service setup, and revised demo script execution. |
| .github/workflows/coding-standards.yml          | Updated PHP version from 8.3 to 8.4.                                                                             |
| .github/workflows/static-analysis.yml           | Updated PHP version from 8.3 to 8.4.                                                                             |
| composer.json                                    | Added symfony/polyfill-php83; upgraded several dev dependencies including phpunit, predis, symfony/process, and twig; reordered dev dependencies. |
| vendor-bin/tools/composer.json                   | Upgraded psalm to v6.12 and added rector/rector and rector/swiss-knife dependencies.                             |
| tests/Fake/fake-app/var/templates/Page/Html/BlogPostingDonut.html.twig | Added new Twig template rendering article and comment variables.                                                 |
| tests/Fake/FakeMobileEtagSetter.php              | Updated method signature to use explicit nullable union types for parameters.                                    |
| tests/QueryRepositoryTest.php                     | Modified JSON string comparison to normalize line endings for cross-platform compatibility; added helper method. |
| tests/UtiTagTest.php                              | Updated expected surrogate key format to reflect new underscore separator and parameter sorting.                 |
| src/RedisDsnProvider.php                          | Added support for RelayCluster type; updated return type and annotations; added #[Override] attribute.           |
| src/DevEtagSetter.php                             | Replaced manual ETag construction with UriTag usage; added #[Override] attribute; removed unused imports.         |
| src/SurrogateKeys.php                             | Replaced manual surrogate key construction with UriTag invocation; removed unused imports.                       |
| src/UriTag.php                                    | Refined surrogate key sanitization replacing certain characters with underscores; added #[Override] attributes.  |
| src/Exception/*.php (ExpireAtKeyNotExists, RedisConnectionException, ResourceStorageUnserializeException, ReturnValueIsNotResourceObjectException, UnmatchedQuery) | Marked all these exception classes as final to prevent subclassing.                                              |
| Multiple source files under src/ (e.g., CacheInterceptor.php, CacheVersionModule.php, CommandInterceptor.php, DevEtagModule.php, DonutCacheModule.php, DonutCommandInterceptor.php, DonutRenderer.php, DonutRepository.php, DonutRequest.php, EtagSetter.php, HttpCache.php, HttpCacheInterceptor.php, MatchQuery.php, MobileEtagModule.php, MobileEtagSetter.php, NullCacheControlHeaderSetter.php, NullCdnCacheControlModule.php, NullPurger.php, ProdQueryRepositoryModule.php, QueryRepository.php, QueryRepositoryModule.php, RefreshAnnotatedCommand.php, RefreshInterceptor.php, RefreshSameCommand.php, RepositoryLogger.php, ResourceStorage.php, StorageExpiryModule.php, StorageMemcachedEtagModule.php, StorageMemcachedModule.php, StorageRedisDsnModule.php, SurrogateKeys.php, UriTag.php, etc.) | Added `#[Override]` attribute annotations to methods overriding parent or interface methods; added import statements for `Override`; no logic or control flow changes except for minor formatting in RepositoryLogger. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant GitHub Actions
    participant Matrix (OS/PHP/Deps)
    participant Runner
    participant Composer
    participant PHPUnit
    participant Redis

    GitHub Actions->>Matrix (OS/PHP/Deps): Start job for each combination
    Matrix->>Runner: Setup environment (OS, PHP version)
    Runner->>Redis: Install and start Redis and Memcached services
    Runner->>Composer: Install dependencies (with/without --prefer-lowest)
    Runner->>PHPUnit: Run PHPUnit tests
    PHPUnit-->>Runner: Test results
    Runner->>GitHub Actions: Upload code coverage (Ubuntu, PHP 8.4, highest deps only)
    alt On Ubuntu & SCRIPT set
        Runner->>Composer: Require doctrine/cache, update dependencies
        Runner->>Runner: Run demo script
    end

Possibly related PRs


</details>

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=bearsunday/BEAR.QueryRepository&utm_content=161):

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

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

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

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

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

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Simplified dependency resolution, updated caching, and revamped matrix strategy to support more OS combinations. Enhanced readability with consistent naming and conditional logic improvements. Updated actions versions and streamlined demo script execution.
@koriym koriym marked this pull request as ready for review June 17, 2025 21:43
@koriym
Copy link
Copy Markdown
Member Author

koriym commented Jun 17, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 17, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Jun 17, 2025

Reviewer's Guide

The PR refactors the CI workflow by reorganizing triggers and environment variables, expanding the build matrix and services, upgrading action versions, consolidating caching, unifying dependency steps, and improving test and demo executions to enhance flexibility and performance.

Flow diagram for improved dependency management and demo execution in CI

flowchart TD
  A[Start Job]
  B[Checkout Repository]
  C[Setup PHP]
  D[Cache Composer Dependencies]
  E[Configure Dependency Resolution]
  F[Update Dependencies]
  G[Run PHPUnit Tests]
  H[Upload Coverage Report]
  I{Is SCRIPT set and OS is ubuntu-latest?}
  J[Prepare Demo Dependencies]
  K[Run Demo Script]
  L[End Job]

  A --> B --> C --> D --> E --> F --> G --> H --> I
  I -- Yes --> J --> K --> L
  I -- No --> L
Loading

File-Level Changes

Change Details Files
Refined workflow triggers and environment variables
  • Standardized markdown ignore patterns for push and PR
  • Removed unused COMPOSER_UPDATE_FLAGS env var
  • Renamed script var to uppercase SCRIPT
  • Adjusted COMPOSER_FLAGS defaults
.github/workflows/continuous-integration.yml
Expanded matrix and service configuration
  • Added windows and macOS runners alongside Ubuntu
  • Included PHP 8.1–8.4 and lowest/highest dependency variants
  • Disabled fail-fast to run all combinations
  • Moved and reformatted Redis service definition
.github/workflows/continuous-integration.yml
Upgraded core actions and step names
  • Bumped actions/checkout from v3 to v4
  • Renamed checkout step for clarity
  • Updated actions/cache to v4
  • Renamed PHPUnit and coverage steps
.github/workflows/continuous-integration.yml
Streamlined Composer caching
  • Switched to caching ~/.composer/cache
  • Enhanced cache key with OS and PHP version
  • Removed custom cache-dir lookup step
.github/workflows/continuous-integration.yml
Consolidated dependency resolution logic
  • Removed separate low/high/ignore handling steps
  • Added single run block to unset platform config
  • Inlined --prefer-lowest flag based on matrix
.github/workflows/continuous-integration.yml
Updated test and coverage commands
  • Renamed test step to Run PHPUnit tests
  • Simplified coverage upload to use files/option flags
  • Enabled fail_ci_if_error for coverage action
.github/workflows/continuous-integration.yml
Enhanced demo script execution
  • Made demo run conditional on SCRIPT and Ubuntu
  • Pre-required doctrine/cache before update
  • Simplified composer update and script invocation
.github/workflows/continuous-integration.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @koriym - I've reviewed your changes - here's some feedback:

  • The matrix exclude only removes the PHP 8.1 + lowest combo on Ubuntu—if you intended to skip 8.1/lowest on all OSes, expand the exclude or add separate rules for Windows/macOS.
  • On Windows runners the Composer cache dir isn’t necessarily ~/.composer/cache; consider using a platform‐aware path or ${{ steps.setup-php.outputs.cache-dir }} to ensure caching works cross‐platform.
  • Using **/composer.lock in the hashFiles key can pick up multiple lockfiles—pin it to the root composer.lock (or a specific path) to avoid unintended cache misses or collisions.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The matrix exclude only removes the PHP 8.1 + lowest combo on Ubuntu—if you intended to skip 8.1/lowest on all OSes, expand the exclude or add separate rules for Windows/macOS.
- On Windows runners the Composer cache dir isn’t necessarily ~/.composer/cache; consider using a platform‐aware path or `${{ steps.setup-php.outputs.cache-dir }}` to ensure caching works cross‐platform.
- Using `**/composer.lock` in the hashFiles key can pick up multiple lockfiles—pin it to the root `composer.lock` (or a specific path) to avoid unintended cache misses or collisions.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

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)
.github/workflows/continuous-integration.yml (3)

6-6: DRY the paths-ignore patterns.
The same **/*.md ignore rule is duplicated under both push and pull_request. Consider combining the events to reduce duplication:

on:
  [push, pull_request]:
    paths-ignore:
      - '**/*.md'

Also applies to: 8-9


13-14: Refine environment variable scoping.
SCRIPT is only used in the demo step—move it into that step’s env: block. You can keep COMPOSER_FLAGS at the global level since it’s consumed by multiple steps.


78-83: Optimize demo execution step.

  • Scope SCRIPT via this step’s env: instead of global.
  • Running composer update is heavy; for demo purposes, prefer:
    composer install --no-dev --no-interaction
    to speed up setup.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b942f72 and 9b7dcd3.

📒 Files selected for processing (1)
  • .github/workflows/continuous-integration.yml (1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/continuous-integration.yml

73-73: the runner of "codecov/codecov-action@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🔇 Additional comments (8)
.github/workflows/continuous-integration.yml (8)

18-19: Dynamic job naming and runner selection look good.
Naming the job with the matrix parameters and using ${{ matrix.os }} for runs-on improves clarity and consistency.


21-21: Disable fail-fast for matrix jobs.
fail-fast: false ensures every PHP/OS/dependency combination runs to completion, providing comprehensive coverage.


23-26: Verify matrix exclusions accuracy.
You’re excluding PHP 8.1 on Ubuntu and PHP 8.1 with lowest dependencies globally. Double-check that these combinations match your intended test surface (e.g., that PHP 8.1-highest still runs on macOS/Windows only).

Also applies to: 29-29


43-44: Updated checkout action to v4.
Upgrading from actions/checkout@v3 to @v4 modernizes the workflow and gains performance improvements.


52-52: Include Composer in PHP setup.
Adding tools: composer ensures Composer is available across all runners without extra installation steps.


63-64: Clean platform config before update.
Unsetting Composer’s platform config unconditionally simplifies dependency resolution across environments.


67-67: Conditionally apply --prefer-lowest.
The expression ${{ matrix.dependencies == 'lowest' && '--prefer-lowest' || '' }} correctly toggles the lowest-dependency flag. Good use of GitHub Actions expressions.


69-69: Step naming is clear.
Run PHPUnit tests succinctly describes the action.

Comment thread .github/workflows/continuous-integration.yml
Comment thread .github/workflows/continuous-integration.yml Outdated
Comment thread .github/workflows/continuous-integration.yml Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 18, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (85688a0) to head (65d6995).
Report is 64 commits behind head on 1.x.

Additional details and impacted files
@@             Coverage Diff             @@
##                 1.x      #161   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
  Complexity       232       232           
===========================================
  Files             51        51           
  Lines            739       741    +2     
===========================================
+ Hits             739       741    +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

koriym added 19 commits June 18, 2025 15:00
Revised the matrix strategy to include detailed configurations for PHP versions and dependencies across Ubuntu, Windows, and macOS. Added Redis setup steps for Windows and macOS to ensure consistency in services. Enhanced workflow flexibility and clarity.
Updated matrix strategy to better support PHP versions and dependencies across different OSes. Added Redis setup steps for all platforms, adjusted service configurations, optimized Composer caching, and streamlined conditional logic for clarity. Enhanced CI execution time and reliability.
Updated matrix strategy to include Redis service for Linux and manual setup for Windows and macOS. Adjusted Redis configuration steps and improved setup consistency across platforms.
…ti-OS behavior, update dependencies, and streamline configuration files.
Extended CI workflow to include Memcached installation and setup for Windows and Linux runners, in addition to macOS. Updated PHP extensions to enable Memcached support.
Switch to `memcached-win64` package due to outdated `memcached` package issues. Update installation and service start steps to ensure correct functionality.
Switch to `memcached.install` package for Windows due to issues with `memcached` and non-existence of `memcached-win64`. Add steps to install and start Memcached on Ubuntu for compatibility across Linux runners. Simplify comments for better clarity.
Add installation parameter to configure Memcached as a Windows Service during setup. Update related comments and ensure proper service start with a delay for stability.
Switch from unreliable Chocolatey package to manual Memcached download and configuration. Update steps to include downloading, extracting, and running Memcached manually for improved stability and reliability.
Switch from Invoke-WebRequest to curl for more reliable downloads, add error handling for download and process checks, and enhance logging to ensure Memcached setup stability.
Switch to dedicated GitHub action for downloading Memcached releases, removing unreliable curl-based downloads. Simplify extraction and setup steps, enhance logging, and refine process validation to improve reliability.
@koriym
Copy link
Copy Markdown
Member Author

koriym commented Jun 19, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 19, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@koriym koriym changed the title Optimize CI workflow for flexibility and efficiency Optimize for better Windows compatibility Jun 19, 2025
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)
.github/workflows/continuous-integration.yml (1)

161-167: Cache configuration needs cross-platform improvement.

The hardcoded ~/.composer/cache path won't work correctly on Windows. Consider using a cross-platform approach.

Use the Composer cache directory environment variable for better cross-platform compatibility:

-          path: ~/.composer/cache
+          path: ${{ env.COMPOSER_CACHE_DIR }}

Alternatively, set COMPOSER_CACHE_DIR in the environment variables or include Windows-specific paths.

🧹 Nitpick comments (1)
.github/workflows/continuous-integration.yml (1)

127-127: Fix trailing whitespace.

Remove trailing spaces as flagged by YAMLlint.

-          #    The URL was found and verified by the user.
+          #    The URL was found and verified by the user.
-          #    Running it as a simple process is the most robust and correct approach here.
+          #    Running it as a simple process is the most robust and correct approach here.

Also applies to: 135-135

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b7dcd3 and 30b4fca.

⛔ Files ignored due to path filters (1)
  • vendor-bin/tools/composer.lock is excluded by !**/*.lock
📒 Files selected for processing (60)
  • .github/workflows/coding-standards.yml (1 hunks)
  • .github/workflows/continuous-integration.yml (1 hunks)
  • .github/workflows/static-analysis.yml (1 hunks)
  • composer.json (1 hunks)
  • src/AbstractDonutCacheInterceptor.php (2 hunks)
  • src/CacheDependency.php (2 hunks)
  • src/CacheInterceptor.php (2 hunks)
  • src/CacheVersionModule.php (2 hunks)
  • src/CacheableModule.php (2 hunks)
  • src/Cdn/AkamaiCacheControlHeaderSetter.php (2 hunks)
  • src/Cdn/AkamaiModule.php (2 hunks)
  • src/Cdn/FastlyCacheControlHeaderSetter.php (1 hunks)
  • src/Cdn/FastlyCachePurger.php (1 hunks)
  • src/Cdn/FastlyModule.php (2 hunks)
  • src/CdnCacheControlHeaderSetter.php (2 hunks)
  • src/CliHttpCache.php (3 hunks)
  • src/CommandInterceptor.php (2 hunks)
  • src/CommandsProvider.php (2 hunks)
  • src/DevEtagModule.php (2 hunks)
  • src/DevEtagSetter.php (2 hunks)
  • src/DonutCacheModule.php (2 hunks)
  • src/DonutCommandInterceptor.php (1 hunks)
  • src/DonutRenderer.php (2 hunks)
  • src/DonutRepository.php (6 hunks)
  • src/DonutRequest.php (2 hunks)
  • src/EtagSetter.php (2 hunks)
  • src/Exception/ExpireAtKeyNotExists.php (1 hunks)
  • src/Exception/RedisConnectionException.php (1 hunks)
  • src/Exception/ResourceStorageUnserializeException.php (1 hunks)
  • src/Exception/ReturnValueIsNotResourceObjectException.php (1 hunks)
  • src/Exception/UnmatchedQuery.php (1 hunks)
  • src/HttpCache.php (3 hunks)
  • src/HttpCacheInterceptor.php (2 hunks)
  • src/MatchQuery.php (2 hunks)
  • src/MobileEtagModule.php (2 hunks)
  • src/MobileEtagSetter.php (2 hunks)
  • src/NullCacheControlHeaderSetter.php (1 hunks)
  • src/NullCdnCacheControlModule.php (1 hunks)
  • src/NullPurger.php (1 hunks)
  • src/ProdQueryRepositoryModule.php (2 hunks)
  • src/QueryRepository.php (4 hunks)
  • src/QueryRepositoryModule.php (2 hunks)
  • src/RedisDsnProvider.php (2 hunks)
  • src/RefreshAnnotatedCommand.php (2 hunks)
  • src/RefreshInterceptor.php (2 hunks)
  • src/RefreshSameCommand.php (1 hunks)
  • src/RepositoryLogger.php (3 hunks)
  • src/ResourceStorage.php (11 hunks)
  • src/StorageExpiryModule.php (2 hunks)
  • src/StorageMemcachedEtagModule.php (2 hunks)
  • src/StorageMemcachedModule.php (2 hunks)
  • src/StorageRedisDsnModule.php (2 hunks)
  • src/SurrogateKeys.php (1 hunks)
  • src/UriTag.php (2 hunks)
  • tests/Fake/FakeMobileEtagSetter.php (1 hunks)
  • tests/Fake/fake-app/var/templates/Page/Html/BlogPostingDonut.html.twig (0 hunks)
  • tests/Fake/fake-app/var/templates/Page/Html/BlogPostingDonut.html.twig (1 hunks)
  • tests/QueryRepositoryTest.php (2 hunks)
  • tests/UtiTagTest.php (1 hunks)
  • vendor-bin/tools/composer.json (1 hunks)
✅ Files skipped from review due to trivial changes (41)
  • src/CacheableModule.php
  • src/MatchQuery.php
  • src/CacheInterceptor.php
  • src/MobileEtagModule.php
  • src/CdnCacheControlHeaderSetter.php
  • tests/Fake/fake-app/var/templates/Page/Html/BlogPostingDonut.html.twig
  • src/Cdn/AkamaiCacheControlHeaderSetter.php
  • src/EtagSetter.php
  • src/CacheDependency.php
  • src/MobileEtagSetter.php
  • src/Exception/RedisConnectionException.php
  • src/Cdn/AkamaiModule.php
  • src/DonutRenderer.php
  • src/Exception/ResourceStorageUnserializeException.php
  • .github/workflows/coding-standards.yml
  • .github/workflows/static-analysis.yml
  • src/DonutRequest.php
  • src/DonutCommandInterceptor.php
  • src/Exception/UnmatchedQuery.php
  • src/CommandInterceptor.php
  • src/NullCdnCacheControlModule.php
  • src/StorageRedisDsnModule.php
  • src/StorageExpiryModule.php
  • src/CliHttpCache.php
  • src/RefreshSameCommand.php
  • src/QueryRepositoryModule.php
  • src/HttpCacheInterceptor.php
  • src/Exception/ReturnValueIsNotResourceObjectException.php
  • src/DonutCacheModule.php
  • src/AbstractDonutCacheInterceptor.php
  • src/Cdn/FastlyCacheControlHeaderSetter.php
  • src/Cdn/FastlyModule.php
  • src/Exception/ExpireAtKeyNotExists.php
  • src/ProdQueryRepositoryModule.php
  • src/StorageMemcachedEtagModule.php
  • src/Cdn/FastlyCachePurger.php
  • tests/Fake/fake-app/var/templates/Page/Html/BlogPostingDonut.html.twig
  • src/HttpCache.php
  • src/CommandsProvider.php
  • composer.json
  • src/DonutRepository.php
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/continuous-integration.yml

[error] 127-127: trailing spaces

(trailing-spaces)


[error] 135-135: trailing spaces

(trailing-spaces)

🔇 Additional comments (35)
tests/Fake/FakeMobileEtagSetter.php (1)

22-22: LGTM! Improved type safety with explicit union types.

The change from implicit nullable parameters to explicit union types (int|null, HttpCache|null) enhances code clarity and follows modern PHP best practices. This makes the method signature more explicit about accepting null values.

src/NullPurger.php (1)

7-7: LGTM! Excellent use of the Override attribute.

The addition of the #[Override] attribute provides explicit documentation that this method overrides the PurgerInterface::__invoke() method and enables compile-time verification of the override relationship.

Also applies to: 11-11

src/DevEtagModule.php (1)

7-7: LGTM! Proper override annotation added.

The #[Override] attribute correctly documents that this method overrides AbstractModule::configure() and provides compile-time safety by ensuring the override relationship is valid.

Also applies to: 22-22

src/RefreshInterceptor.php (1)

10-10: LGTM! Override attribute correctly applied.

The #[Override] attribute appropriately documents that this method implements MethodInterceptor::invoke() and provides valuable compile-time verification of the interface contract.

Also applies to: 21-21

src/CacheVersionModule.php (1)

7-7: LGTM! Override attribute enhances method documentation.

The #[Override] attribute correctly indicates that this method overrides AbstractModule::configure() and enables compile-time validation of the override relationship.

Also applies to: 30-30

src/RefreshAnnotatedCommand.php (1)

13-13: LGTM! Override attribute properly documents interface implementation.

The #[Override] attribute correctly marks this method as implementing CommandInterface::command() and provides compile-time assurance that the interface contract is properly fulfilled.

Also applies to: 27-27

src/NullCacheControlHeaderSetter.php (1)

8-8: Excellent addition of explicit override annotation.

The #[Override] attribute clearly documents that this method implements the interface contract, improving code clarity and enabling better IDE/tooling support.

Also applies to: 12-12

src/RepositoryLogger.php (2)

7-7: Good addition of explicit override annotations.

The #[Override] attributes properly document interface method implementations, enhancing code clarity and tooling support.

Also applies to: 12-12, 24-24, 41-41


36-36: Functionally equivalent sprintf to vsprintf conversion.

The change from sprintf(...$values) to vsprintf($template, $values) maintains identical functionality while using a different argument passing approach. Both implementations produce the same result.

src/QueryRepository.php (1)

13-13: Excellent systematic addition of override annotations.

All three public methods correctly implement QueryRepositoryInterface, and the #[Override] attributes clearly document these interface implementations. This improves code maintainability and enables better IDE support.

Also applies to: 35-35, 61-61, 78-78

tests/QueryRepositoryTest.php (2)

33-33: Good addition of str_replace import for line ending normalization.

The import supports the cross-platform compatibility improvements in the test.


137-140: Excellent cross-platform line ending normalization helper.

The normalizeLineEndings method properly handles Windows (\r\n) and old Mac (\r) line endings, converting them to Unix (\n) style. This aligns perfectly with the PR's multi-OS CI testing objectives.

src/ResourceStorage.php (2)

12-12: Comprehensive and systematic override annotations.

All public methods correctly implement ResourceStorageInterface, and the #[Override] attributes systematically document these implementations. This significantly improves code maintainability and enables better IDE/tooling support across the entire storage interface.

Also applies to: 90-90, 100-100, 114-114, 123-123, 134-134, 151-151, 169-169, 185-185, 194-194, 260-260


268-268: Helpful documentation comment for etag sanitization.

The comment clarifies that the etag parameter is sanitized before saving, providing useful context for understanding the storage behavior.

src/StorageMemcachedModule.php (1)

9-9: LGTM! Good use of #[Override] attribute for code clarity.

The addition of the #[Override] attribute improves code documentation by explicitly marking the configure() method as overriding the parent AbstractModule::configure() method. This provides better IDE support and helps catch signature mismatches.

Also applies to: 31-31

vendor-bin/tools/composer.json (1)

6-8: Verify compatibility of major version upgrades.

The addition of Rector tools is excellent for code quality automation, and the Psalm upgrade from v5 to v6 brings improved static analysis. However, major version upgrades may introduce breaking changes or new analysis rules.

Please test the updated tools to ensure they work correctly with the current codebase:

#!/bin/bash
# Description: Test the updated static analysis tools
# Expected: All tools should run without errors and be compatible with PHP 8.1+

# Test Rector
echo "Testing Rector..."
vendor-bin/tools/vendor/bin/rector --version
vendor-bin/tools/vendor/bin/rector process --dry-run src/ || echo "Rector failed"

# Test Psalm
echo "Testing Psalm..."
vendor-bin/tools/vendor/bin/psalm --version  
vendor-bin/tools/vendor/bin/psalm --show-info=false || echo "Psalm failed"

# Test swiss-knife
echo "Testing Swiss Knife..."
vendor-bin/tools/vendor/bin/swiss-knife --version || echo "Swiss Knife failed"
tests/UtiTagTest.php (1)

15-17: Excellent test coverage for UriTag normalization.

The updated test correctly validates the new UriTag behavior:

  • Query parameters are now separated by underscores (more cache-friendly)
  • Parameter order normalization ensures consistent cache keys regardless of query parameter order

This improves cache efficiency by ensuring ?a=1&b=2 and ?b=2&a=1 produce identical cache keys.

src/SurrogateKeys.php (1)

25-25: Good refactoring to centralize URI key generation.

Delegating surrogate key generation to UriTag improves code maintainability by:

  • Centralizing URI-to-key conversion logic
  • Eliminating duplicate string manipulation code
  • Ensuring consistent key generation across the codebase

This aligns well with the UriTag normalization changes validated in the tests.

src/DevEtagSetter.php (2)

11-11: Good addition of #[Override] attribute.

The #[Override] attribute properly documents that this method implements the EtagSetterInterface::__invoke() method, improving code clarity and IDE support.

Also applies to: 25-25


28-32: Excellent refactoring to use UriTag for consistency.

The refactoring to use UriTag for ETag generation:

  • Ensures consistent URI-to-key conversion across the codebase
  • Simplifies the code by removing manual string manipulation
  • Provides helpful comments explaining the dev-mode behavior
  • Aligns with the UriTag normalization improvements

This creates a unified approach to URI-based cache key generation throughout the system.

src/UriTag.php (4)

9-9: Good practice: Adding Override import.

The addition of the Override import enables explicit marking of overriding methods, improving code clarity and enabling static analysis benefits.


23-23: Correct use of Override attribute.

The #[Override] attribute correctly marks this method as overriding the interface method, improving code documentation and enabling compile-time validation.


29-33: Excellent URI sanitization improvement.

The refined logic now properly sanitizes URI keys by replacing /, ?, and & with underscores, making them compatible with Symfony cache adapter requirements. The comment clearly explains the purpose and benefits.


39-39: Consistent Override attribute usage.

Good consistency in marking interface method overrides with the #[Override] attribute.

src/RedisDsnProvider.php (4)

9-9: Good addition of Override import.

Consistent with the broader codebase pattern of adding explicit Override attributes.


15-15: Proper import alias for RelayCluster.

The import alias Relay\Cluster as RelayCluster clearly differentiates from other cluster types and maintains readability.


19-19: Comprehensive type annotation update.

The generic type annotation correctly includes RelayCluster alongside existing Redis connection types, maintaining type safety.


34-41: Enhanced type safety and documentation.

The #[Override] attribute and typed variable assignment improve both documentation and type safety. The explicit typing of the $connection variable ensures proper type validation at runtime.

.github/workflows/continuous-integration.yml (7)

6-13: Good optimization: Ignoring documentation-only changes.

The path ignores for markdown files, text files, and LICENSE prevent unnecessary CI runs for documentation-only changes, improving efficiency.


22-64: Excellent multi-platform testing matrix.

The structured approach to testing across Ubuntu (all PHP versions), Windows and macOS (latest PHP only) provides comprehensive coverage while balancing CI resource usage. The clear commenting makes the strategy easy to understand.


67-68: Good: Updated checkout action to v4.

Upgrading from v3 to v4 ensures compatibility with the latest GitHub Actions infrastructure.


71-97: Comprehensive Redis setup across platforms.

The platform-specific Redis installation and startup logic properly handles the differences between Linux, Windows, and macOS environments. Good use of conditional steps and verification with redis-cli ping.


112-149: Robust Windows Memcached implementation.

The detailed Windows Memcached setup addresses the complexity of installing Memcached on Windows with proper error handling and verification steps. The comments clearly explain the approach and reasoning.


179-179: Codecov action version updated correctly.

Good update from v3 to v4, addressing the previous review feedback about the outdated action version.


184-189: Well-implemented conditional demo script execution.

The demo script step is properly conditioned to run only on Ubuntu with PHP 8.4 and highest dependencies, with appropriate dependency management before execution.

Comment thread tests/QueryRepositoryTest.php
@koriym koriym merged commit 9e7ca85 into 1.x Jun 20, 2025
35 checks passed
@koriym koriym deleted the cache branch June 20, 2025 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant