Deployment hooks enable services to program and gate their deployments. This is often used for testing but can also be used for things like deploying static assets to a CDN or building other types of automation into a deployment.
Hooks are Dockerfiles meaning hook authors can choose any language or runtime.
Hooks can be referenced in 2 ways:
- By specifying the
dockerfile
for the hook - By specifying a git
repo
to be cloned, aref
to be checked out, anddockerfile
to be built and run. These are called plugins.
All hooks are optional and will only be called if they exist. If they exist they must exit with a code of 0 to continue the deployment. Any non-zero exit code is considered a failure and will halt whatever command was called that caused the hook to be called. Exceptions to the rule can be configured via run conditions.
There are currently 9 hooks porter defines. 8 of them are used during the 4 build phases (pre and post), the other is used to customize EC2 initialization.
The pre
and post
hooks are tied to the porter build ...
command names, not
the underlying mechanisms of provisioning, promoting, etc.
- pre-pack
- post-pack
- pre-provision
- post-provision
- pre-promote
- post-promote
- pre-prune
- post-prune
- ec2-bootstrap
A hook named other than one of above is a user defined hook. The internal
structure is the same as any other hook. A user-defined hook is never
automatically called by porter. It can only be called by the
porter build hook
command.
Example
hooks:
alert_the_operator:
- dockerfile: path/to/Dockerfile
repo: https://github.com/person/repo.git
ref: v1.0.0
This hook might be run by a build system as such:
porter build hook -name alert_the_operator -e Stage
Multiple of each hook can be run. They are run in the order defined unless configured to run concurrently.
Each hook's Docker context is the directory containing the hook.
The repo's root is volume mapped to /repo_root
so hooks can access and mutate
the contents of a repo.
Environment variables are injected as they are available.
See the config reference for more.
These are available to all hooks and provided by porter.
PORTER_SERVICE_NAME
PORTER_SERVICE_VERSION (git sha)
DOCKER_ENV_FILE
HAPROXY_STATS_USERNAME
HAPROXY_STATS_PASSWORD
HAPROXY_STATS_URL
You can whitelist what environment each hook receives with the same semantics as Docker Compose
This is a pre_pack hook with FOO
set to bar
, and BAZ
set to the value of
BAZ
when porter is run.
hooks:
pre_pack:
- dockerfile: path/to/Dockerfile
environment:
FOO: bar
BAZ:
Single hooks are hardly sufficient for non-trivial projects. Porter enables
hooks to be developed independently and referenced by porter projects in
.porter/config
.
Plugins are porter hooks that live in a separate repo.
Plugins can run as part of more than one hook. By default porter looks for a
dockerfile
value in the hook config. If this isn't found it defaults to
Dockerfile
. Here is an example config for a made up plugin called
porter-contrib-foo that runs for both pre_pack
and post_pack
, and a
porter-contrib-bar that contains a single Dockerfile at its root (to illustrate
the behavior).
hooks:
pre_pack:
- repo: [email protected]:adobe-platform/porter-contrib-foo.git
ref: v1.0.0
dockerfile: pre-pack
post_pack:
- repo: [email protected]:adobe-platform/porter-contrib-foo.git
ref: v1.0.0
dockerfile: post-pack
- repo: [email protected]:adobe-platform/porter-contrib-bar.git
ref: v1.0.0
# This is the default if undefined
# dockerfile: Dockerfile
pre-pack
and post-pack
are Dockerfiles found in the root directory of the
porter-contrib-foo repo. There's no restriction on the name or placement of
these Dockerfiles (i.e. pre-pack
could also have been some_dir/Dockerfile
)
meaning a single repo could contain many hooks.
When to use a pre hook vs a post hook is determined by what build command you want the hook to operate as part of.
For example, post-provision
and pre-promote
aren't very different. The state
of the deployment hasn't changed and all of the same variables are available.
The only difference is that post-provision
is called during porter build provision
, while pre-promote
is called during porter build promote
.
That difference is probably only meaningful if these commands are run on different boxes, with different environment variables, or are otherwise logically separate from the caller's perspective.
The recommendation is to use pre hooks and then add or change to post hooks as hooks are better understood or requirements dictate.
For post-pack, post-provision, and post-promote, and post-prune you can set run
conditions so that these hooks may run regardless of failure in the command they
run after. The implicit run condition is run_condition: pass
which means the
hook will only be run only if the build step passed.
Additional options are run_condition: fail
and run_condition: always
which
be run only on failure, and always, respectively.
Failure is defined as the underlying command failing meaning if a pre-pack
hooks fails, the packaging never takes place and post-pack
is not called even
with a run_condition: fail
or run_condition: always
. If pre-pack
succeeds
or is undefined and packaging fails, then all post-pack
hooks with
run_condition: fail
or run_condition: always
are run.
The intent of run_condition
is to allow scripts that may have altered some
state in a pre-*
hook to be able to clean up if something goes wrong.