instituteweb / deployer-scripts
PHP deployer scripts (deployer.org) to build local and deploy remote iw_master TYPO3 distribution.
Requires
- deployer/deployer: ^4.0
- league/flysystem: ^1.0
- league/flysystem-sftp: ^1.0
- symfony/process: ^3.2
README
These Deployer Scripts contains build and deployment scripts for the task runner PHP Deployer. All tasks are system independent (unix/windows) and are highly configurable.
The scripts are originally made for TYPO3 CMS and the distribution iw_master. But you can deploy any application you want with these scripts, as well.
It's an early version currently, I'm happy about feedback and contributions Thanks :)
Key feature: league/flysystem
One cool thing of these Deployer Scripts is the awesome package league/flysystem which allows you to perform file operations via SSH, FTP, on the local machine and some more.
Deployer Scripts provides the functions files()
and filesLocally()
in your tasks, which get
initialized automatically with the current server's configuration of deployer.
Installation
Just add instituteweb/deployer-scripts to your composer project:
$ composer require instituteweb/deployer-scripts
This will also install deployer/deployer in your project.
Global installation
I can recommend to install PHP deployer globally and add vendor/bin directory in your home directory, to PATH variable.
$ composer global require instituteweb/deployer-scripts
In examples below I always write $ dep ...
, assuming you also got it globally installed. If not, you need to write
$ bin/dep
(iw_master) or $ vendor/bin/dep
(composer default)... depending on your composer.json config (bin-dir).
Configuration
PHP Deployer provides a pretty nice Environment handling, which allows us to set variables globally or for each environment individually. The build and deploy configuration happens in deploy.php file in root of your project.
You need to include the common script of deployer-scripts. In common script all available tasks are included.
<?php
namespace Deployer;
require 'vendor/instituteweb/deployer-scripts/src/common.php';
// deployer.php kickstart template
If you have no experience with it, checkout the chapter tasks in documentation of Deployer.
General configuration parameters
Used binaries, like php, git, composer or unzip can have different calls on different environments.
<?php
set('bin/php', get('bin/php') ?: getenv('PHP_BIN') ?: 'php');
set('bin/git', get('bin/git') ?: getenv('GIT_BIN') ?: 'git');
set('bin/composer', get('bin/composer') ?: getenv('COMPOSER_BIN') ?: 'composer');
Many file operations are working well with flysystem, but some not. Removing and copying whole directories and
creating symlinks are such things. They use vsprintf()
.
<?php
// File operations (unix)
set('bin/unzip', 'unzip -qo "%s" -d "%s"');
set('bin/rm', 'rm -rf %s');
set('bin/cp', 'cp -rf "%s" "%s"');
set('bin/symlink', 'ln -nfs %s %s');
set('bin/symlink-file', get('bin/symlink'));
For windows systems you can use these commands:
<?php
// File operations (windows)
set('bin/rm', 'del /S /Q "%s"');
set('bin/cp', 'copy /Y /L "%s" "%s"');
set('bin/symlink', 'mklink /D %2$s %1$s');
set('bin/symlink-file', 'mklink %2$s %1$s');
There are more configuration parameters, but they are used for building or deploying. You find them below in related section.
Build Scripts
Before we can deploy the project, we need to create a build. Deployer Scripts compresses all files to zip archive, which can get deployed easily.
To create a build just call
$ dep build
- Create configured build directory (Default: ../.build, because git in git is not possible)
- Update code using git. We define branch/tag or specific revision (default is master branch)
- Well, here we can execute frontend related stuff, like npm, bower and grunt/gulp. No composer here, this should be executed on the system it run (because of symlinks and write/execution flags)
- Create the zip archive based on checked out and prepared release
- Clear and remove checked out folder. Done.
This zip file is now able to get deployed.
Build and deploy can get called separately. If you want to execute it at once, you also can call
$ dep build-deploy
Build config
build_dir
String. Folder to use for building the release. Relative from current working directory (cwd).
May not be already under git versioning. Default: ../.builds
archive_list
Array. Key is path of directory and value path of zip file to create with contents of given key directory.
Default set('archive_list', ['{{build_path}}' => '{{build_dir}}/{{short_revision}}.zip']);
git_repository
String. Path to your repository. You can also apply repos via SSH and access private repositories. Default: null
git_branch
String. Branch or tag (both possible) to checkout. Default: master
build_directory (readonly)
Returns absolute build_dir path.
build_path (readonly)
Returns absolute build_dir path with appended build_name.
build_name (readonly)
Returns build_name. If --name option is given it returns this value. Otherwise it takes the git_target value.
git_target (readonly)
Returns the given git_target. Default is master
. You can influence this option with --branch or --tag option, or with
--revision option. Revision is also the first argument. You can call dep build-deploy 76b5410
revision (readonly)
Returns the current git revision. Just available after build:update_code task or if revision is already given by command line.
short_revision (readonly)
Same like revision, but returns just the first seven digits of commit hash.
Deployment Scripts
This is an example structure of a deployed TYPO3 project:
/html/typo3
├── .dep
│ └── releases.json
├── current -> releases/76b5410
├── releases
│ └── b2ff764
│ └── 1b61ee9
│ └── f9e80f1
│ └── e7059d1
│ └── 76b5410
└── shared
├── .env
└── web
└── fileadmin
└── typo3temp
└── uploads
To keep downtime very small during update and give you the possibility to roll to an earlier version back, in case of heavy bugs after deploy, we work with releases (like Deployer itself does). Each deploy is a new release.
What happens during a deploy:
$ dep deploy --revision 76b5410
- Prepare initial folder structure on remote(s) on very first time
- Lock deployer (to avoid parallel executions)
- Upload zip file (76b5410.zip), which contains the build, to /releases
- Extract the zip file to /releases/76b5410 (configurable, default: the git commit hash in short)
- Perform composer install within the new release
- Moves configured shared files and folders to /shared directory, deletes them in e.g. /releases/76b5410 and create instead symlinks to the shared folders
- Rollout the release, which switches /current symlink to new release
- Perform composer run post-update-cmd which performs TYPO3 tasks (update db schema, clear cache, ...)
- Unlock deployer. We are done :)
Deploy config
composer_action
String. The command of composer which should be executed on server. Usually install or update. Default: install
composer_options
String. Append options to composer to use, when get executed on remote machine.
Default: {{composer_action}} --prefer-dist --no-progress --no-suggest --no-interaction --no-dev --optimize-autoloader
release_name
String. The name of the release. Default {{build_name}}
release_path
String. Path on remote to upload and extract release to. Default: {{deploy_path}}/releases/{{release_name}}
max_release_cycle
Integer. Amount of release to remain on remote system. Default: 5
use_symlink_for_current
Boolean. If true the /current directory, which is used by webserver (htdocs), is a symlink. If provider is not
supporting symlinks here, you can disable the option. The current folder gets copied then, from release. Default: true
upload_list
Array. Key is local source file and value is remote destination. File get uploaded. And if zip file it get also
extracted into a folder, named like the zip archive. Default:
['{{build_dir}}/{{short_revision}}.zip' => '{{deploy_path}}/releases/{{release_name}}.zip']
directory_permissions
Integer. Unix directory permissions. Used for SSH connections (on remotes) only. Default: 0755
Rollback
In case you need to roll back to a previous version you can do that, with:
$ dep rollback [to]
You can set to argument to release name. By default it rolls back to previous release.
All releases are stored in .dep/release.json file. To show available release names use dep list-releases
.
Run scripts
You can run a full deploy with this command:
$ dep build-deploy [stage] [--revision]
$ dep build [stage] [--revision|--branch|--name]
$ dep deploy [stage] [--revision]
Argument revision is for deploy required and expects a {{revision}}.zip
file in build_dir.
Arguments and options
stage argument
Run tasks only on this server or group of servers.
--revision
Specify a certain commit to build and release.
--tag or --branch
Does both the same. Sets tag or branch.
--name
Set the build name (which is also release name).
--force
If set the .lock file on remote is ignored. Use this just in case your previous deployment failed.
Convenience tasks
To see the local builds and the remote releases (including which is the current one) you can use these commands:
$ dep list-builds
➤ Executing task list-builds
Found builds in "C:\Dev\.builds":
- bbc2760
✔ Ok
$ dep list-releases
➤ Executing task list-releases
Max release cycle count: 5
Found releases on "production":
#0
Name: bbc2760
Path: /html/releases/bbc2760
Date: Sun, 15 Jan 2017 21:35:20 +0100
#1
Name: bbc2760_7
Path: /html/releases/bbc2760_7
Date: Sun, 15 Jan 2017 21:40:07 +0100
#2
Name: bbc2760_8
Path: /html/releases/bbc2760_8
Date: Sun, 15 Jan 2017 21:44:34 +0100
#3
Name: bbc2760_9
Path: /html/releases/bbc2760_9
Date: Sun, 15 Jan 2017 21:44:52 +0100
#10 +++ CURRENT RELEASE! +++
Name: bbc2760_10
Path: /html/releases/bbc2760_10
Date: Fri, 20 Jan 2017 13:26:57 +0100
✔ Ok
Notice: This happens (_7, _8, etc.) when you upload the same build multiple times.