Ignore tests folder when send to packagist - php

I have a project with the following structure:
- src
----/ /* Relevant files */
- tests
----/ /* Irrelevant files */
- composer.json
- phpunit.xml
The project is sent to packagist on every commit already. But, it is sending the test files.
I'd like to ignore tests folder, so composer wont download unecessary files when someone calls composer require my/package
Here is whats the content of my composer.json looks like:
{
"name": "my/package",
"description": "...",
"type": "library",
"license": "MIT",
"require": {
"php": ">=7"
},
"require-dev": {
"phpunit/phpunit": ">=5.4"
},
"autoload": {
"psr-4": {
"MyProject\\": "./src"
}
}
}

Ignore tests folder when send to packagist
Let's first clear up some confusion.
When you enable Packagist for your repository, Packagist will load the composer.json to get metadata about your project and fetch the version informations from the tags/branches.
But you are not sending your PHP code or any tests to Packagist.
I'd like to ignore tests folder, so composer wont download unecessary files when someone calls composer require my/package
This question pops up quite often. I'm referencing a detailed answer, which i've written some time ago, which explains a lot of the background: https://stackoverflow.com/a/32476500/1163786
Usage of a .gitattributes file with export-ignore directive
Technically, you could add a .gitattributes file to your repository, which declares a export-ignore rule for the test folder.
This means that any git export will no longer have the tests folder, including the Github zip file.
Ok, exclude done..
But, when someone composer require's your project, it will now depend on the --prefer-dist setting to install the package from the dist (zip). (You would get the tests with --prefer-source).
If it is a small library, stop to worry. Be happy.. :)
If it is a bigger application, then a better solution is to package your application properly, instead of relying on the git exported zip distribution.
Most developers don't use a build.xml or any build script anymore, but that's the correct way to do it in my opinion.
That means once you are ready to tag a new release.
You trigger your build script, which fetches all the dependencies, runs the tests once more and when everything is ok, drop all the tests and packages the files for deployment.
Small hint: don't forget to add a autoload-dev section for your tests to composer.json.

