Buildkite Agent Hooks

Hooks extend or override the built-in behaviours of the Buildkite Agent and Bootstrap binaries.

Hooks can be defined in three locations: agent-wide, your pipeline’s repository, or in plugins applied to steps. For example, you could define an agent wide checkout hook which speeds up a fresh git clone on a new build machine, a repository pre-command hook which sets up repository-specific environment variables, or a plugin environment hook which fetches API keys from a secrets storage service.

There are two categories of hook:

  • Agent Lifecycle
  • Job Lifecycle

Agent lifecycle hooks are executed by the Buildkite Agent as part of the agent’s lifecycle. For example, the pre-bootstrap hook is executed before starting a job’s bootstrap process, and the agent-shutdown hook is executed before the agent process terminates.

Job lifecycle hooks are sourced by the Buildkite Bootstrap in the different job phases. They are run in a per-job shell environment, and any exported environment variables are carried to the job’s subsequent phases and hooks. For example, the environment hook can modify or export new environment variables for the job’s subsequent checkout and command phases.

In August 2021 we changed how we refer to Agent Hooks to differentiate between the hooks feature for both the Agent and Bootstrap processes, and the agent hooks-path configuration for the directory that agent level hooks are defined.

Agent lifecycle hooks

Hook Location Order Description
pre-bootstrap Agent

Executed before any job is started. Useful for adding strict checks before jobs are permitted to run.

The proposed job command and environment is written to a file and the path to this file provided in the BUILDKITE_ENV_FILE environment variable. Use the contents of this file to determine whether to permit the job to run on this agent.

If the pre-bootstrap hook terminates with an exit code of 0, the job is permitted to run. Any other exit code results in the job being rejected, and job failure being reported to the Buildkite API.

agent-shutdown Agent Executed when the agent shuts down. Useful for performing cleanup tasks for the entire agent, outside of the job lifecycle.

Creating agent lifecycle hooks

Agent lifecycle hooks can be written in the programming language of your choice and are executed by the Buildkite Agent. See the documentation for each agent lifecycle hook for details on the interface between them and the Buildkite Agent.

These hooks can only be defined in the agent hooks-path directory.

Job lifecycle hooks

The following is a complete list of available job hooks, and the order in which they are run as part of each job:

Hook Location Order Description
environment Agent, Plugin Runs before all other hooks. Useful for exposing secret keys.
pre-checkout Agent, Plugin Runs before checkout.
checkout Plugin, Agent Overrides the default git checkout behavior.
Note: As of Agent v3.15.0, if multiple checkout hooks are found, only the first will be run.
post-checkout Agent, Repository, Plugin Runs after checkout.
pre-command Agent, Repository, Plugin Runs before the build command.
command Plugin, Repository, Agent Overrides the default command running behavior. If multiple command hooks are found, only the first will be run.
post-command Agent, Repository, Plugin Runs after the command.
pre-artifact Agent, Repository, Plugin Runs before artifacts are uploaded, if an artifact upload pattern was defined for the job.
post-artifact Agent, Repository, Plugin Runs after artifacts have been uploaded, if an artifact upload pattern was defined for the job.
pre-exit Agent, Repository, Plugin Runs before the job finishes. Useful for performing cleanup tasks.

Creating job lifecycle hooks

Job lifecycle hooks run for every job an agent accepts. They are shell scripts you can use to run commands and export environment variables. These hooks have access to all the standard Buildkite environment variables.

Job lifecycle hooks are copied to $TMPDIR directory and sourced by the agent’s default shell. This has a few implications:

  • $BASH_SOURCE contains the location the hook is sourced from
  • $0 contains the location of the copy of the script that is running from $TMPDIR
  • the shebang line of the hook script has no effect

To write job lifecycle hooks in another programming language, you need to execute them from within the shell script, and explicitly pass any Buildkite environment variables you need to the script when you call it.

The following is an example of an environment hook which exports a GitHub API key for the pipeline’s release build step:

set -eu
echo '--- :house_with_garden: Setting up the environment'

export GITHUB_RELEASE_ACCESS_KEY='xxx'

Job hooks on Windows

Buildkite defaults to using the Batch shell on Windows. Buildkite agents running on Windows require that either:

  • The hooks files have a .bat extension, and be written in Windows Batch, or
  • The agent shell option points to the PowerShell or PowerShell Core executable, and the hooks files are written in PowerShell. PowerShell hooks are supported in Buildkite agent version 3.32.3 and above.

An example of a Windows environment.bat hook:

@ECHO OFF
ECHO "--- :house_with_garden: Setting up the environment"
SET GITHUB_RELEASE_ACCESS_KEY='xxx'

Hook Locations

Hooks can be defined in three locations:

  • Agent hooks - these exist on the agent file system in a directory created by your agent installer and configured by the hooks-path setting. You can define both agent lifecycle and job lifecycle hooks in the agent hooks location. Job lifecycle hooks defined here will be run for every job the agent receives, from any pipeline.
  • Repository hooks - these exist in your pipeline repository’s .buildkite/hooks directory and can define job lifecycle hooks. Job lifecycle hooks defined here will be run for every pipeline that uses the repository.
  • Plugin hooks - these are provided by any plugins you’ve included in your pipeline steps and can define job lifecycle hooks. Job lifecycle hooks defined by a plugin will only be run for the step that includes them.

Agent hooks

Every agent installer creates a hooks directory containing a set of sample hooks. You can find the location of your agent hooks directory in your platform’s installation documentation.

To get started with agent hooks copy the relevant example script and remove the .sample file extension.

See agent lifecycle hooks and job lifecycle hooks for the hook types that can be defined in the agent hooks directory.

Repository hooks

Repository hooks allow you to execute repository-specific scripts. Repository hooks live alongside your repository’s source code under the .buildkite/hooks directory.

To get started, create a shell script in .buildkite/hooks named post-checkout. It will be sourced and run after your repository has been checked out as part of every job for any pipeline that uses this repository.

You can define any of the job lifecycle hooks whose Order includes Repository.

Plugin hooks

Plugin hooks allow plugins you’ve defined in your Pipeline Steps to override default behavior.

See the plugin documentation for how to implement plugin hooks and job lifecycle hooks for the list of hook types that a plugin can define.