The traditional way to install composer is to download it from composer.org using “curl”, pipe it into PHP and then place the resultant file in your path while also making it executable. Simple enough to script! Then comes the need to create and initialize a project so the vendor directory and required PHP packages are available.
Scripting this into two state files makes the process very easy to implement, apply and manage.
First the install state file, if you followed my guides you know that I am big on creating reusable “roles” that live in /srv/salt/roles/ these are then applied like a shopping list of roles you can reuse for each server/virtual machine (VM) environment.
In this article we will have two roles in the /srv/salt/roles/composer directory. The first is an “install” state file called install.sls and then the project file that lives in your sever state file directory. For a VM called php-test-01 the directory would be /srv/salt/servers/php-test-01/ and the file might be composer-project.sls
Install.sls
Installs into /usr/local/bin but downloads the composer file to /root initially.
get-composer:
cmd.run:
- name: 'CURL=`which curl`; $CURL -sS https://getcomposer.org/installer | php'
- unless: test -f /usr/local/bin/composer
- cwd: /root/
install-composer:
cmd.wait:
- name: mv /root/composer.phar /usr/local/bin/composer
- cwd: /root/
- watch:
- cmd: get-composer
/usr/local/bin:
composer.installed:
- no_dev: true
- require:
- cmd: install-composer
#
# End of File
composer-project.sls
The next file is the composer-project.sls, this is defined for each project and we can use pillar data to manage the project details, this makes the file below re-usable between servers. For this example, I set /opt as the project but for a web based system, this would normally be something like /var/www/vhosts/<project>/
#
# Composer Project definition
#
# In your pillar define the following (use your own packages).
#composer:
# project:
# - name: <proj_name_here>
# packages:
# - 'monolog/monolog'
# - 'friendsofphp/php-cs-fixer'
# - 'fzaninotto/faker'
# - 'phpbench/phpbench'
# - 'phpstan/phpstan'
# - 'phpstan/phpstan-deprecation-rules'
# - 'phpstan/phpstan-strict-rules'
# - 'phpunit/phpunit'
#
# The project packages
#
{% set project_name = salt['pillar.get']("composer:project:name") %}
{% set packages = salt['pillar.get']("composer:packages") %}
# Without composer installed in your PATH
# Note: composer.phar must be executable for state to work properly
/opt/{{project_name}}:
file.directory:
- user: root
- group: root
- mode: '0775'
- makedirs: True
{{project_name}}:
cmd.run:
- name: composer init
- cwd: /opt/{{project_name}}/
- onlyif: test ! -f /opt/{{project_name}}/composer.json
install_composer_packages:
cmd.run:
- directory: /opt/{{project_name}}/
- composer: /usr/local/bin/
- cwd: /opt/{{project_name}}/
- name: composer require {% for p in packages %} {{p}} {%endfor%}
#
# End of File
Applying the files
In your server’s highstate file simple add two lines:
- roles.composer.install
- servers.php-test-01.composer-project
The output (ignore the error shown, there is a bug notice raised for it):
[root@salt composer]# salt 'php-test-01*' state.sls server.php-test-01.composer-project
php-test-01.your-domain.test:
----------
ID: /opt/testp
Function: file.directory
Result: True
Comment:
Started: 15:48:17.105881
Duration: 6.239 ms
Changes:
----------
/opt/testp:
----------
directory:
new
----------
ID: testp
Function: cmd.run
Name: composer init
Result: True
Comment: Command "composer init" run
Started: 15:48:17.131304
Duration: 980.136 ms
Changes:
----------
pid:
1279758
retcode:
0
stderr:
Writing ./composer.json
stdout:
----------
ID: install_composer_packages
Function: cmd.run
Name: composer require php-amqplib/php-amqplib monolog/monolog fzaninotto/faker
Result: True
Comment: Command "composer require php-amqplib/php-amqplib monolog/monolog fzaninotto/faker" run
Started: 15:48:18.133930
Duration: 3519.246 ms
Changes:
----------
pid:
1279771
retcode:
0
stderr:
Composer could not detect the root package (root/testp) version, defaulting to '1.0.0'. See https://getcomposer.org/root-version
Cannot use fzaninotto/faker's latest version v1.9.2 as it requires php ^5.3.3 || ^7.0 which is not satisfied by your platform.
./composer.json has been updated
Composer could not detect the root package (root/testp) version, defaulting to '1.0.0'. See https://getcomposer.org/root-version
Running composer update php-amqplib/php-amqplib monolog/monolog fzaninotto/faker
Loading composer repositories with package information
Updating dependencies
Lock file operations: 7 installs, 0 updates, 0 removals
- Locking fzaninotto/faker (v1.5.0)
- Locking monolog/monolog (3.10.0)
- Locking paragonie/constant_time_encoding (v3.1.3)
- Locking paragonie/random_compat (v9.99.100)
- Locking php-amqplib/php-amqplib (v3.7.4)
- Locking phpseclib/phpseclib (3.0.51)
- Locking psr/log (3.0.2)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 7 installs, 0 updates, 0 removals
- Downloading fzaninotto/faker (v1.5.0)
0/1 [>---------------------------] 0%
1/1 [============================] 100%
- Installing fzaninotto/faker (v1.5.0): Extracting archive
- Installing psr/log (3.0.2): Extracting archive
- Installing monolog/monolog (3.10.0): Extracting archive
- Installing paragonie/random_compat (v9.99.100): Extracting archive
- Installing paragonie/constant_time_encoding (v3.1.3): Extracting archive
- Installing phpseclib/phpseclib (3.0.51): Extracting archive
- Installing php-amqplib/php-amqplib (v3.7.4): Extracting archive
0/7 [>---------------------------] 0%
3/7 [============>---------------] 42%
7/7 [============================] 100%
13 package suggestions were added by new dependencies, use `composer suggest` to see details.
Package fzaninotto/faker is abandoned, you should avoid using it. No replacement was suggested.
Generating autoload files
2 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
Using version ^3.7 for php-amqplib/php-amqplib
Using version ^3.10 for monolog/monolog
Using version ^1.5 for fzaninotto/faker
stdout:
Summary for php-test-01.your-domain.test
------------
Succeeded: 3 (changed=3)
Failed: 0
------------
Total states run: 3
Total run time: 4.506 s
Done!
-oOo-