If your Packagist package is linked to a GitHub repo, just create a "Release" in GitHub that does not contain the development files.
This works out-of-the-box for your end users, because Composer install/update uses --prefer-dist by default, which serves the package zip that is in the "Release".
The easiest way to do this (And it's how some Symfony packages does it, for instance), is to create a .gitattributes (as Jens suggested) with the following content:
/tests export-ignore
Now, when you create a tag/release in GitHub, the release zip won't contain the tests folder.
The only scenario where tests folder would be included in this case is if the user installed your package with --prefer-source, but if they do that, they should know what they're doing.

Related

Using PHP Composer to develop a local package and then copy it on deploy

I've got a local PHP project (a website), and I want to use another project I've made (a tiny web framework) as a Composer package for the website project. I'm developing them in tandem, but want to keep them as separate projects; when I deploy the website, I want to use Composer to install the framework project as a package, just like I would with Guzzle or any other common Composer package.
The website project has the following composer.json:
{
"repositories": [
{
"type": "path",
"url": "/local/path/to/framework/package"
"options": {
"symlink": true
}
}
],
"require": {
"my/framework": "dev-master",
"guzzlehttp/guzzle": "6.3.3"
}
}
In /local/path/to/framework/package/composer.json I have:
{
"name": "my/framework",
"description": "A tiny framework.",
"autoload": {
"psr-4": {
"MyFramework\\": "src"
}
}
}
I run php composer.phar update and it sets up a symlink to the framework package in my website project. If I update code in the framework, it's immediately available to the website code. This is great.
However, later on I want to deploy the website project to my web server. For a clean deployment, I have a deploy script that exports an archive copy of the appropriate branch of the website git repo, and then runs php composer.phar install to make sure all the proper packages are installed. With the above config, the deploy script creates a symlink to the framework package, which is obviously no good when the deployment artifact is zipped up and scp'd out to the web server.
If I remove the symlink option above, then I have to run php composer.phar update every time I make any changes in the framework package, which is irritating since I'm developing the packages in tandem. But then on deploy, the package is copied in, rather than being symlinked in; this is good for deploy, except it always copies in the master branch (because I specified dev-master in composer.json).
Is there a way to set up Composer so that I can have the convenience of a local symlinked package for development, but to let the deployment script get a clean copy of the framework package, without having to change composer.json every time I want to deploy?
I also tried changing the repository type to vcs instead of path, but then Composer clones the framework package repository, and I really don't need a clone of the repo in my local vendor/ tree, either during development or deployment. I just want to be able to have a symlinked tree (which gets me instant updates) during development, and have a clean package installed for deplotment.
I may have to resign myself to developing the framework project "properly," that is, as a Composer package that I tag with actual release version numbers, and then update my website project to use a specific version of when it comes time for a deployment. I still haven't figured out the easiest way to do that, though.
You can use Composer Studio plugin.
It uses a separate file for configuration and allows you to have symlinks in development and a regular Composer install for prod deploy, without touching composer.json.
With it, your website composer.json will look like a regular file:
{
"require": {
"my/framework": "dev-master",
"guzzlehttp/guzzle": "6.3.3"
}
}
And with studio.json in the root of the project, with the following content:
{
"version": 2,
"paths": [
"/local/path/to/framework/package"
]
}
you can tell the plugin where to locate my/framework. Studio will then symlink the packages from the provided paths.
To have a regular install, just remove or rename studio.json, remove the vendor folder and composer.lock file and run the install again when deploying.
I made a composer plugin to make it more easy to test packages.
It doesn't require a configuration file, changing your composer.json and doesn't change the upgrade behavior of composer update
https://github.com/SanderSander/composer-link
It works as simple as calling composer link ../path-to-package to link the local package into your project.

How to install a manual downloaded composer-based plugin in a composer-based application?

for educational proposes I write my own PHP application and add a little plugin system. The application itself uses composer to manage required dependencies.
It is possible that a plugin have his own dependencies (Guzzle etc.) and that two plugins have some overlapping dependencies. To reduce storage and avoid any interference I will use composer with composer installers for the plugins:
/src
/plugins
/DemoPlugin
composer.json
/src
/config
...
/vendor
composer.phar
composer.json
...
So it is possible to install a plugin easy over the "main" application and composer handles all dependencies automatically (incl. autoloading).
But this workflow creates a problem that I cant solve at the moment: It requires that the user uses composer require app/plugin-name and download the plugin from the network. But I cant guarantee that every plugin can be installed this way. For example: Paid plugins, company internal plugins or simple dev plugins which only exists as "zip file".
With composer installers the plugins are stored in a different directory, in place of the "classic" vendor directory. But from my understanding it is not possible to copy a zip based plugin into this plugin folder. I cant find any method to start the installation of the plugin (downloading vendor, maybe setup scripts etc.).
This concludes into my question: It is possible to tell the composer instance from the "main application" that a plugin should be installed (downloading vendor, maybe setup scripts etc.) but dont start a download because the plugin is already placed correctly?
If I run composer install in the plugin directory, composer will download the vendor directly into the plugin directory - with all the problems (duplicate dependencies, no integration into the autoload etc.).
I appreciate any help!
What you are looking for is a path repository.
To follow your example you can use the following composer.json
{
"name": "test/test",
"type": "test",
"repositories": [{
"type": "path",
"url": "./plugins/**/"
}],
"require": {
"guzzlehttp/guzzle": "^6.3"
}
}
Where you have the following structure:
├── composer.json
├── composer.lock
└── plugins
└── DemoPlugin
└── composer.json
You can eventually require your plugin as you would do usually:
composer require "test/demo:#dev"
And you will see the dependencies are not duplicated (you do not need to install the DemoPlugin package).

Is it possible to get /dist only in Composer?

I'd like to use composer for managing my front-end dependencies as well.
Unfortunately, using "bower-asset/bootstrap": "dev-master" or "twbs/bootstrap": "dev-master" brings more than 80 MB of code, while I need only /dist/ from the whole bootstrap folder.
Is it possible to add only /dist/ of bootstrap to my application using dependency manager?
You can ignore files with the composer fxp-asset plugin.
For instance, if want only the dist folder of bootstrap, add these lines in your composer.json :
"config": {
"process-timeout": 1800,
"fxp-asset":{
"ignore-files": {
"bower-asset/bootstrap": [
"!dist",
"*"
]
}
}
}
Composer cannot influence what is in the packages you download. Especially if you depend on branches (hint: don't do it), basically the only thing Composer does is clone that repository. This adds up to probably the amount of data you see.
You may try to influence what Composer downloads by adding --prefer-dist to the update command (you may need to delete the vendor folder before you update), but if Composer is unable to locate a source for a ZIP download, it will still clone the repo.

Composer install package from private GIT repository without the .git directory

I have a project X which relies on module Y. They are both my private projects. Each have their own git repository on bitbucket. And each of them has a composer.json.
When I run composer install on project X, it gets Y from its repository and shoves it into X's vendor directory.
The problem is it also shoves a .git directory in vendor/jodes/Y/.
This is a problem because something keeps opening files in that .git directory, meaning my [continuous integration] scripts cannot then delete the .git directory when it repeats the process. I presume it's my IDE.
How can I make composer get Y from the repository, without making a `.git` directory?
X's composer.json is:
{
"name": "jodes/X",
"require": {
"jodes/Y": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "https://Jodes#bitbucket.org/Jodes/Y.git"
}
]
}
It seems that composer basically runs git clone to fetch from the repository? Instead, is there a way to make it do something similar to git archive into the vendor directory? (rather than a zip file).
as a workaround I have tried configuring my IDE (Netbeans) to ignore the .git directory but my scripts still get the "Permission denied" error when trying to delete it.
As a bonus, I would also like to make use of other advantages of using git archive, such as being able to specify files or directories or other patterns which will be excluded from the archive.
composer [install|update] --prefer-dist
should do the trick.
By default, especially when you refer to branches, instead of tags ("versions"), composer prefers to fetch the dependencies as source. If you specify --prefer-dist you explicitely tell composer to use the archive instead.

Where do PHP Composer Packages Come From?

When I run
$ composer.phar install
where do the packages that get installed come from?
I understand that Packagist is the default repository for PHP packages, and that lacking a different package in composer.json, this is where composer will look for packages.
However, what I'm not clear on is how Composer and Packagist interact.
Does Composer download files directly from packagist.org
Or does Composer get a git/svn/hg repository link from packagist and download the files from the repository directly?
Or something else?
It depends on the contents of your composer.json file.
For example, if your composer.json contained simply
{
"require": {
"phpunit/phpunit": "3.8.*#dev"
}
}
then composer searches packagist, and finds phpunit here:
https://packagist.org/packages/phpunit/phpunit
which tells composer to load phpunit from here:
https://github.com/sebastianbergmann/phpunit.git
If instead your composer.json contained
{
"repositories": [
{
"type": "vcs",
"url": "http://github.com/sebastianbergmann/phpunit"
}
],
"require": {
"phpunit/phpunit": "3.8.*#dev"
}
}
then composer will not look to packagist, but go directly to github to download the repo.
The packages registered on Packagist are usually the "authoritative" version of the package (not a fork), but I have found several instances where this is NOT the case, so you should check it to be sure you are pulling the package you expect.
Packagist.org offers users to register their software there by pointing Packagist to read their composer.json file that is published somewhere on the web.
The usual case would be some of the common open source hosters like github, which makes it really easy because composer can deal with such a git repo right away. You could however host your own git or svn or hg repository, or even just publish ready-made ZIP or TGZ files for each software version.
Composer downloads directly from the source, e.g. Packagist only knows those source and tells your composer instance where to go. It does this by downloading a bunch of json files from Packagist.org that have all the infos. This is way easier than to find out where the libraries that you want are hosted and add this info as a repository entry into your local composer.json file. :)

Categories