Skip to content

Latest commit

 

History

History
185 lines (140 loc) · 6.2 KB

deployment-hooks.md

File metadata and controls

185 lines (140 loc) · 6.2 KB

Deployment hooks

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:

  1. By specifying the dockerfile for the hook
  2. By specifying a git repo to be cloned, a ref to be checked out, and dockerfile 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.

The hooks

User-defined hooks

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

Execution order

Multiple of each hook can be run. They are run in the order defined unless configured to run concurrently.

Hook environment

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.

Standard environment variables

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

Custom environment variables

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:

Plugins

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.

pre hook vs. post hook

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.

Run conditions

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.