instituteweb/deployer-scripts

PHP deployer scripts (deployer.org) to build local and deploy remote iw_master TYPO3 distribution.

1.3.1 2017-02-15 13:24 UTC

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
  1. Create configured build directory (Default: ../.build, because git in git is not possible)
  2. Update code using git. We define branch/tag or specific revision (default is master branch)
  3. 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)
  4. Create the zip archive based on checked out and prepared release
  5. 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
  1. Prepare initial folder structure on remote(s) on very first time
  2. Lock deployer (to avoid parallel executions)
  3. Upload zip file (76b5410.zip), which contains the build, to /releases
  4. Extract the zip file to /releases/76b5410 (configurable, default: the git commit hash in short)
  5. Perform composer install within the new release
  6. Moves configured shared files and folders to /shared directory, deletes them in e.g. /releases/76b5410 and create instead symlinks to the shared folders
  7. Rollout the release, which switches /current symlink to new release
  8. Perform composer run post-update-cmd which performs TYPO3 tasks (update db schema, clear cache, ...)
  9. 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.