-
Notifications
You must be signed in to change notification settings - Fork 446
Description
Hi,
I'm opening this PR to try to get the file composer.lock live in the repository and be part of the Grumphp sources.
Summary
The composer.lock file, though sometimes overlooked, is key for project reproducibility, performance, and security.
Rationale
Composer is the dependency manager for PHP. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you. In a composer.json file, you specify the dependencies for your project. For example, you might need a certain library, and that library might need another library, and so on.
When you run composer install for the first time, it resolves dependencies and then downloads all of them and writes all of the packages and the exact versions of them that it downloaded to the composer.lock file, locking the project to those specific versions.
Committing this file in this repo is important for many reasons:
-
Reproducibility: Reproducibility is one of the foundational aspects of software engineering. It ensures that all team members and the deployment system are using the exact same versions of the dependencies. This eliminates the potential issues that may arise from differences in versions used, such as function deprecations, changes in behavior, etc. Without the
composer.lockfile, runningcomposer installwould fetch the latest versions of the dependencies you defined incomposer.json, which could cause inconsistencies between environments. -
Security: It helps ensure that you're using the versions of dependencies that you have tested and reviewed. Without a
composer.lockfile, there's a risk that a malicious person could find a vulnerability in one of your dependencies, fix that vulnerability, bump the version number, and if you runcomposer installorcomposer update, you could be pulling in un-reviewed/un-tested code since you do not control anymore the dependency resolution and delegate it to the host system. -
Speed: Having a
composer.lockfile speeds up the composer installation process. Composer no longer needs to resolve dependencies (which can take some time) and can just download the version of each dependency specified in thecomposer.lock.
Inclusion of composer.lock in this repository also promotes the following advantages (but I won't go into the details, this post is already too long):
- Less time spending in debugging,
- Increased reliability,
- Enhanced collaboration and scalability,
- Effective version control,
- Streamlined Continuous Integration and Continuous Deployment,
- Efficient auditing and compliance,
- Reliable scientific and data-driven applications.
Conclusion
While the composer.lock file may appear nonessential and is sometimes overlooked, its inclusion is critical for ensuring the reproducibility, speed, and security of your project. By including the composer.lock file in your project's repository, you are effectively shifting the responsibility of specifying correct dependencies from the end-users to the project's author.
Consequently, the author takes charge of determining the precise dependencies to install, sparing the users from this task. This approach streamlines the installation process and fosters a consistent project environment.
By including the composer.lock file in the repository, not only does it improve the development experience for contributors, but it also provides users with an assurance of quality, security, and reliability. The presence of the composer.lock file signifies that the project's dependencies are carefully managed and tested. It confirms that the project operates effectively with the locked versions of dependencies, thus reducing the risk of compatibility issues, unexpected behavior and bugs.
The composer.lock file ultimately serves as a testament to the project's stability. It safeguards users against potential risks associated with untested updates or patches in dependencies. Therefore, both contributors and users can benefit from the project author's meticulous dependency management reflected in the committed composer.lock file. This can enhance the overall confidence in the project's robustness and reliability.
Further Considerations
While Grumphp is developed in PHP, it can also be viewed as a binary, not solely a PHP library. Given this, it's imperative that it retains reproducibility across various environments. composer.lock is our most effective asset to ensure this within the PHP ecosystem. Considering the reasons outlined here, I strongly believe it deserves a place in the project.
What others are doing ?
It's often beneficial to consider practices in other projects. Composer, the PHP package manager itself, follows this practice. There are many more such examples in the ecosystem.
Application, binaries, libraries
A PHP application or binary is a standalone piece of software intended to be installed and run as is, and the composer.lock file should be included. This is because the application or binary needs to ensure that it is using the exact versions of its dependencies that it was developed and tested with. If the dependencies were to change unpredictably, the application could break. Therefore, the composer.lock file, which specifies the exact versions of the dependencies, is essential.
On the other hand, a PHP library is a piece of software intended to be included as a dependency of other projects. In this case, the composer.lock file is typically not included in version control. This is because the library should be compatible with a range of versions of its own dependencies. The library doesn't control the exact versions of its dependencies - the parent project that uses the library does. As such, the dependency resolving mechanism should indeed be handled by the project that requires the library, not the library itself.
Relation with Nix
Reproducibility is a hard requirement when bundling packages in Nix. To build a reproducible version of Grumphp, we need to ensure all inputs are accurately provided to Composer. We currently provide the composer.lock ourselves to ensure consistent use of the same dependencies, and I believe we should not do that. Making developers aware of the significance of this file would be beneficial.
Practical, hands on
To ensure reproducibility with a Grumphp build, containing composer.lock:
git clone https://github.com/phpro/grumphpcd grumphp
This next step is mandatory to prevent Composer to generate random class names for the Autoloader:
composer config autoloader-suffix FooBar
Let's install the required dependencies only:
composer install --no-dev
The next command will compute a checksum of the grumphp directory containing now the vendor directory:
cd -; dir=grumphp find "$dir" -type f -not -path '*/\.git/*' -exec sha256sum {} \; | LC_ALL=C sort -d | sha256sum; cd -
When the composer.lock is available, there is a guarantee of reproducibility, you could run this on any platform and you will always get the same checksum.
When the composer.lock is not available, the checksum might be different from a day to another, there is absolutely no guarantee of reproducibility.