Skip to content

Latest commit

 

History

History
853 lines (559 loc) · 16.5 KB

File metadata and controls

853 lines (559 loc) · 16.5 KB

API Reference

host()

host(string ...$hostname): Host|ObjectProxy

Define one or more hosts for deployment.

host('example.org');
host('prod.example.org', 'staging.example.org');

Inside a task, returns the Host instance for the given alias:

task('test', function () {
    $port = host('example.org')->get('port');
});

localhost()

localhost(string ...$hostnames): Localhost|ObjectProxy

Define a local host. Commands run on the local machine instead of over SSH.

localhost('ci'); // Alias and hostname will be "ci".

currentHost()

currentHost(): Host

Return the host the current task is running on.

task('whoami', function () {
    writeln(currentHost()->getAlias());
});

select()

select(string $selector): array

Return hosts matching a selector expression.

on(select('stage=prod, role=db'), function (Host $host) {
    // Runs on hosts tagged stage=prod AND role=db.
});

selectedHosts()

selectedHosts(): array

Return the hosts the user picked on the command line.

import()

import(string $file): void

Import another recipe (PHP or MAML).

Built-in recipe/* and contrib/* paths are already on PHP's include path, so they can be imported by relative path. Use __DIR__ for files inside your own project.

import('recipe/common.php');                  // built-in recipe
import('contrib/rsync.php');                  // contrib recipe
import(__DIR__ . '/config/hosts.maml');       // local file

desc()

desc(?string $title = null): ?string

Set the description for the next task defined with task().

desc('Restart php-fpm');
task('restart', function () {
    run('sudo systemctl restart php-fpm');
});

Calling desc() with no argument returns the pending description.

task()

task(string $name, callable|array|null $body = null): Task

Define a task, or return an already defined one.

Pass a callback to define a single task:

task('deploy:run', function () {
    run('echo deploying');
});

Pass an array of task names to define a group task:

task('deploy', ['deploy:update_code', 'deploy:vendors', 'deploy:symlink']);

Pass only the name to fetch an existing task:

task('deploy')->desc('Run full deploy');
Argument Type Comment
$name string Task name.
$body callable or array or null Callback, list of task names, or null to fetch an existing task.

before()

before(string $task, string|callable $do): ?Task

Run a task (or callback) before another task.

before('deploy:symlink', 'deploy:cache:warmup');

before('deploy:symlink', function () {
    run('echo about to symlink');
});
Argument Type Comment
$task string Name of the task to attach the hook to.
$do string or callable Task name or callback to run.

after()

after(string $task, string|callable $do): ?Task

Run a task (or callback) after another task.

after('deploy:symlink', 'deploy:cleanup');

after('deploy:failed', function () {
    run('echo something went wrong');
});
Argument Type Comment
$task string Name of the task to attach the hook to.
$do string or callable Task name or callback to run.

fail()

fail(string $task, string|callable $do): ?Task

Run a task (or callback) when another task fails.

Calling fail() again for the same task replaces the previous handler.

fail('deploy', 'deploy:unlock');

fail('deploy', function () {
    run('echo rollback triggered');
});
Argument Type Comment
$task string Name of the task whose failure triggers $do.
$do string or callable Task name or callback to run on failure.

option()

option(string $name, $shortcut = null, ?int $mode = null, string $description = '', $default = null): void

Add a CLI option to the dep binary.

use Symfony\Component\Console\Input\InputOption;

option('tag', null, InputOption::VALUE_REQUIRED, 'Release tag');

task('deploy', function () {
    $tag = input()->getOption('tag');
});
Argument Type Comment
$name string Option name (long form, no leading dashes).
$shortcut string or array or null Single-letter shortcut, `
$mode int or null One of the InputOption::VALUE_* constants.
$description string Help text shown in dep --help.
$default string or string[] or int or bool or null Default value (must be null for VALUE_NONE).

cd()

cd(string $path): void

Change the current working directory.

Both cd() and the cwd: argument of run() change the working directory for executed commands. The difference: cd() changes it for the rest of the current task, while cwd: overrides it for a single run() call only.

set('deploy_path', '~/deployer.org');

task('task1', function () {
    cd('{{deploy_path}}');

    run('pwd');
    // output: /home/deployer/deployer.org

    run('pwd', cwd: '/usr'); // Override working dir for this run only.
    // output: /usr

    run('pwd');
    // output: /home/deployer/deployer.org
});

Note that cd() only changes the working directory within a single task. The next task starts fresh.

task('task2', function () {
    run('pwd'); // cd from previous task is not used.
    // output: /home/deployer
});

task('all', [
   'task1',
   'task2',
]);

become()

become(string $user): \Closure

Switch the user that run() uses for subsequent commands.

Returns a closure that restores the previous user when called.

$restore = become('deployer');
run('whoami'); // deployer
$restore();

within()

within(string $path, callable $callback): mixed

Run a callback inside a working directory, then restore the previous one.

Use this when you need a scoped cd() that does not leak to the rest of the task.

within('{{release_path}}', function () {
    run('composer install');
});

run()

run(
    string  $command,
    ?string $cwd = null,
    ?array  $env = null,
    #[\SensitiveParameter]
    ?array  $secrets = null,
    ?bool   $nothrow = false,
    ?bool   $forceOutput = false,
    ?int    $timeout = null,
    ?int    $idleTimeout = null,
): string 

Run a command on the current remote host and return its trimmed stdout.

run('echo hello world');
run('cd {{deploy_path}} && git status');
run('curl medv.io', timeout: 5);

$path = run('readlink {{deploy_path}}/current');
run("echo $path");

Pass secrets via placeholders (e.g. %token%) so they are redacted in logs:

run('curl -u admin:%token% https://api.example', secrets: ['token' => getenv('TOKEN')]);

Use the | quote filter to escape config values as shell arguments:

run('echo {{ message | quote }}');
run('grep -r {{ pattern | quote }} {{release_path}}');

To emit a literal {{, escape it with a backslash:

run('echo \{{not_replaced}}'); // outputs: {{not_replaced}}
Argument Type Comment
$command string Command to run on the remote host.
$cwd string or null Working directory for this run. Defaults to {{working_path}} (set by cd()).
$timeout int or null Max runtime in seconds (default: {{default_timeout}}, 300; null disables).
$idleTimeout int or null Max seconds without output before aborting.
$secrets array<string, scalar> or null Map of %name% placeholders to redacted values.
$env array<string, scalar> or null Environment variables: run('echo $KEY', env: ['KEY' => 'value']);
$forceOutput bool or null Print command output in real time.
$nothrow bool or null Return output instead of throwing on non-zero exit.

runLocally()

runLocally(
    string  $command,
    ?string $cwd = null,
    ?int    $timeout = null,
    ?int    $idleTimeout = null,
    #[\SensitiveParameter]
    ?array  $secrets = null,
    ?array  $env = null,
    ?bool   $forceOutput = false,
    ?bool   $nothrow = false,
    ?string $shell = null,
): string 

Run a command on the local machine and return its trimmed stdout.

$branch = runLocally('git rev-parse --abbrev-ref HEAD');
runLocally('npm run build', timeout: 600);
Argument Type Comment
$command string Command to run locally.
$cwd string or null Working directory for this run. Defaults to {{working_path}}.
$timeout int or null Max runtime in seconds (default 300, null disables).
$idleTimeout int or null Max seconds without output before aborting.
$secrets array<string, scalar> or null Map of %name% placeholders to redacted values.
$env array<string, scalar> or null Environment variables: runLocally('echo $KEY', env: ['KEY' => 'value']);
$forceOutput bool or null Print command output in real time.
$nothrow bool or null Return output instead of throwing on non-zero exit.
$shell string or null Shell to run in. Default bash -s.

test()

test(string $command): bool

Return whether a shell test command succeeds on the remote host.

if (test('[ -d {{release_path}} ]')) {
    run('rm -rf {{release_path}}');
}

testLocally()

testLocally(string $command): bool

Return whether a shell test command succeeds on the local machine.

if (testLocally('[ -f .env ]')) {
    upload('.env', '{{release_path}}/.env');
}

on()

on($hosts, callable $callback): void

Run a callback on each given host.

on(select('stage=prod, role=db'), function (Host $host) {
    run('mysqldump app > /tmp/backup.sql');
});

on(host('example.org'), function (Host $host) {
    run('uptime');
});

on(Deployer::get()->hosts, function (Host $host) {
    run('uname -a');
});

invoke()

invoke(string $taskName): void

Run another task by name from inside the current task.

task('deploy', function () {
    invoke('deploy:update_code');
    invoke('deploy:symlink');
});

upload()

upload($source, string $destination, array $config = []): void

Upload files or directories to the current host via rsync.

To copy the contents of a directory, end the source with /:

upload('build/', '{{release_path}}/public'); // copies contents of build/
upload('build',  '{{release_path}}/public'); // copies the build/ dir itself

$config keys:

  • flags: replaces the default -azP flags
  • options: extra flags appended to the rsync command
  • timeout: process timeout in seconds (null = no limit)
  • progress_bar: show transfer progress
  • display_stats: show rsync statistics

Note: PHP shell-escaping breaks rsync's --exclude={'a','b'} brace list. Pass each exclude as its own --exclude=... option, or use --exclude-from=<file>.

download()

download(string $source, string $destination, array $config = []): void

Download a file or directory from the current host via rsync.

download('{{deploy_path}}/.dep/database.sql', 'backup/database.sql');

$config accepts the same keys as upload().

info()

info(string $message): void

Print an info message, prefixed with info and the host alias.

info('Deployed release {{release_name}}');

warning()

warning(string $message): void

Print a warning message.

writeln()

writeln(string $message, int $options = 0): void

Write a line to the output, prefixed with the current host alias.

The message is parsed for {{config}} placeholders before printing.

parse()

parse(string $value): string

Replace {{name}} placeholders in a string with values from the current config.

$current = parse('{{deploy_path}}/current');

set()

set(string $name, $value): void

Set a global config value.

set('keep_releases', 5);
set('shared_files', ['.env']);

add()

add(string $name, array $array): void

Append values to an array config option.

add('shared_files', ['.env']);
add('shared_dirs', ['storage/logs']);

get()

get(string $name, $default = null)

Return a config value, or $default if it isn't set.

Callable values are resolved on first access and cached.

$branch = get('branch', 'main');

has()

has(string $name): bool

Return whether a config option is set.

ask()

ask(string $message, ?string $default = null, ?array $autocomplete = null): ?string

Prompt the user for a string, on the current host.

Returns $default in quiet mode (-q).

$branch = ask('Branch to deploy?', 'main');
$tag    = ask('Tag?', null, ['v1.0', 'v1.1', 'v1.2']);

askChoice()

askChoice(string $message, array $availableChoices, $default = null, bool $multiselect = false)

Prompt the user to pick one or more values from a list.

$color = askChoice('Pick a color', ['red', 'green', 'blue'], 0);
Argument Type Comment
$default mixed Key into $availableChoices, or null for no default.

askConfirmation()

askConfirmation(string $message, bool $default = false): bool

Prompt the user with a yes/no question. Returns $default in quiet mode.

if (askConfirmation('Drop the database?')) {
    run('mysql -e "DROP DATABASE app"');
}

askHiddenResponse()

askHiddenResponse(string $message): string

Prompt the user for input without echoing it. Use for passwords and tokens.

input()

input(): InputInterface

Return the Symfony Console input, e.g. to read CLI options.

$tag = input()->getOption('tag');

output()

output(): OutputInterface

Return the Symfony Console output, e.g. to check verbosity.

commandExist()

commandExist(string $command): bool

Return whether a command is available on the current host's PATH.

if (!commandExist('git')) {
    throw error('git is required to deploy');
}

commandSupportsOption()

commandSupportsOption(string $command, string $option): bool

Return whether a command's man page or --help output mentions the given option.

Useful for picking newer flags only when the installed version supports them.

$progress = commandSupportsOption('rsync', '--info=progress2') ? '--info=progress2' : '--progress';

which()

which(string $name): string

Return the absolute path of a command on the current host.

Tries command -v, then which, then type -p.

$php = which('php');
run("$php -v");

remoteEnv()

remoteEnv(): array

Return the remote host's environment as an associative array.

$remotePath = remoteEnv()['PATH'];
run('echo $PATH', env: ['PATH' => "/home/user/bin:$remotePath"]);

error()

error(string $message): Exception

Build a Deployer Exception with {{config}} placeholders parsed in the message.

if (!commandExist('git')) {
    throw error('git is required on {{alias}}');
}

timestamp()

timestamp(): string

Return the current UTC timestamp in ISO 8601 format.

quote()

quote(string|int $arg): string

Quote a string for safe use as a shell argument (ANSI-C $'...' syntax).

Strings made of safe characters (alphanumeric, /.-+@:=,%) are returned unquoted. Throws on null bytes.

run('git log --format=' . quote($format));
run('echo ' . quote("it's a test"));  // echo $'it\'s a test'

fetch()

fetch(string $url, string $method = 'get', array $headers = [], ?string $body = null, ?array &$info = null, bool $nothrow = false): string

Make an HTTP request and return the response body.

Pass $info by reference to capture status code, headers, and timing (same shape as PHP's curl_getinfo). Use nothrow: true to receive the body even on non-2xx responses.

$body = fetch('{{domain}}/health', info: $info);
if ($info['http_code'] !== 200) {
    throw error("health check failed: {$info['http_code']}");
}

fetch('https://api.example.com/notify', 'post',
    ['Authorization' => 'Bearer {{token}}'],
    json_encode(['release' => '{{release_name}}']),
);