Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Composer - run scripts only in dev environment

This is my composer.json file:

"require": {     "php": ">=5.4",     "zendframework/zendframework": "2.*",     "doctrine/doctrine-module": "dev-master",     "doctrine/doctrine-orm-module": "0.*",     "gedmo/doctrine-extensions": "dev-master" }, "require-dev": {     "phpunit/phpunit": "3.7.*" }, "scripts": {     "post-update-cmd": [         "rm -rf vendor/Behat",         "git clone git://github.com/Behat/Behat.git",         "cp composer.phar Behat/composer.phar",         "cd Behat && git submodule update --init",         "cd Behat && php composer.phar install",         "cd Behat && php composer.phar require guzzle/guzzle:3.0.*",         "mv Behat vendor/Behat",         "ln -sf ../Behat/bin/behat vendor/bin/"     ] } 

How can I make it so the scripts are only run in the dev environment?

Basically I want the scripts to run only when I call:

php composer.phar update --dev 
like image 457
Richard Knop Avatar asked Oct 26 '12 12:10

Richard Knop


People also ask

What is require Dev in composer?

The require_dev lists packages required for developing this package, or running tests, etc. The dev requirements of the root package are installed by default.

What is -- no Dev in composer?

--no-dev: Skip installing packages listed in require-dev . The autoloader generation skips the autoload-dev rules. Also see COMPOSER_NO_DEV. --no-install: Does not run the install step after updating the composer.

What is composer update -- no scripts?

composer upgrade --no-scripts. This is especially useful when upgrading packages while your code is currently not working. It would also work if your only scripts are development and test-related. Running one script separately (docs)


2 Answers

To do the non-development environment update without triggering any scripts, use the --no-scripts command line switch for the update command:

php composer.phar update --no-scripts                          ^^^^^^^^^^^^ 

By default, Composer scripts are only executed in the base package. So you could have one package for development and in the live environment make it a dependency of the live system.

Apart from that, I do not see any way to differentiate scripts automatically.

like image 138
hakre Avatar answered Sep 18 '22 15:09

hakre


Introduction

Some of the answers are a bit brief and don't go into detail about the context in which this is done. I'd like to share some knowledge with whoever is still puzzled after reading the previous answers.

Determine the right option for you

First, take a moment to realise that you're effectively creating a different flow, specific for a certain environment (i.e. your development server/container). This is against any best practices, as it is generally prone to errors. Having said that, you can achieve what you want in several ways;

Not triggering any scripts (docs)

If on some environment you do not want to trigger any scripts, you can prevent this using the --no-scripts flag.

Documentation reads: --no-scripts: Skips execution of scripts defined in composer.json.

composer upgrade --no-scripts 

This is especially useful when upgrading packages while your code is currently not working. It would also work if your only scripts are development and test-related.

Running one script separately (docs)

Simply run the specific command as needed:

composer run-script [--dev] [--no-dev] script 

This is useful when you want to run a script only on specific occasions.

For example, on build systems that have to perform a certain script before running any tests; build systems offer configuration options to call custom scripts like the above.

Defining a condition in the command (docs)

Documentation reads: During a composer install or update process, a variable named COMPOSER_DEV_MODE will be added to the environment. If the command was run with the --no-dev flag, this variable will be set to 0, otherwise it will be set to 1.

An example could look like

"scripts": {     "post-install-cmd": [          "[ $COMPOSER_DEV_MODE -eq 0 ] || <your command>"     ] } 

Personally i would say this is the recommended way if you are using containers.

Note: this does not work on windows, since it would need %COMPOSER_DEV_MODE%.

There are also packages (like scriptsdev by neronmoon) that help you achieve the same goal without having to type the above in all commands, using a dev-scripts section in the extra section in composer.json

Defining a condition in your PHP script (docs)

Call a PHP method, that checks your environment based on how your application already does this. You can even reuse this condition by combining it with the method above; "Defining a condition in the command".

"scripts": {     "post-update-cmd": [         "AppNameSpaceName\\YourClassName::methodName"     ] } 

You can then go ahead and create the class, like so:

<?php  namespace AppNameSpaceName;  class YourClassName  {     methodName() {          // do stuff     } } 

In many modern frameworks there is already a mechanism present to determine the runtime environment of the application (Symfony way, Laravel way).

Yarn run (docs)

Since most PHP applications nowadays also transpile their javascript files, either NPM or Yarn would be installed. You can use the scripts section to run this part only on development machines/containers. For example:

yarn run dev-only-script 

having a section in package.json

"scripts": {     "dev-only-script": "rm some/folder && ln -s path/to/your/folder some/" } 

The point of this is would be to your composer.json clean. In yarn you could have scripts for dev-server, test and build.

like image 35
Webber Avatar answered Sep 16 '22 15:09

Webber