Deployment Commands
commands (and rollback_commands) run in the new release directory, in order, before the atomic switchover. Each entry needs a name and a run:
commands:
- name: Install dependencies
run: composer install --no-dev --optimize-autoloader
- name: Database migrations
run: ./vendor/bin/typo3 upgrade:runINFO
Because they run before the current symlink moves, a failing command means the release never goes live — see Deployment Process.
Scoping a command to specific hosts
By default a command runs for every host in hosts:. Use only / except (GitLab-CI style) to scope a single command instead of duplicating the whole command list per host:
commands:
- name: Database migrations
run: ./vendor/bin/typo3 upgrade:run
# Only run this command for the listed host(s) (keys under `hosts:`).
# Skipped everywhere else. Omit `only`/`except` entirely to run on every host.
only:
- production
- name: Notify monitoring
run: /usr/local/bin/notify-deploy
# except is the inverse of only: runs everywhere except the listed hosts.
except:
- stagingonlyandexceptaccept a list of host names (the keys underhosts:).- If a host matches both,
exceptwins. - Commands skipped for a host are logged as skipped during
deploy/rollback. shippy config validaterejectsonly/exceptentries that reference a host name not defined underhosts:.shippy config show <host>lists only the commands that actually apply to that host;shippy config validateannotates every command with its resolved scope.
Running commands inside a container
If your PHP sources are mounted into a container, command_context runs every command inside a subcontext instead of directly on the remote host. When set, Shippy executes each command as:
<command_context> sh -c 'cd <release-dir> && <run>'Shippy adds sh -c itself — give only the container-entry prefix, without a trailing shell (docker exec php85, not docker exec php85 bash). The cd happens inside the context, so the release directory must resolve to the same path there (the normal bind-mount case, e.g. /var/www:/var/www).
command_context can be set globally, per host, or per command — the most specific one wins:
# Global default for every host and command (optional; empty = run directly on the host)
command_context: docker exec -u www-data php85
hosts:
production:
hostname: example.com
remote_user: deploy
command_context: docker exec php84 # Overrides the global default for this host
commands:
- name: Notify monitoring
run: /usr/local/bin/notify-deploy
# Per-command override. An empty string forces this command to run
# directly on the host even when a global/per-host context is set.
command_context: ""Precedence: per-command > per-host (hosts.<name>.command_context) > global command_context.
Checking what will run
shippy config show <host> prints the effective command list for one host, with commands filtered out by only/except shown as comments:
shippy config show production