Actions
Actions were introduced in 0.13
and are the basic building blocks of a Garden project. They are usually the first thing you add after creating the project configuration.
Motivation
Before we dive in, let's consider what's involved in building and testing an app that runs on Kubernetes—in a realistic way, like people typically do in their CI pipelines.
First, we build a Docker image from source.
Then we deploy the app to a Kubernetes cluster using a deployment tool like kubectl
or helm
. We also deploy any dependencies the app may require, like databases.
Next, we may need to run some scripts to load the database with a schema and some test data.
Finally, we run all our test suites. Some of these (e.g. unit tests) don't require our services to be running, but others (like end-to-end tests) require several services to be running first.
This sequence of steps (some of which can be run in parallel) boils down to a set of actions that need to be run in dependency order: Builds, Deploys, Tests and Runs (the last of which refers to glue steps, like the one for seeding the DB).
The same applies to large systems with tens or even hundreds of services. The only difference is that the dependency graph is correspondingly larger.
Garden is all about making your workweek more fun and productive by capturing this executable graph of actions.
Action kinds
There are four different kinds of actions in Garden.
Each of them is generic, and has several implementations in Garden via its built-in plugins.
For example, helm
Deploys (i.e. those with type: helm
in their configuration) deploy a Helm chart to a Kubernetes cluster, exec
Deploys start a local process (a great fit for local development), and terraform
Deploys apply a Terraform stack.
The four action kinds in Garden are:
Build
actions, e.g. to build a Docker image or to run a local build script.Deploy
actions to deploy a service, e.g. a Kubernetes Deployment, Helm chart or Terraform stack.For those of you who have been using Garden for a while: These correspond to services in 0.12.
Run
actions for arbitrary scripts, e.g. to perform stateful operations (load test data into databases), download tools or any other miscellaneous steps.These correspond to tasks in 0.12.
Test
actions to test components, e.g. run unit tests, end-to-end tests or any other test suite you may have defined.
Below is a sample of the action configurations for the API service in the vote-helm
example project:
How it Works
A Garden project is usually split up into the project-level config file and several action config files (which usually sit next to their corresponding Dockerfile/Helm chart/Terraform stack/script etc.).
Filenames ending with .garden.yml
will be picked up by Garden. For example, you might prefer to set the application name in the filename, e.g. application-a.actions.garden.yml
to make it easier to find in a large project.
Alternatively, you can have the actions grouped by kind
in a dedicated config file, i.e. deploy-actions.garden.yml
, test-actions.garden.yml
, and so on.
Another option is to have each action defined in a separate configuration file. It might be not convenient if you have a large number of actions in your project.
Read the sections below for more information on configuring actions, including how to control which files and directories are included in a single action.
Action types
Each kind
of action must have a type. Different action types behave in different ways.
Garden is pluggable and features a number of action types. You can find all of them and their full reference documentation here, but we'll provide a high-level overview of the most commonly used types below.
Generally, we recommend using the same deployment tools you use in CI or in production. That way, you can get up and running with Garden more easily, and also minimize the difference between your Garden environment and your production environment.
kubernetes action types use Kubernetes manifests for Deploys, Tests and Runs. These support Kustomize out of the box. Use these actions when you prefer the more lightweight deployment approach of using Kubernetes manifests directly, which is a valid alternative to the Helm chart-based
helm
actions.helm action type allow you to deploy your own Helm charts, or 3rd-party charts from remote repositories. Helm is a powerful tool, especially when deploying 3rd-party (or otherwise external) charts. You can also make your own charts, but we recommend only doing so when you need its flexible templating capabilities, or if you aim to publish the charts.
exec
actions offer a flexible way to weave in arbitrary scripts and commands that are executed locally. These can be custom build steps, unit tests, scripts, tests or really anything else. The caveat is that they always run on the same machine as the Garden CLI, and not e.g. in a Kubernetes cluster, and thus not quite as portable. See the reference guide for theexec
Build, Deploy, Test and Run actions for more details.container action type is a high level and portable way to describe how container images are both built and deployed. When working with containers you'll at least use this to build the images, but you may also specify
Deploy
,Run
andTest
actions on them. Thekubernetes
providers, for example, can take these service definitions, generate Kubernetes manifests and deploy them. This is generally much easier to use than the belowkubernetes
andhelm
action types, but in turn loses some flexibility of those two.terraform offer a powerful way to deploy any cloud resources as part of your project. See the Terraform guide for more information.
There are several other action types available as well. See the action types reference for a full list of supported action types, and their configuration reference.
Including and excluding files
By default, all files in the same directory as an action configuration file are included as source files for that action. Sometimes you need more granular control over the context, not least if you have multiple actions in the same directory.
The include
and exclude
fields are used to explicitly specify which sources should belong to a particular action. Both of them accept a list of POSIX-style paths or globs. For example:
Generally, using .gardenignore
files is far more performant than exclude config statements and will decrease graph resolution time. Read more about .gardenignore
files in the configuration-overview documentation
Here we only include the Dockerfile
and all the .py
files under my-sources/
, but exclude the my-sources/tmp
directory.
If you specify a list with include
, only those files/patterns are included. If you then specify one or more exclude
files or patterns, those are filtered out of the files matched by include
. If you only specify exclude
, those patterns will be filtered out of all files in the action directory.
Note that the action include
and exclude
fields have no effect on which paths Garden watches for changes. Use the project scan.exclude
field for that purpose.
You can also use .gardenignore file, much like .gitignore
files, to exclude files across your project. You can place them in your project root, in action roots, and even in individual sub-directories of actions.
Note that you must use the include
and/or exclude
directives (described above) when action paths overlap. This is to help users steer away from subtle bugs that can occur when actions unintentionally consume source files from other actions. See the next section for details on including and excluding files.
Differences in exclude behavior between the repo
and subtree
Git scan modes when no include is configured
repo
and subtree
Git scan modes when no include is configuredThis section is only relevant for users who have set scan.git.mode
to subtree
in their project config.
Garden supports two modes for scanning Git repositories (and any submodules) for files:
repo
(the default): Scans entire repositories and then filters down to files matching the paths, includes and excludes for each action/module. This can be considerably more efficient than thesubtree
mode for large projects with many actions/modules.subtree
(legacy): This was Garden's scan algoithm before therepo
scan mode was introduced. This method runs individualgit
scans on each action/module path.
When no includes are configured in the module/action config but there are one or more excludes in the config, the subtree
mode will interpret all exclude paths as globs. For example, excluding foo.txt
would also exclude dir/foo.txt
(and any path that contains the string foo.txt
).
This is because the subtree
scan mode uses the --exclude
flag of git ls-files
under the hood for perfomance reasons. Note that this only happens when no includes are specified, and only when using the subtree
scan mode (which needs to be explicitly set in the project config).
We're leaving this inconsistency with the older subtree
mode in place to avoid breaking changes to the Garden configs of users with older projects whose include/exclude configs rely on the exclude semantics of the subtree
mode as is.
The newer repo
mode doesn't have this inconsistency, since it uses a different method to compute the file list for an action/module.
Actions in the Stack Graph
The key concept and the main benefit of having actions instead of modules is that anything can depend on anything.
Some prior constraints, that have tripped people up in the past, have been dropped. A dependency is then specified as <kind>.<name>
, e.g. build.my-image
or deploy.my-deploy
. There will still be some specific semantics for different types of dependencies, but quite a bit simpler than before (which was often difficult to reason about as well).
Examples
In this section we consider a few very basic examples with configuration code-snippets. See more examples on our GitHub repository.
Container Build action
Below is the configuration for a simple container Build
action. Here we're assuming that the Dockerfile
and source files are in the same directory as the garden.yml
file.
Multiple Actions in the Same File
In this example, we declare multiple container Build
actions in the same file. We use the include
directive to tell Garden where the source code for each action resides.
Container Build Action with a Remote Image
In this example, we use the image
directive to include an external Docker image with the project. This action has no source code of its own.
Advanced
Disabling Actions
You can disable actions by setting disabled: true
in the action config file. You can also disable it conditionally using template strings. For example, to disable a particular action for a specific environment, you could do something like this:
If a disabled action is referenced as a build dependency of another action it will still be executed to ensure the dependant action can be built as expected.
Disabled actions are skipped with other action kinds and dependency declarations to them are ignored. Template strings referencing runtime outputs will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for them using conditional expressions.
See the disabled-config example for more details.
Further Reading
Next Steps
Take a look at our Workflows section to learn how to define sequences of Garden commands and custom scripts.
Last updated